From 2ff0bddbfb2816a51b6fb42e113a084e80db1f53 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 dcf827091f54e..be37c56837d70 100644 --- a/server/src/main/java/org/elasticsearch/Build.java +++ b/server/src/main/java/org/elasticsearch/Build.java @@ -241,7 +241,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 1f99a1f4542b5..12af1d31841cf 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 */ @@ -115,4 +123,103 @@ public void testEqualsAndHashCode() { ); assertNotEquals(build, differentVersion); } + + 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())); + } }