Skip to content
Merged
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 @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased 3.x]
### Added
- Allow setting index.creation_date on index creation and restore for plugin compatibility and migrations ([#19931](https://github.com/opensearch-project/OpenSearch/pull/19931))
- Add support for a ForkJoinPool type ([#19008](https://github.com/opensearch-project/OpenSearch/pull/19008))
- Add seperate shard limit validation for local and remote indices ([#19532](https://github.com/opensearch-project/OpenSearch/pull/19532))
- Use Lucene `pack` method for `half_float` and `usigned_long` when using `ApproximatePointRangeQuery`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,54 @@ public void testCreateIndex() throws IOException {
}
}

public void testCreateIndexFailPrivateSetting() throws IOException {
public void testCreateIndexWithCreationDate() throws IOException {
{
// Create index with private setting
String indexName = "private_index";
// Create index with creation_date setting - should succeed now that it's not private
String indexName = "creation_date_index";
assertFalse(indexExists(indexName));

CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);

Settings.Builder settings = Settings.builder();
settings.put(SETTING_CREATION_DATE, -1);
settings.put(SETTING_CREATION_DATE, 1234567890L);
createIndexRequest.settings(settings);

OpenSearchStatusException exception = expectThrows(
OpenSearchStatusException.class,
() -> execute(createIndexRequest, highLevelClient().indices()::create, highLevelClient().indices()::createAsync)
CreateIndexResponse createIndexResponse = execute(
createIndexRequest,
highLevelClient().indices()::create,
highLevelClient().indices()::createAsync
);
assertTrue(
"Index creation should be acknowledged when setting creation_date during index creation",
createIndexResponse.isAcknowledged()
);
assertTrue("Index should exist after creation with creation_date setting", indexExists(indexName));
}
}

public void testUpdateIndexSettingsFailFinalSetting() throws IOException {
{
// Create index and attempt to update creation_date - should fail as it's a final setting
String indexName = "final_setting_index";
createIndex(indexName, Settings.EMPTY);

UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(indexName);
Settings.Builder settings = Settings.builder();
settings.put(SETTING_CREATION_DATE, 9876543210L);
updateSettingsRequest.settings(settings);

OpenSearchException exception = expectThrows(
OpenSearchException.class,
() -> execute(
updateSettingsRequest,
highLevelClient().indices()::putSettings,
highLevelClient().indices()::putSettingsAsync
)
);
assertTrue(
"Exception message should indicate that index.creation_date cannot be updated. Got: " + exception.getMessage(),
exception.getMessage().contains("Can't update non dynamic settings [[index.creation_date]]")
);
assertTrue(exception.getMessage().contains("private index setting [index.creation_date] can not be set explicitly"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,10 @@ public void testUnknownSettingFails() {

public void testPrivateSettingFails() {
try {
prepareCreate("test").setSettings(Settings.builder().put(IndexMetadata.SETTING_CREATION_DATE, -1).build()).get();
prepareCreate("test").setSettings(Settings.builder().put(IndexMetadata.SETTING_INDEX_UUID, "uuid").build()).get();
fail("should have thrown an exception about private settings");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("private index setting [index.creation_date] can not be set explicitly"));
assertTrue(e.getMessage().contains("private index setting [index.uuid] can not be set explicitly"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,7 @@ public static APIBlock readFrom(StreamInput input) throws IOException {
-1,
-1,
Property.IndexScope,
Property.PrivateIndex,
Property.UnmodifiableOnRestore
Property.Final
);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3024,4 +3024,172 @@ private DiscoveryNode getRemoteNode() {
);
}

public void testCreateIndexWithCustomCreationDate() {
// Test creating an index with a custom creation_date in the past
long customCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(30).millis();

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
final Settings.Builder requestSettings = Settings.builder();
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, customCreationDate);
request.settings(requestSettings.build());

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
Settings.EMPTY,
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

assertEquals(Long.toString(customCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
}

public void testCreateIndexWithCustomCreationDateInFuture() {
// Test creating an index with a custom creation_date in the future
long futureCreationDate = System.currentTimeMillis() + TimeValue.timeValueDays(30).millis();

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
final Settings.Builder requestSettings = Settings.builder();
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, futureCreationDate);
request.settings(requestSettings.build());

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
Settings.EMPTY,
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

assertEquals(Long.toString(futureCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
}

public void testCreateIndexWithoutCustomCreationDate() {
// Test that default behavior still works when creation_date is not provided
long beforeCreation = System.currentTimeMillis();

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
Settings.EMPTY,
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

long afterCreation = System.currentTimeMillis();
long actualCreationDate = Long.parseLong(aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));

// Verify the creation date is set to current time (within reasonable bounds)
assertTrue("Creation date should be >= beforeCreation", actualCreationDate >= beforeCreation);
assertTrue("Creation date should be <= afterCreation", actualCreationDate <= afterCreation);
}

public void testCreateIndexWithNegativeCreationDate() {
// Test creating an index with a negative timestamp (dates before epoch)
long negativeCreationDate = -1000000000L; // Some time before 1970

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
final Settings.Builder requestSettings = Settings.builder();
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, negativeCreationDate);
request.settings(requestSettings.build());

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
Settings.EMPTY,
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

assertEquals(Long.toString(negativeCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
}

public void testCreateIndexWithZeroCreationDate() {
// Test creating an index with creation_date set to 0 (epoch time)
long epochCreationDate = 0L;

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
final Settings.Builder requestSettings = Settings.builder();
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, epochCreationDate);
request.settings(requestSettings.build());

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
Settings.EMPTY,
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

assertEquals(Long.toString(epochCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
}

public void testCustomCreationDatePreservedInIndexMetadata() {
// Test that custom creation_date is properly stored in IndexMetadata
long customCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(7).millis();

Settings indexSettings = Settings.builder()
.put("index.version.created", Version.CURRENT)
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
.put(IndexMetadata.SETTING_CREATION_DATE, customCreationDate)
.build();

IndexMetadata indexMetadata = IndexMetadata.builder("test").settings(indexSettings).build();

assertEquals(customCreationDate, indexMetadata.getCreationDate());
}

public void testCustomCreationDateWithTemplates() {
// Test that custom creation_date from request takes precedence over template
long templateCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(60).millis();
long requestCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(30).millis();

IndexTemplateMetadata templateMetadata = addMatchingTemplate(builder -> {
builder.settings(Settings.builder().put(IndexMetadata.SETTING_CREATION_DATE, templateCreationDate));
});

request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
final Settings.Builder requestSettings = Settings.builder();
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, requestCreationDate);
request.settings(requestSettings.build());

Settings aggregatedSettings = aggregateIndexSettings(
ClusterState.EMPTY_STATE,
request,
templateMetadata.settings(),
null,
Settings.EMPTY,
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
randomShardLimitService(),
Collections.emptySet(),
clusterSettings
);

// Request setting should take precedence over template
assertEquals(Long.toString(requestCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
}

}
Loading