Skip to content

Commit eea927f

Browse files
committed
Enable installing plugins from snapshots.elastic.co (#30765)
We post snapshot builds to snapshots.elastic.co yet the official plugin installer will not let you install such plugins without manually downloading them and installing them from a file URL. This commit adds the ability for the plugin installer to use snapshots.elastic.co for installing official plugins if a es.plugins.staging is set and the current build is also a snapshot build. Otherwise, we continue to use staging.elastic.co if the current build is a release build and es.plugins.staging is set and, of course, use the release artifacts at artifacts.elastic.co for release builds with es.plugins.staging unset.
1 parent 05c7787 commit eea927f

File tree

2 files changed

+87
-24
lines changed

2 files changed

+87
-24
lines changed

distribution/tools/plugin-cli/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.elasticsearch.cli.ExitCodes;
3131
import org.elasticsearch.cli.Terminal;
3232
import org.elasticsearch.cli.UserException;
33-
import org.elasticsearch.common.Strings;
3433
import org.elasticsearch.common.SuppressForbidden;
3534
import org.elasticsearch.common.collect.Tuple;
3635
import org.elasticsearch.common.hash.MessageDigests;
@@ -240,7 +239,7 @@ private static void handleInstallXPack(final Build.Flavor flavor) throws UserExc
240239
/** Downloads the plugin and returns the file it was downloaded to. */
241240
private Path download(Terminal terminal, String pluginId, Path tmpDir) throws Exception {
242241
if (OFFICIAL_PLUGINS.contains(pluginId)) {
243-
final String url = getElasticUrl(terminal, getStagingHash(), Version.CURRENT, pluginId, Platforms.PLATFORM_NAME);
242+
final String url = getElasticUrl(terminal, getStagingHash(), Version.CURRENT, isSnapshot(), pluginId, Platforms.PLATFORM_NAME);
244243
terminal.println("-> Downloading " + pluginId + " from elastic");
245244
return downloadZipAndChecksum(terminal, url, tmpDir, false);
246245
}
@@ -272,22 +271,43 @@ String getStagingHash() {
272271
return System.getProperty(PROPERTY_STAGING_ID);
273272
}
274273

274+
boolean isSnapshot() {
275+
return Build.CURRENT.isSnapshot();
276+
}
277+
275278
/** Returns the url for an official elasticsearch plugin. */
276-
private String getElasticUrl(Terminal terminal, String stagingHash, Version version,
277-
String pluginId, String platform) throws IOException {
279+
private String getElasticUrl(
280+
final Terminal terminal,
281+
final String stagingHash,
282+
final Version version,
283+
final boolean isSnapshot,
284+
final String pluginId,
285+
final String platform) throws IOException, UserException {
278286
final String baseUrl;
287+
if (isSnapshot && stagingHash == null) {
288+
throw new UserException(
289+
ExitCodes.CONFIG, "attempted to install release build of official plugin on snapshot build of Elasticsearch");
290+
}
279291
if (stagingHash != null) {
280-
baseUrl = String.format(Locale.ROOT,
281-
"https://staging.elastic.co/%s-%s/downloads/elasticsearch-plugins/%s", version, stagingHash, pluginId);
292+
if (isSnapshot) {
293+
baseUrl = nonReleaseUrl("snapshots", version, stagingHash, pluginId);
294+
} else {
295+
baseUrl = nonReleaseUrl("staging", version, stagingHash, pluginId);
296+
}
282297
} else {
283-
baseUrl = String.format(Locale.ROOT,
284-
"https://artifacts.elastic.co/downloads/elasticsearch-plugins/%s", pluginId);
298+
baseUrl = String.format(Locale.ROOT, "https://artifacts.elastic.co/downloads/elasticsearch-plugins/%s", pluginId);
285299
}
286-
final String platformUrl = String.format(Locale.ROOT, "%s/%s-%s-%s.zip", baseUrl, pluginId, platform, version);
300+
final String platformUrl =
301+
String.format(Locale.ROOT, "%s/%s-%s-%s.zip", baseUrl, pluginId, platform, Version.displayVersion(version, isSnapshot));
287302
if (urlExists(terminal, platformUrl)) {
288303
return platformUrl;
289304
}
290-
return String.format(Locale.ROOT, "%s/%s-%s.zip", baseUrl, pluginId, version);
305+
return String.format(Locale.ROOT, "%s/%s-%s.zip", baseUrl, pluginId, Version.displayVersion(version, isSnapshot));
306+
}
307+
308+
private String nonReleaseUrl(final String hostname, final Version version, final String stagingHash, final String pluginId) {
309+
return String.format(
310+
Locale.ROOT, "https://%s.elastic.co/%s-%s/downloads/elasticsearch-plugins/%s", hostname, version, stagingHash, pluginId);
291311
}
292312

293313
/** Returns the url for an elasticsearch plugin in maven. */

distribution/tools/plugin-cli/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ private void installPlugin(MockTerminal terminal, boolean isBatch) throws Except
800800
skipJarHellCommand.execute(terminal, pluginZip, isBatch, env.v2());
801801
}
802802

803-
void assertInstallPluginFromUrl(String pluginId, String name, String url, String stagingHash,
803+
void assertInstallPluginFromUrl(String pluginId, String name, String url, String stagingHash, boolean isSnapshot,
804804
String shaExtension, Function<byte[], String> shaCalculator) throws Exception {
805805
Tuple<Path, Environment> env = createEnv(fs, temp);
806806
Path pluginDir = createPluginDir(temp);
@@ -834,6 +834,12 @@ boolean urlExists(Terminal terminal, String urlString) throws IOException {
834834
String getStagingHash() {
835835
return stagingHash;
836836
}
837+
838+
@Override
839+
boolean isSnapshot() {
840+
return isSnapshot;
841+
}
842+
837843
@Override
838844
void jarHellCheck(PluginInfo candidateInfo, Path candidate, Path pluginsDir, Path modulesDir) throws Exception {
839845
// no jarhell check
@@ -843,64 +849,98 @@ void jarHellCheck(PluginInfo candidateInfo, Path candidate, Path pluginsDir, Pat
843849
assertPlugin(name, pluginDir, env.v2());
844850
}
845851

846-
public void assertInstallPluginFromUrl(String pluginId, String name, String url, String stagingHash) throws Exception {
852+
public void assertInstallPluginFromUrl(
853+
final String pluginId, final String name, final String url, final String stagingHash, boolean isSnapshot) throws Exception {
847854
MessageDigest digest = MessageDigest.getInstance("SHA-512");
848-
assertInstallPluginFromUrl(pluginId, name, url, stagingHash, ".sha512", checksumAndFilename(digest, url));
855+
assertInstallPluginFromUrl(pluginId, name, url, stagingHash, isSnapshot, ".sha512", checksumAndFilename(digest, url));
849856
}
850857

851858
public void testOfficalPlugin() throws Exception {
852859
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + Version.CURRENT + ".zip";
853-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null);
860+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false);
861+
}
862+
863+
public void testOfficialPluginSnapshot() throws Exception {
864+
String url = String.format(
865+
Locale.ROOT,
866+
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip",
867+
Version.CURRENT,
868+
Version.displayVersion(Version.CURRENT, true));
869+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true);
870+
}
871+
872+
public void testInstallReleaseBuildOfPluginOnSnapshotBuild() {
873+
String url = String.format(
874+
Locale.ROOT,
875+
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s.zip",
876+
Version.CURRENT,
877+
Version.displayVersion(Version.CURRENT, true));
878+
// attemping to install a release build of a plugin (no staging ID) on a snapshot build should throw a user exception
879+
final UserException e =
880+
expectThrows(UserException.class, () -> assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, true));
881+
assertThat(e.exitCode, equalTo(ExitCodes.CONFIG));
882+
assertThat(
883+
e, hasToString(containsString("attempted to install release build of official plugin on snapshot build of Elasticsearch")));
854884
}
855885

856886
public void testOfficalPluginStaging() throws Exception {
857887
String url = "https://staging.elastic.co/" + Version.CURRENT + "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
858888
+ Version.CURRENT + ".zip";
859-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123");
889+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false);
860890
}
861891

862892
public void testOfficalPlatformPlugin() throws Exception {
863893
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + Platforms.PLATFORM_NAME +
864894
"-" + Version.CURRENT + ".zip";
865-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null);
895+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false);
896+
}
897+
898+
public void testOfficialPlatformPluginSnapshot() throws Exception {
899+
String url = String.format(
900+
Locale.ROOT,
901+
"https://snapshots.elastic.co/%s-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-%s-%s.zip",
902+
Version.CURRENT,
903+
Platforms.PLATFORM_NAME,
904+
Version.displayVersion(Version.CURRENT, true));
905+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", true);
866906
}
867907

