Skip to content

Commit cdb2d41

Browse files
author
Christoph Büscher
committed
Merge branch 'master' into reloadable-analyzers-feature
2 parents ab24a04 + 5fa36da commit cdb2d41

File tree

1,174 files changed

+37703
-11683
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,174 files changed

+37703
-11683
lines changed

buildSrc/src/main/java/org/elasticsearch/gradle/BwcVersions.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,19 @@ public BwcVersions(List<String> versionLines) {
109109
}
110110

111111
protected BwcVersions(List<String> versionLines, Version currentVersionProperty) {
112-
SortedSet<Version> allVersions = versionLines.stream()
112+
this(versionLines.stream()
113113
.map(LINE_PATTERN::matcher)
114114
.filter(Matcher::matches)
115115
.map(match -> new Version(
116116
Integer.parseInt(match.group(1)),
117117
Integer.parseInt(match.group(2)),
118118
Integer.parseInt(match.group(3))
119119
))
120-
.collect(Collectors.toCollection(TreeSet::new));
120+
.collect(Collectors.toCollection(TreeSet::new)), currentVersionProperty);
121+
}
121122

123+
// for testkit tests, until BwcVersions is extracted into an extension
124+
public BwcVersions(SortedSet<Version> allVersions, Version currentVersionProperty) {
122125
if (allVersions.isEmpty()) {
123126
throw new IllegalArgumentException("Could not parse any versions");
124127
}
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.gradle;
21+
22+
import org.elasticsearch.gradle.ElasticsearchDistribution.Flavor;
23+
import org.elasticsearch.gradle.ElasticsearchDistribution.Platform;
24+
import org.elasticsearch.gradle.ElasticsearchDistribution.Type;
25+
import org.gradle.api.GradleException;
26+
import org.gradle.api.NamedDomainObjectContainer;
27+
import org.gradle.api.Plugin;
28+
import org.gradle.api.Project;
29+
import org.gradle.api.UnknownTaskException;
30+
import org.gradle.api.artifacts.Configuration;
31+
import org.gradle.api.artifacts.ConfigurationContainer;
32+
import org.gradle.api.artifacts.Dependency;
33+
import org.gradle.api.artifacts.dsl.DependencyHandler;
34+
import org.gradle.api.artifacts.repositories.IvyArtifactRepository;
35+
import org.gradle.api.credentials.HttpHeaderCredentials;
36+
import org.gradle.api.file.FileTree;
37+
import org.gradle.api.plugins.ExtraPropertiesExtension;
38+
import org.gradle.api.tasks.Sync;
39+
import org.gradle.api.tasks.TaskProvider;
40+
import org.gradle.authentication.http.HttpHeaderAuthentication;
41+
42+
import java.io.File;
43+
import java.util.HashMap;
44+
import java.util.Locale;
45+
import java.util.Map;
46+
import java.util.concurrent.Callable;
47+
import java.util.function.Supplier;
48+
49+
/**
50+
* A plugin to manage getting and extracting distributions of Elasticsearch.
51+
*
52+
* The source of the distribution could be from a local snapshot, a locally built
53+
* bwc snapshot, or the Elastic downloads service.
54+
*/
55+
public class DistributionDownloadPlugin implements Plugin<Project> {
56+
57+
private static final String FAKE_IVY_GROUP = "elasticsearch-distribution";
58+
private static final String DOWNLOAD_REPO_NAME = "elasticsearch-downloads";
59+
60+
private BwcVersions bwcVersions;
61+
private NamedDomainObjectContainer<ElasticsearchDistribution> distributionsContainer;
62+
63+
@Override
64+
public void apply(Project project) {
65+
distributionsContainer = project.container(ElasticsearchDistribution.class, name -> {
66+
Configuration fileConfiguration = project.getConfigurations().create("es_distro_file_" + name);
67+
Configuration extractedConfiguration = project.getConfigurations().create("es_distro_extracted_" + name);
68+
return new ElasticsearchDistribution(name, project.getObjects(), fileConfiguration, extractedConfiguration);
69+
});
70+
project.getExtensions().add("elasticsearch_distributions", distributionsContainer);
71+
72+
setupDownloadServiceRepo(project);
73+
74+
ExtraPropertiesExtension extraProperties = project.getExtensions().getExtraProperties();
75+
this.bwcVersions = (BwcVersions) extraProperties.get("bwcVersions");
76+
// TODO: setup snapshot dependency instead of pointing to bwc distribution projects for external projects
77+
78+
project.afterEvaluate(this::setupDistributions);
79+
}
80+
81+
// pkg private for tests
82+
void setupDistributions(Project project) {
83+
for (ElasticsearchDistribution distribution : distributionsContainer) {
84+
distribution.finalizeValues();
85+
86+
DependencyHandler dependencies = project.getDependencies();
87+
// for the distribution as a file, just depend on the artifact directly
88+
dependencies.add(distribution.configuration.getName(), dependencyNotation(project, distribution));
89+
90+
// no extraction allowed for rpm or deb
91+
if (distribution.getType() != Type.RPM && distribution.getType() != Type.DEB) {
92+
// for the distribution extracted, add a root level task that does the extraction, and depend on that
93+
// extracted configuration as an artifact consisting of the extracted distribution directory
94+
dependencies.add(distribution.getExtracted().configuration.getName(),
95+
projectDependency(project, ":", configName("extracted_elasticsearch", distribution)));
96+
// ensure a root level download task exists
97+
setupRootDownload(project.getRootProject(), distribution);
98+
}
99+
}
100+
}
101+
102+
private void setupRootDownload(Project rootProject, ElasticsearchDistribution distribution) {
103+
String extractTaskName = extractTaskName(distribution);
104+
// NOTE: this is *horrendous*, but seems to be the only way to check for the existence of a registered task
105+
try {
106+
rootProject.getTasks().named(extractTaskName);
107+
// already setup this version
108+
return;
109+
} catch (UnknownTaskException e) {
110+
// fall through: register the task
111+
}
112+
setupDownloadServiceRepo(rootProject);
113+
114+
final ConfigurationContainer configurations = rootProject.getConfigurations();
115+
String downloadConfigName = configName("elasticsearch", distribution);
116+
String extractedConfigName = "extracted_" + downloadConfigName;
117+
final Configuration downloadConfig = configurations.create(downloadConfigName);
118+
configurations.create(extractedConfigName);
119+
rootProject.getDependencies().add(downloadConfigName, dependencyNotation(rootProject, distribution));
120+
121+
// add task for extraction, delaying resolving config until runtime
122+
if (distribution.getType() == Type.ARCHIVE || distribution.getType() == Type.INTEG_TEST_ZIP) {
123+
Supplier<File> archiveGetter = downloadConfig::getSingleFile;
124+
String extractDir = rootProject.getBuildDir().toPath().resolve("elasticsearch-distros").resolve(extractedConfigName).toString();
125+
TaskProvider<Sync> extractTask = rootProject.getTasks().register(extractTaskName, Sync.class, syncTask -> {
126+
syncTask.dependsOn(downloadConfig);
127+
syncTask.into(extractDir);
128+
syncTask.from((Callable<FileTree>)() -> {
129+
File archiveFile = archiveGetter.get();
130+
String archivePath = archiveFile.toString();
131+
if (archivePath.endsWith(".zip")) {
132+
return rootProject.zipTree(archiveFile);
133+
} else if (archivePath.endsWith(".tar.gz")) {
134+
return rootProject.tarTree(rootProject.getResources().gzip(archiveFile));
135+
}
136+
throw new IllegalStateException("unexpected file extension on [" + archivePath + "]");
137+
});
138+
});
139+
rootProject.getArtifacts().add(extractedConfigName,
140+
rootProject.getLayout().getProjectDirectory().dir(extractDir),
141+
artifact -> artifact.builtBy(extractTask));
142+
}
143+
}
144+
145+
private static void setupDownloadServiceRepo(Project project) {
146+
if (project.getRepositories().findByName(DOWNLOAD_REPO_NAME) != null) {
147+
return;
148+
}
149+
project.getRepositories().ivy(ivyRepo -> {
150+
ivyRepo.setName(DOWNLOAD_REPO_NAME);
151+
ivyRepo.setUrl("https://artifacts.elastic.co");
152+
ivyRepo.metadataSources(IvyArtifactRepository.MetadataSources::artifact);
153+
// this header is not a credential but we hack the capability to send this header to avoid polluting our download stats
154+
ivyRepo.credentials(HttpHeaderCredentials.class, creds -> {
155+
creds.setName("X-Elastic-No-KPI");
156+
creds.setValue("1");
157+
});
158+
ivyRepo.getAuthentication().create("header", HttpHeaderAuthentication.class);
159+
ivyRepo.patternLayout(layout -> layout.artifact("/downloads/elasticsearch/[module]-[revision](-[classifier]).[ext]"));
160+
ivyRepo.content(content -> content.includeGroup(FAKE_IVY_GROUP));
161+
});
162+
project.getRepositories().all(repo -> {
163+
if (repo.getName().equals(DOWNLOAD_REPO_NAME) == false) {
164+
// all other repos should ignore the special group name
165+
repo.content(content -> content.excludeGroup(FAKE_IVY_GROUP));
166+
}
167+
});
168+
// TODO: need maven repo just for integ-test-zip, but only in external cases
169+
}
170+
171+
/**
172+
* Returns a dependency object representing the given distribution.
173+
*
174+
* The returned object is suitable to be passed to {@link DependencyHandler}.
175+
* The concrete type of the object will either be a project {@link Dependency} or
176+
* a set of maven coordinates as a {@link String}. Project dependencies point to
177+
* a project in the Elasticsearch repo either under `:distribution:bwc`,
178+
* `:distribution:archives` or :distribution:packages`. Maven coordinates point to
179+
* either the integ-test-zip coordinates on maven central, or a set of artificial
180+
* coordinates that resolve to the Elastic download service through an ivy repository.
181+
*/
182+
private Object dependencyNotation(Project project, ElasticsearchDistribution distribution) {
183+
184+
if (Version.fromString(VersionProperties.getElasticsearch()).equals(distribution.getVersion())) {
185+
return projectDependency(project, distributionProjectPath(distribution), "default");
186+
// TODO: snapshot dep when not in ES repo
187+
}
188+
BwcVersions.UnreleasedVersionInfo unreleasedInfo = bwcVersions.unreleasedInfo(distribution.getVersion());
189+
if (unreleasedInfo != null) {
190+
assert distribution.getBundledJdk();
191+
return projectDependency(project, unreleasedInfo.gradleProjectPath, distributionProjectName(distribution));
192+
}
193+
194+
if (distribution.getType() == Type.INTEG_TEST_ZIP) {
195+
return "org.elasticsearch.distribution.integ-test-zip:elasticsearch:" + distribution.getVersion();
196+
}
197+
198+
String extension = distribution.getType().toString();
199+
String classifier = "x86_64";
200+
if (distribution.getType() == Type.ARCHIVE) {
201+
extension = distribution.getPlatform() == Platform.WINDOWS ? "zip" : "tar.gz";
202+
classifier = distribution.getPlatform() + "-" + classifier;
203+
}
204+
return FAKE_IVY_GROUP + ":elasticsearch" + (distribution.getFlavor() == Flavor.OSS ? "-oss:" : ":")
205+
+ distribution.getVersion() + ":" + classifier + "@" + extension;
206+
}
207+
208+
private static Dependency projectDependency(Project project, String projectPath, String projectConfig) {
209+
210+
if (project.findProject(projectPath) == null) {
211+
throw new GradleException("no project [" + projectPath + "], project names: " + project.getRootProject().getAllprojects());
212+
}
213+
Map<String, Object> depConfig = new HashMap<>();
214+
depConfig.put("path", projectPath);
215+
depConfig.put("configuration", projectConfig);
216+
return project.getDependencies().project(depConfig);
217+
}
218+
219+
private static String distributionProjectPath(ElasticsearchDistribution distribution) {
220+
String projectPath = ":distribution";
221+
if (distribution.getType() == Type.INTEG_TEST_ZIP) {
222+
projectPath += ":archives:integ-test-zip";
223+
} else {
224+
projectPath += distribution.getType() == Type.ARCHIVE ? ":archives:" : ":packages:";
225+
projectPath += distributionProjectName(distribution);
226+
}
227+
return projectPath;
228+
}
229+
230+
private static String distributionProjectName(ElasticsearchDistribution distribution) {
231+
String projectName = "";
232+
if (distribution.getFlavor() == Flavor.OSS) {
233+
projectName += "oss-";
234+
}
235+
if (distribution.getBundledJdk() == false) {
236+
projectName += "no-jdk-";
237+
}
238+
if (distribution.getType() == Type.ARCHIVE) {
239+
Platform platform = distribution.getPlatform();
240+
projectName += platform.toString() + (platform == Platform.WINDOWS ? "-zip" : "-tar");
241+
} else {
242+
projectName += distribution.getType();
243+
}
244+
return projectName;
245+
}
246+
247+
private static String configName(String prefix, ElasticsearchDistribution distribution) {
248+
return prefix + "_" + distribution.getVersion() + "_" + distribution.getType() + "_" +
249+
(distribution.getPlatform() == null ? "" : distribution.getPlatform() + "_")
250+
+ distribution.getFlavor() + (distribution.getBundledJdk() ? "" : "_nojdk");
251+
}
252+
253+
private static String capitalize(String s) {
254+
return s.substring(0, 1).toUpperCase(Locale.ROOT) + s.substring(1);
255+
}
256+
257+
private static String extractTaskName(ElasticsearchDistribution distribution) {
258+
String taskName = "extractElasticsearch";
259+
if (distribution.getType() != Type.INTEG_TEST_ZIP) {
260+
if (distribution.getFlavor() == Flavor.OSS) {
261+
taskName += "Oss";
262+
}
263+
if (distribution.getBundledJdk() == false) {
264+
taskName += "NoJdk";
265+
}
266+
}
267+
if (distribution.getType() == Type.ARCHIVE) {
268+
taskName += capitalize(distribution.getPlatform().toString());
269+
} else if (distribution.getType() != Type.INTEG_TEST_ZIP) {
270+
taskName += capitalize(distribution.getType().toString());
271+
}
272+
taskName += distribution.getVersion();
273+
return taskName;
274+
}
275+
}

0 commit comments

Comments
 (0)