Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Use env variable (OPENSEARCH_FIPS_MODE) to enable opensearch to run in FIPS enforced mode instead of checking for existence of bcFIPS jars ([#20625](https://github.com/opensearch-project/OpenSearch/pull/20625))
- Update streaming flag to use search request context ([#20530](https://github.com/opensearch-project/OpenSearch/pull/20530))
- Move pull-based ingestion classes from experimental to publicAPI ([#20704](https://github.com/opensearch-project/OpenSearch/pull/20704))
* Improved error message when trying to open an index originally created with Elasticsearch on OpenSearch ([#20512](https://github.com/opensearch-project/OpenSearch/pull/20512))

### Fixed
- Fix flaky test failures in ShardsLimitAllocationDeciderIT ([#20375](https://github.com/opensearch-project/OpenSearch/pull/20375))
Expand Down
43 changes: 34 additions & 9 deletions libs/core/src/main/java/org/opensearch/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.opensearch.common.SuppressForbidden;
import org.opensearch.common.annotation.PublicApi;
import org.opensearch.core.Assertions;
import org.opensearch.core.common.Strings;
import org.opensearch.core.xcontent.ToXContentFragment;
import org.opensearch.core.xcontent.XContentBuilder;

Expand All @@ -56,6 +57,37 @@
*/
@PublicApi(since = "1.0.0")
public class Version implements Comparable<Version>, ToXContentFragment {
/**
* Exception thrown when an unsupported version ID is encountered.
*/
public static class UnsupportedVersionException extends RuntimeException {
private final String versionString;

private UnsupportedVersionException(int versionId) {
super(String.format(Locale.ROOT, "Unsupported version [%s]", legacyFriendlyIdToString(versionId)));
this.versionString = legacyFriendlyIdToString(versionId);
}

public String getVersionString() {
return versionString;
}
}

private static String legacyFriendlyIdToString(int versionId) {
String prefix;
if ((versionId & MASK) != 0) {
versionId = versionId ^ MASK;
prefix = "";
} else {
prefix = "ES ";
}
int major = (versionId / MAJOR_SHIFT) % VERSION_SHIFT;
int minor = (versionId / MINOR_SHIFT) % VERSION_SHIFT;
int revision = (versionId / REVISION_SHIFT) % VERSION_SHIFT;

return prefix + major + "." + minor + "." + revision;
}

private static final int VERSION_SHIFT = 100; // Two digits per version part
private static final int REVISION_SHIFT = VERSION_SHIFT;
private static final int MINOR_SHIFT = VERSION_SHIFT * VERSION_SHIFT;
Expand Down Expand Up @@ -210,7 +242,7 @@ public class Version implements Comparable<Version>, ToXContentFragment {

public static Version fromId(int id) {
if (id != 0 && (id & MASK) == 0) {
throw new IllegalArgumentException("Version id " + id + " must contain OpenSearch mask");
throw new UnsupportedVersionException(id);
}
final Version known = idToVersion.get(id);
if (known != null) {
Expand Down Expand Up @@ -267,7 +299,7 @@ public static Version max(Version version1, Version version2) {
* Returns the version given its string representation, current version if the argument is null or empty
*/
public static Version fromString(String version) {
if (stringHasLength(version) == false) { // TODO replace with Strings.hasLength after refactoring Strings to core lib
if (Strings.hasLength(version) == false) {
return Version.CURRENT;
}
final Version cached = stringToVersion.get(version);
Expand Down Expand Up @@ -597,11 +629,4 @@ public static List<Version> getDeclaredVersions(final Class<?> versionClass) {
return versions;
}

/**
* Check that the given String is neither <code>null</code> nor of length 0.
* Note: Will return <code>true</code> for a String that purely consists of whitespace.
*/
public static boolean stringHasLength(String str) {
return (str != null && str.length() > 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.opensearch.Version;
import org.opensearch.common.Nullable;
import org.opensearch.common.annotation.PublicApi;
import org.opensearch.core.common.Strings;
import org.opensearch.core.xcontent.ToXContentFragment;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.semver.expr.Caret;
Expand Down Expand Up @@ -80,7 +81,7 @@ public static SemverRange fromString(final String range) {

RangeOperator rangeOperator = RangeOperator.fromRange(range);
String version = range.replaceFirst(rangeOperator.asEscapedString(), "");
if (!Version.stringHasLength(version)) {
if (!Strings.hasLength(version)) {
throw new IllegalArgumentException("Version cannot be empty");
}
return new SemverRange(Version.fromString(version), rangeOperator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,7 @@ public Version getCreationVersion() {

/**
* Gets the ingestion source.
*
* @return ingestion source, or null if ingestion source is not enabled
*/
public IngestionSource getIngestionSource() {
Expand Down Expand Up @@ -2589,6 +2590,7 @@ public static Settings addHumanReadableSettings(Settings settings) {
}

private static final ToXContent.Params FORMAT_PARAMS;

static {
Map<String, String> params = new HashMap<>(2);
params.put("binary", "true");
Expand All @@ -2602,7 +2604,19 @@ public static Settings addHumanReadableSettings(Settings settings) {
* This looks for the presence of the {@link Version} object with key {@link IndexMetadata#SETTING_VERSION_CREATED}
*/
public static Version indexCreated(final Settings indexSettings) {
final Version indexVersion = SETTING_INDEX_VERSION_CREATED.get(indexSettings);
final Version indexVersion;
try {
indexVersion = SETTING_INDEX_VERSION_CREATED.get(indexSettings);
} catch (Version.UnsupportedVersionException e) {
final String message = String.format(
Locale.ROOT,
"index with UUID [%s] created on version [%s] is not supported by version [%s]",
indexSettings.get(IndexMetadata.SETTING_INDEX_UUID),
e.getVersionString(),
Version.CURRENT.toString()
);
throw new IllegalArgumentException(message, e);
}
if (indexVersion.equals(Version.V_EMPTY)) {
final String message = String.format(
Locale.ROOT,
Expand Down Expand Up @@ -2652,9 +2666,10 @@ public int getRoutingFactor() {

/**
* Returns the source shard ID to split the given target shard off
* @param shardId the id of the target shard to split into
*
* @param shardId the id of the target shard to split into
* @param sourceIndexMetadata the source index metadata
* @param numTargetShards the total number of shards in the target index
* @param numTargetShards the total number of shards in the target index
* @return a the source shard ID to split off from
*/
public static ShardId selectSplitShard(int shardId, IndexMetadata sourceIndexMetadata, int numTargetShards) {
Expand All @@ -2671,9 +2686,10 @@ public static ShardId selectSplitShard(int shardId, IndexMetadata sourceIndexMet

/**
* Returns the source shard ID to clone the given target shard off
* @param shardId the id of the target shard to clone into
*
* @param shardId the id of the target shard to clone into
* @param sourceIndexMetadata the source index metadata
* @param numTargetShards the total number of shards in the target index
* @param numTargetShards the total number of shards in the target index
* @return a the source shard ID to clone from
*/
public static ShardId selectCloneShard(int shardId, IndexMetadata sourceIndexMetadata, int numTargetShards) {
Expand Down Expand Up @@ -2718,9 +2734,10 @@ private static void assertSplitMetadata(int numSourceShards, int numTargetShards

/**
* Selects the source shards for a local shard recovery. This might either be a split or a shrink operation.
* @param shardId the target shard ID to select the source shards for
*
* @param shardId the target shard ID to select the source shards for
* @param sourceIndexMetadata the source metadata
* @param numTargetShards the number of target shards
* @param numTargetShards the number of target shards
*/
public static Set<ShardId> selectRecoverFromShards(int shardId, IndexMetadata sourceIndexMetadata, int numTargetShards) {
if (sourceIndexMetadata.getNumberOfShards() > numTargetShards) {
Expand All @@ -2734,9 +2751,10 @@ public static Set<ShardId> selectRecoverFromShards(int shardId, IndexMetadata so

/**
* Returns the source shard ids to shrink into the given shard id.
* @param shardId the id of the target shard to shrink to
*
* @param shardId the id of the target shard to shrink to
* @param sourceIndexMetadata the source index metadata
* @param numTargetShards the total number of shards in the target index
* @param numTargetShards the total number of shards in the target index
* @return a set of shard IDs to shrink into the given shard ID.
*/
public static Set<ShardId> selectShrinkShards(int shardId, IndexMetadata sourceIndexMetadata, int numTargetShards) {
Expand Down Expand Up @@ -2772,7 +2790,7 @@ public static Set<ShardId> selectShrinkShards(int shardId, IndexMetadata sourceI
* @param targetNumberOfShards the total number of shards in the target index
* @return the routing factor for and shrunk index with the given number of target shards.
* @throws IllegalArgumentException if the number of source shards is less than the number of target shards or if the source shards
* are not divisible by the number of target shards.
* are not divisible by the number of target shards.
*/
public static int getRoutingFactor(int sourceNumberOfShards, int targetNumberOfShards) {
final int factor;
Expand Down Expand Up @@ -2801,8 +2819,9 @@ public static int getRoutingFactor(int sourceNumberOfShards, int targetNumberOfS
* E.g.
* - For ".ds-logs-000002" it will return 2
* - For "&lt;logs-{now/d}-3&gt;" it'll return 3
*
* @throws IllegalArgumentException if the index doesn't contain a "-" separator or if the last token after the separator is not a
* number
* number
*/
public static int parseIndexNameCounter(String indexName) {
int numberIndex = indexName.lastIndexOf("-");
Expand Down
9 changes: 9 additions & 0 deletions server/src/test/java/org/opensearch/VersionTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -464,4 +464,13 @@ public void testUnreleasedVersion() {
Version VERSION_5_1_0_UNRELEASED = Version.fromString("5.1.0");
VersionTests.assertUnknownVersion(VERSION_5_1_0_UNRELEASED);
}

public void testLegacyVersion() {
try {
Version.fromId(7090199);
fail("Legacy version should throw an exception");
} catch (Version.UnsupportedVersionException e) {
assertEquals("ES 7.9.1", e.getVersionString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -755,4 +755,27 @@ public void testAllActivePullBasedIngestionSettings() {
isAllActiveIngestionEnabled = IndexMetadata.INGESTION_SOURCE_ALL_ACTIVE_INGESTION_SETTING.get(settings6);
assertFalse(isAllActiveIngestionEnabled);
}

public void testLegacyCreatedVersion() {
Index index = new Index("test-index", UUIDs.randomBase64UUID());
final Settings settings = Settings.builder()
.put(IndexMetadata.SETTING_VERSION_CREATED, "7090199")
.put(IndexMetadata.SETTING_INDEX_UUID, index.getUUID())
.build();
try {
IndexMetadata.builder(index.getName())
.settings(settings)
.numberOfShards(1)
.numberOfReplicas(0)
.creationDate(System.currentTimeMillis())
.version(1)
.system(false)
.build();
fail("Should not be able to create index with legacy created version");
} catch (IllegalArgumentException e) {
assertTrue(e.getCause() instanceof Version.UnsupportedVersionException);
Version.UnsupportedVersionException versionException = (Version.UnsupportedVersionException) e.getCause();
assertEquals("ES 7.9.1", versionException.getVersionString());
}
}
}
Loading