868908
public void testOfficalPlatformPluginStaging() throws Exception {
869909
String url = "https://staging.elastic.co/" + Version.CURRENT + "-abc123/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-"
870910
+ Platforms.PLATFORM_NAME + "-"+ Version.CURRENT + ".zip";
871-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123");
911+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, "abc123", false);
872912
}
873913

874914
public void testMavenPlugin() throws Exception {
875915
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
876-
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null);
916+
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, false);
877917
}
878918

879919
public void testMavenPlatformPlugin() throws Exception {
880920
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-" + Platforms.PLATFORM_NAME + "-1.0.0.zip";
881-
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null);
921+
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, false);
882922
}
883923

884924
public void testMavenSha1Backcompat() throws Exception {
885925
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
886926
MessageDigest digest = MessageDigest.getInstance("SHA-1");
887-
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, ".sha1", checksum(digest));
927+
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, false, ".sha1", checksum(digest));
888928
assertTrue(terminal.getOutput(), terminal.getOutput().contains("sha512 not found, falling back to sha1"));
889929
}
890930

891931
public void testOfficialShaMissing() throws Exception {
892932
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + Version.CURRENT + ".zip";
893933
MessageDigest digest = MessageDigest.getInstance("SHA-1");
894934
UserException e = expectThrows(UserException.class, () ->
895-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, ".sha1", checksum(digest)));
935+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false, ".sha1", checksum(digest)));
896936
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
897937
assertEquals("Plugin checksum missing: " + url + ".sha512", e.getMessage());
898938
}
899939

