From abe509a3b16be0707ace12abd4cabf3dc28a007d Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 2 Apr 2019 13:18:17 +0100 Subject: [PATCH] Use TAR instead of DOCKER build type before 6.7.0 (#40723) In 6.7.0 (#39378) we added a build type of DOCKER for the docker images, but unfortunately earlier versions do not understand this and will reject any transport messages that mention this build type. This commit fixes this by reporting TAR instead of DOCKER when talking to older nodes. Relates (but does not fix) #40511 Relates #39378 --- .../main/java/org/elasticsearch/Build.java | 8 +- .../java/org/elasticsearch/BuildTests.java | 107 ++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/Build.java b/server/src/main/java/org/elasticsearch/Build.java index 6f33775023d96..6598b7a0a449e 100644 --- a/server/src/main/java/org/elasticsearch/Build.java +++ b/server/src/main/java/org/elasticsearch/Build.java @@ -219,7 +219,13 @@ public static void writeBuild(Build build, StreamOutput out) throws IOException out.writeString(build.flavor().displayName()); } if (out.getVersion().onOrAfter(Version.V_6_3_0)) { - out.writeString(build.type().displayName()); + final Type buildType; + if (out.getVersion().before(Version.V_6_7_0) && build.type() == Type.DOCKER) { + buildType = Type.TAR; + } else { + buildType = build.type(); + } + out.writeString(buildType.displayName()); } out.writeString(build.shortHash()); out.writeString(build.date()); diff --git a/server/src/test/java/org/elasticsearch/BuildTests.java b/server/src/test/java/org/elasticsearch/BuildTests.java index c2b0f3acb941d..fdb1cabc6bcc1 100644 --- a/server/src/test/java/org/elasticsearch/BuildTests.java +++ b/server/src/test/java/org/elasticsearch/BuildTests.java @@ -20,15 +20,23 @@ package org.elasticsearch; import org.elasticsearch.common.io.FileSystemUtils; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.EqualsHashCodeTestUtils; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Arrays; +import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import static org.hamcrest.Matchers.equalTo; + public class BuildTests extends ESTestCase { /** Asking for the jar metadata should not throw exception in tests, no matter how configured */ @@ -69,4 +77,103 @@ public void testEqualsAndHashCode() { Build differentSnapshot = new Build(build.flavor(), build.type(), build.shortHash(), build.date(), !build.isSnapshot()); assertNotEquals(build, differentSnapshot); } + + private static class WriteableBuild implements Writeable { + private final Build build; + + WriteableBuild(StreamInput in) throws IOException { + build = Build.readBuild(in); + } + + WriteableBuild(Build build) { + this.build = build; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + Build.writeBuild(build, out); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WriteableBuild that = (WriteableBuild) o; + return build.equals(that.build); + } + + @Override + public int hashCode() { + return Objects.hash(build); + } + } + + private static String randomStringExcept(final String s) { + return randomAlphaOfLength(13 - s.length()); + } + + public void testSerialization() { + EqualsHashCodeTestUtils.checkEqualsAndHashCode(new WriteableBuild(new Build( + randomFrom(Build.Flavor.values()), randomFrom(Build.Type.values()), + randomAlphaOfLength(6), randomAlphaOfLength(6), randomBoolean(), randomAlphaOfLength(6))), + b -> copyWriteable(b, writableRegistry(), WriteableBuild::new, Version.CURRENT), + b -> { + switch (randomIntBetween(1, 6)) { + case 1: + return new WriteableBuild(new Build( + randomValueOtherThan(b.build.flavor(), () -> randomFrom(Build.Flavor.values())), b.build.type(), + b.build.shortHash(), b.build.date(), b.build.isSnapshot(), b.build.getQualifiedVersion())); + case 2: + return new WriteableBuild(new Build(b.build.flavor(), + randomValueOtherThan(b.build.type(), () -> randomFrom(Build.Type.values())), + b.build.shortHash(), b.build.date(), b.build.isSnapshot(), b.build.getQualifiedVersion())); + case 3: + return new WriteableBuild(new Build(b.build.flavor(), b.build.type(), + randomStringExcept(b.build.shortHash()), b.build.date(), b.build.isSnapshot(), b.build.getQualifiedVersion())); + case 4: + return new WriteableBuild(new Build(b.build.flavor(), b.build.type(), + b.build.shortHash(), randomStringExcept(b.build.date()), b.build.isSnapshot(), b.build.getQualifiedVersion())); + case 5: + return new WriteableBuild(new Build(b.build.flavor(), b.build.type(), + b.build.shortHash(), b.build.date(), b.build.isSnapshot() == false, b.build.getQualifiedVersion())); + case 6: + return new WriteableBuild(new Build(b.build.flavor(), b.build.type(), + b.build.shortHash(), b.build.date(), b.build.isSnapshot(), randomStringExcept(b.build.getQualifiedVersion()))); + } + throw new AssertionError(); + }); + } + + public void testSerializationBWC() throws IOException { + final WriteableBuild dockerBuild = new WriteableBuild(new Build(randomFrom(Build.Flavor.values()), Build.Type.DOCKER, + randomAlphaOfLength(6), randomAlphaOfLength(6), randomBoolean(), randomAlphaOfLength(6))); + + final List versions = Version.getDeclaredVersions(Version.class); + final Version pre63Version = randomFrom(versions.stream().filter(v -> v.before(Version.V_6_3_0)).collect(Collectors.toList())); + final Version post63Pre67Version = randomFrom(versions.stream() + .filter(v -> v.onOrAfter(Version.V_6_3_0) && v.before(Version.V_6_7_0)).collect(Collectors.toList())); + final Version post67Pre70Version = randomFrom(versions.stream() + .filter(v -> v.onOrAfter(Version.V_6_7_0) && v.before(Version.V_7_0_0)).collect(Collectors.toList())); + final Version post70Version = randomFrom(versions.stream().filter(v -> v.onOrAfter(Version.V_7_0_0)).collect(Collectors.toList())); + + final WriteableBuild pre63 = copyWriteable(dockerBuild, writableRegistry(), WriteableBuild::new, pre63Version); + final WriteableBuild post63pre67 = copyWriteable(dockerBuild, writableRegistry(), WriteableBuild::new, post63Pre67Version); + final WriteableBuild post67pre70 = copyWriteable(dockerBuild, writableRegistry(), WriteableBuild::new, post67Pre70Version); + final WriteableBuild post70 = copyWriteable(dockerBuild, writableRegistry(), WriteableBuild::new, post70Version); + + assertThat(pre63.build.flavor(), equalTo(Build.Flavor.OSS)); + assertThat(post63pre67.build.flavor(), equalTo(dockerBuild.build.flavor())); + assertThat(post67pre70.build.flavor(), equalTo(dockerBuild.build.flavor())); + assertThat(post70.build.flavor(), equalTo(dockerBuild.build.flavor())); + + assertThat(pre63.build.type(), equalTo(Build.Type.UNKNOWN)); + assertThat(post63pre67.build.type(), equalTo(Build.Type.TAR)); + assertThat(post67pre70.build.type(), equalTo(dockerBuild.build.type())); + assertThat(post70.build.type(), equalTo(dockerBuild.build.type())); + + assertThat(pre63.build.getQualifiedVersion(), equalTo(pre63Version.toString())); + assertThat(post63pre67.build.getQualifiedVersion(), equalTo(post63Pre67Version.toString())); + assertThat(post67pre70.build.getQualifiedVersion(), equalTo(post67Pre70Version.toString())); + assertThat(post70.build.getQualifiedVersion(), equalTo(dockerBuild.build.getQualifiedVersion())); + } }