Skip to content

Commit 32eada6

Browse files
Introduce minimumCompatibilityVersion to BuildVersion (ES-9378) (#119101)
1 parent 39c4eda commit 32eada6

File tree

12 files changed

+81
-77
lines changed

12 files changed

+81
-77
lines changed

server/src/main/java/org/elasticsearch/ReleaseVersions.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
package org.elasticsearch;
1111

1212
import org.elasticsearch.common.Strings;
13-
import org.elasticsearch.core.UpdateForV9;
13+
import org.elasticsearch.core.UpdateForV10;
1414
import org.elasticsearch.internal.BuildExtension;
1515
import org.elasticsearch.plugins.ExtensionLoader;
1616

@@ -114,8 +114,7 @@ private static IntFunction<String> lookupFunction(NavigableMap<Integer, List<Ver
114114
// this will no longer be the case with ES 10 (which won't know about ES v8.x where we introduced separated versions)
115115
// maybe keep the release mapping around in the csv file?
116116
// SEP for now
117-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
118-
// @UpdateForV10(owner = UpdateForV10.Owner.CORE_INFRA)
117+
@UpdateForV10(owner = UpdateForV10.Owner.CORE_INFRA)
119118
Version oldVersion = Version.fromId(id);
120119
return oldVersion.toString();
121120
}

server/src/main/java/org/elasticsearch/Version.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
import org.elasticsearch.common.io.stream.StreamInput;
1515
import org.elasticsearch.common.io.stream.StreamOutput;
1616
import org.elasticsearch.core.Assertions;
17+
import org.elasticsearch.core.RestApiVersion;
1718
import org.elasticsearch.core.SuppressForbidden;
18-
import org.elasticsearch.core.UpdateForV9;
1919
import org.elasticsearch.monitor.jvm.JvmInfo;
2020
import org.elasticsearch.xcontent.ToXContentFragment;
2121
import org.elasticsearch.xcontent.XContentBuilder;
@@ -242,17 +242,15 @@ public class Version implements VersionId<Version>, ToXContentFragment {
242242
VERSION_STRINGS = Map.copyOf(builderByString);
243243
}
244244

245-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
246-
// Re-enable this assertion once the rest api version is bumped
247245
private static void assertRestApiVersion() {
248-
// assert RestApiVersion.current().major == CURRENT.major && RestApiVersion.previous().major == CURRENT.major - 1
249-
// : "RestApiVersion must be upgraded "
250-
// + "to reflect major from Version.CURRENT ["
251-
// + CURRENT.major
252-
// + "]"
253-
// + " but is still set to ["
254-
// + RestApiVersion.current().major
255-
// + "]";
246+
assert RestApiVersion.current().major == CURRENT.major && RestApiVersion.previous().major == CURRENT.major - 1
247+
: "RestApiVersion must be upgraded "
248+
+ "to reflect major from Version.CURRENT ["
249+
+ CURRENT.major
250+
+ "]"
251+
+ " but is still set to ["
252+
+ RestApiVersion.current().major
253+
+ "]";
256254
}
257255

258256
public static Version readVersion(StreamInput in) throws IOException {

server/src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import org.elasticsearch.common.xcontent.ChunkedToXContentHelper;
4848
import org.elasticsearch.core.Nullable;
4949
import org.elasticsearch.core.SuppressForbidden;
50-
import org.elasticsearch.core.UpdateForV9;
5150
import org.elasticsearch.index.shard.IndexLongFieldRange;
5251
import org.elasticsearch.indices.SystemIndexDescriptor;
5352
import org.elasticsearch.xcontent.ToXContent;
@@ -1039,12 +1038,6 @@ public static ClusterState readFrom(StreamInput in, DiscoveryNode localNode) thr
10391038
return builder.build();
10401039
}
10411040

1042-
/**
1043-
* If the cluster state does not contain transport version information, this is the version
1044-
* that is inferred for all nodes on version 8.8.0 or above.
1045-
*/
1046-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
1047-
public static final TransportVersion INFERRED_TRANSPORT_VERSION = TransportVersions.V_8_8_0;
10481041
public static final Version VERSION_INTRODUCING_TRANSPORT_VERSIONS = Version.V_8_8_0;
10491042

10501043
@Override

server/src/main/java/org/elasticsearch/env/BuildVersion.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ public abstract class BuildVersion implements ToXContentFragment, Writeable {
7373
*/
7474
public abstract String toNodeMetadata();
7575

76+
/**
77+
* Returns the minimum compatible build version based on the current version.
78+
* Ie a node needs to have at least the return version in order to communicate with a node running the current version.
79+
*/
80+
public abstract BuildVersion minimumCompatibilityVersion();
81+
7682
/**
7783
* Create a {@link BuildVersion} from a version ID number.
7884
*

server/src/main/java/org/elasticsearch/env/DefaultBuildVersion.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ public String toNodeMetadata() {
7373
return Integer.toString(version.id());
7474
}
7575

76+
@Override
77+
public BuildVersion minimumCompatibilityVersion() {
78+
return fromVersionId(version.minimumCompatibilityVersion().id);
79+
}
80+
7681
@Override
7782
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
7883
return builder.value(version.id());

server/src/main/java/org/elasticsearch/env/NodeEnvironment.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@
8686
import java.util.function.Consumer;
8787
import java.util.function.Function;
8888
import java.util.function.Predicate;
89-
import java.util.regex.Matcher;
90-
import java.util.regex.Pattern;
9189
import java.util.stream.Collectors;
9290
import java.util.stream.Stream;
9391

@@ -525,7 +523,7 @@ static void checkForIndexCompatibility(Logger logger, DataPath... dataPaths) thr
525523
logger.info("oldest index version recorded in NodeMetadata {}", metadata.oldestIndexVersion());
526524

527525
if (metadata.oldestIndexVersion().before(IndexVersions.MINIMUM_COMPATIBLE)) {
528-
String bestDowngradeVersion = getBestDowngradeVersion(metadata.previousNodeVersion().toString());
526+
BuildVersion bestDowngradeVersion = getBestDowngradeVersion(metadata.previousNodeVersion());
529527
throw new IllegalStateException(
530528
"Cannot start this node because it holds metadata for indices with version ["
531529
+ metadata.oldestIndexVersion().toReleaseVersion()
@@ -1504,28 +1502,17 @@ private static void tryWriteTempFile(Path path) throws IOException {
15041502
/**
15051503
* Get a useful version string to direct a user's downgrade operation
15061504
*
1507-
* <p>If a user is trying to install 8.0 but has incompatible indices, the user should
1508-
* downgrade to 7.17.x. We return 7.17.0, unless the user is trying to upgrade from
1509-
* a 7.17.x release, in which case we return the last installed version.
1505+
* <p>If a user is trying to install current major N but has incompatible indices, the user should
1506+
* downgrade to last minor of the previous major (N-1).last. We return (N-1).last, unless the user is trying to upgrade from
1507+
* a (N-1).last.x release, in which case we return the last installed version.
15101508
* @return Version to downgrade to
15111509
*/
15121510
// visible for testing
1513-
static String getBestDowngradeVersion(String previousNodeVersion) {
1514-
// this method should only be called in the context of an upgrade to 8.x
1515-
assert Build.current().version().startsWith("9.") == false;
1516-
Pattern pattern = Pattern.compile("^7\\.(\\d+)\\.\\d+$");
1517-
Matcher matcher = pattern.matcher(previousNodeVersion);
1518-
if (matcher.matches()) {
1519-
try {
1520-
int minorVersion = Integer.parseInt(matcher.group(1));
1521-
if (minorVersion >= 17) {
1522-
return previousNodeVersion;
1523-
}
1524-
} catch (NumberFormatException e) {
1525-
// continue and return default
1526-
}
1511+
static BuildVersion getBestDowngradeVersion(BuildVersion previousNodeVersion) {
1512+
if (previousNodeVersion.onOrAfterMinimumCompatible()) {
1513+
return previousNodeVersion;
15271514
}
1528-
return "7.17.0";
1515+
return BuildVersion.current().minimumCompatibilityVersion();
15291516
}
15301517

15311518
}

server/src/main/java/org/elasticsearch/env/NodeMetadata.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
package org.elasticsearch.env;
1111

1212
import org.elasticsearch.Build;
13-
import org.elasticsearch.core.UpdateForV9;
1413
import org.elasticsearch.gateway.MetadataStateFormat;
1514
import org.elasticsearch.index.IndexVersion;
1615
import org.elasticsearch.index.IndexVersions;
@@ -158,12 +157,11 @@ public void setOldestIndexVersion(int oldestIndexVersion) {
158157
this.oldestIndexVersion = IndexVersion.fromId(oldestIndexVersion);
159158
}
160159

161-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA) // version is required in the node metadata from v9 onwards
162160
public NodeMetadata build() {
163161
final IndexVersion oldestIndexVersion;
164162

165163
if (this.nodeVersion == null) {
166-
nodeVersion = BuildVersion.fromVersionId(0);
164+
throw new IllegalStateException("Node version is required in node metadata");
167165
}
168166
if (this.previousNodeVersion == null) {
169167
previousNodeVersion = nodeVersion;

server/src/test/java/org/elasticsearch/env/BuildVersionTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ public void testIsFutureVersion() {
4343
assertTrue(futureVersion.isFutureVersion());
4444
}
4545

46+
public void testMinimumCompatibilityVersion() {
47+
BuildVersion minCompatible = BuildVersion.fromVersionId(Version.CURRENT.minimumCompatibilityVersion().id());
48+
assertThat(BuildVersion.current().minimumCompatibilityVersion(), equalTo(minCompatible));
49+
50+
BuildVersion previousCompatible = BuildVersion.fromVersionId(
51+
Version.CURRENT.minimumCompatibilityVersion().minimumCompatibilityVersion().id()
52+
);
53+
assertThat(minCompatible.minimumCompatibilityVersion(), equalTo(previousCompatible));
54+
}
55+
4656
public static BuildVersion increment(BuildVersion version) {
4757
return BuildVersion.fromVersionId(((DefaultBuildVersion) version).version.id() + 1);
4858
}

server/src/test/java/org/elasticsearch/env/NodeEnvironmentTests.java

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,9 @@ public void testIndexCompatibilityChecks() throws IOException {
584584
containsString("it holds metadata for indices with version [" + oldIndexVersion.toReleaseVersion() + "]"),
585585
containsString(
586586
"Revert this node to version ["
587-
+ (previousNodeVersion.major == Version.V_8_0_0.major ? Version.V_7_17_0 : previousNodeVersion)
587+
+ (previousNodeVersion.major == Version.CURRENT.major
588+
? Version.CURRENT.minimumCompatibilityVersion()
589+
: previousNodeVersion)
588590
+ "]"
589591
)
590592
)
@@ -638,20 +640,31 @@ public void testSymlinkDataDirectory() throws Exception {
638640
env.close();
639641
}
640642

641-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
642-
@AwaitsFix(bugUrl = "test won't work until we remove and bump minimum index versions")
643643
public void testGetBestDowngradeVersion() {
644-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.0"), Matchers.equalTo("7.17.0"));
645-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.5"), Matchers.equalTo("7.17.5"));
646-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.1234"), Matchers.equalTo("7.17.1234"));
647-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.18.0"), Matchers.equalTo("7.18.0"));
648-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.x"), Matchers.equalTo("7.17.0"));
649-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.5-SNAPSHOT"), Matchers.equalTo("7.17.0"));
650-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.17.6b"), Matchers.equalTo("7.17.0"));
651-
assertThat(NodeEnvironment.getBestDowngradeVersion("7.16.0"), Matchers.equalTo("7.17.0"));
652-
// when we get to version 7.2147483648.0 we will have to rethink our approach, but for now we return 7.17.0 with an integer overflow
653-
assertThat(NodeEnvironment.getBestDowngradeVersion("7." + Integer.MAX_VALUE + "0.0"), Matchers.equalTo("7.17.0"));
654-
assertThat(NodeEnvironment.getBestDowngradeVersion("foo"), Matchers.equalTo("7.17.0"));
644+
assertThat(
645+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("8.18.0")),
646+
Matchers.equalTo(BuildVersion.fromString("8.18.0"))
647+
);
648+
assertThat(
649+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("8.18.5")),
650+
Matchers.equalTo(BuildVersion.fromString("8.18.5"))
651+
);
652+
assertThat(
653+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("8.18.12")),
654+
Matchers.equalTo(BuildVersion.fromString("8.18.12"))
655+
);
656+
assertThat(
657+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("8.19.0")),
658+
Matchers.equalTo(BuildVersion.fromString("8.19.0"))
659+
);
660+
assertThat(
661+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("8.17.0")),
662+
Matchers.equalTo(BuildVersion.fromString("8.18.0"))
663+
);
664+
assertThat(
665+
NodeEnvironment.getBestDowngradeVersion(BuildVersion.fromString("7.17.0")),
666+
Matchers.equalTo(BuildVersion.fromString("8.18.0"))
667+
);
655668
}
656669