900940
public void testMavenShaMissing() throws Exception {
901941
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
902942
UserException e = expectThrows(UserException.class, () ->
903-
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, ".dne", bytes -> null));
943+
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, false, ".dne", bytes -> null));
904944
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
905945
assertEquals("Plugin checksum missing: " + url + ".sha1", e.getMessage());
906946
}
@@ -909,7 +949,7 @@ public void testInvalidShaFileMissingFilename() throws Exception {
909949
String url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-" + Version.CURRENT + ".zip";
910950
MessageDigest digest = MessageDigest.getInstance("SHA-512");
911951
UserException e = expectThrows(UserException.class, () ->
912-
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, ".sha512", checksum(digest)));
952+
assertInstallPluginFromUrl("analysis-icu", "analysis-icu", url, null, false, ".sha512", checksum(digest)));
913953
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
914954
assertTrue(e.getMessage(), e.getMessage().startsWith("Invalid checksum file"));
915955
}
@@ -923,6 +963,7 @@ public void testInvalidShaFileMismatchFilename() throws Exception {
923963
"analysis-icu",
924964
url,
925965
null,
966+
false,
926967
".sha512",
927968
checksumAndString(digest, " repository-s3-" + Version.CURRENT + ".zip")));
928969
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
@@ -938,6 +979,7 @@ public void testInvalidShaFileContainingExtraLine() throws Exception {
938979
"analysis-icu",
939980
url,
940981
null,
982+
false,
941983
".sha512",
942984
checksumAndString(digest, " analysis-icu-" + Version.CURRENT + ".zip\nfoobar")));
943985
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
@@ -952,6 +994,7 @@ public void testSha512Mismatch() throws Exception {
952994
"analysis-icu",
953995
url,
954996
null,
997+
false,
955998
".sha512",
956999
bytes -> "foobar analysis-icu-" + Version.CURRENT + ".zip"));
9571000
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
@@ -961,7 +1004,7 @@ public void testSha512Mismatch() throws Exception {
9611004
public void testSha1Mismatch() throws Exception {
9621005
String url = "https://repo1.maven.org/maven2/mygroup/myplugin/1.0.0/myplugin-1.0.0.zip";
9631006
UserException e = expectThrows(UserException.class, () ->
964-
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, ".sha1", bytes -> "foobar"));
1007+
assertInstallPluginFromUrl("mygroup:myplugin:1.0.0", "myplugin", url, null, false, ".sha1", bytes -> "foobar"));
9651008
assertEquals(ExitCodes.IO_ERROR, e.exitCode);
9661009
assertTrue(e.getMessage(), e.getMessage().contains("SHA-1 mismatch, expected foobar"));
9671010
}

0 commit comments

Comments
 (0)