657670
private void verifyFailsOnShardData(Settings settings, Path indexPath, String shardDataDirName) {

server/src/test/java/org/elasticsearch/env/NodeMetadataTests.java

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
package org.elasticsearch.env;
1010

1111
import org.elasticsearch.Build;
12+
import org.elasticsearch.ElasticsearchException;
1213
import org.elasticsearch.Version;
1314
import org.elasticsearch.core.Tuple;
14-
import org.elasticsearch.core.UpdateForV9;
1515
import org.elasticsearch.gateway.MetadataStateFormat;
1616
import org.elasticsearch.index.IndexVersion;
17-
import org.elasticsearch.index.IndexVersions;
1817
import org.elasticsearch.test.ESTestCase;
1918
import org.elasticsearch.test.EqualsHashCodeTestUtils;
2019
import org.elasticsearch.test.VersionUtils;
@@ -28,6 +27,7 @@
2827
import static org.hamcrest.Matchers.allOf;
2928
import static org.hamcrest.Matchers.endsWith;
3029
import static org.hamcrest.Matchers.equalTo;
30+
import static org.hamcrest.Matchers.instanceOf;
3131
import static org.hamcrest.Matchers.notNullValue;
3232
import static org.hamcrest.Matchers.startsWith;
3333

@@ -80,22 +80,20 @@ public void testEqualsHashcodeSerialization() {
8080
);
8181
}
8282

83-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
84-
@AwaitsFix(bugUrl = "as mentioned in the comment below, the behavior here is changing for 9.0 so this test needs updating")
85-
public void testReadsFormatWithoutVersion() throws IOException {
86-
// the behaviour tested here is only appropriate if the current version is compatible with versions 7 and earlier
87-
assertTrue(IndexVersions.MINIMUM_COMPATIBLE.onOrBefore(IndexVersions.V_7_0_0));
88-
// when the current version is incompatible with version 7, the behaviour should change to reject files like the given resource
89-
// which do not have the version field
90-
83+
public void testFailsToReadFormatWithoutVersion() throws IOException {
9184
final Path tempDir = createTempDir();
9285
final Path stateDir = Files.createDirectory(tempDir.resolve(MetadataStateFormat.STATE_DIR_NAME));
9386
final InputStream resource = this.getClass().getResourceAsStream("testReadsFormatWithoutVersion.binary");
9487
assertThat(resource, notNullValue());
9588
Files.copy(resource, stateDir.resolve(NodeMetadata.FORMAT.getStateFileName(between(0, Integer.MAX_VALUE))));
96-
final NodeMetadata nodeMetadata = NodeMetadata.FORMAT.loadLatestState(logger, xContentRegistry(), tempDir);
97-
assertThat(nodeMetadata.nodeId(), equalTo("y6VUVMSaStO4Tz-B5BxcOw"));
98-
assertThat(nodeMetadata.nodeVersion(), equalTo(BuildVersion.fromVersionId(0)));
89+
90+
ElasticsearchException ex = expectThrows(
91+
ElasticsearchException.class,
92+
() -> NodeMetadata.FORMAT.loadLatestState(logger, xContentRegistry(), tempDir)
93+
);
94+
Throwable rootCause = ex.getRootCause();
95+
assertThat(rootCause, instanceOf(IllegalStateException.class));
96+
assertThat("Node version is required in node metadata", equalTo(rootCause.getMessage()));
9997
}
10098

10199
public void testUpgradesLegitimateVersions() {
@@ -155,11 +153,9 @@ public void testDoesNotUpgradeAncientVersion() {
155153
);
156154
}
157155

158-
@UpdateForV9(owner = UpdateForV9.Owner.CORE_INFRA)
159-
@AwaitsFix(bugUrl = "Needs to be updated for 9.0 version bump")
160156
public void testUpgradeMarksPreviousVersion() {
161157
final String nodeId = randomAlphaOfLength(10);
162-
final Version version = VersionUtils.randomVersionBetween(random(), Version.CURRENT.minimumCompatibilityVersion(), Version.V_8_0_0);
158+
final Version version = VersionUtils.randomVersionBetween(random(), Version.CURRENT.minimumCompatibilityVersion(), Version.V_9_0_0);
163159
final BuildVersion buildVersion = BuildVersion.fromVersionId(version.id());
164160

165161
final NodeMetadata nodeMetadata = new NodeMetadata(nodeId, buildVersion, IndexVersion.current()).upgradeToCurrentVersion();

0 commit comments

Comments
 (0)