Skip to content

Commit 07cb2b9

Browse files
committed
Allow setting index.creation_date on index creation for plugin compatibility and migrations
Aligns behavior with snapshot restore to let migrations retain original creation timestamps. Signed-off-by: Andre Kurait <akurait@amazon.com>
1 parent b74d032 commit 07cb2b9

3 files changed

Lines changed: 169 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55

66
## [Unreleased 3.x]
77
### Added
8+
- Allow setting index.creation_date on index creation for plugin compatibility and migrations ([#19931](https://github.com/opensearch-project/OpenSearch/pull/19931))
89
- Add support for a ForkJoinPool type ([#19008](https://github.com/opensearch-project/OpenSearch/pull/19008))
910
- Add seperate shard limit validation for local and remote indices ([#19532](https://github.com/opensearch-project/OpenSearch/pull/19532))
1011
- Use Lucene `pack` method for `half_float` and `usigned_long` when using `ApproximatePointRangeQuery`.

server/src/main/java/org/opensearch/cluster/metadata/IndexMetadata.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,6 @@ public static APIBlock readFrom(StreamInput input) throws IOException {
668668
-1,
669669
-1,
670670
Property.IndexScope,
671-
Property.PrivateIndex,
672671
Property.UnmodifiableOnRestore
673672
);
674673

server/src/test/java/org/opensearch/cluster/metadata/MetadataCreateIndexServiceTests.java

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3024,4 +3024,172 @@ private DiscoveryNode getRemoteNode() {
30243024
);
30253025
}
30263026

3027+
public void testCreateIndexWithCustomCreationDate() {
3028+
// Test creating an index with a custom creation_date in the past
3029+
long customCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(30).millis();
3030+
3031+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3032+
final Settings.Builder requestSettings = Settings.builder();
3033+
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, customCreationDate);
3034+
request.settings(requestSettings.build());
3035+
3036+
Settings aggregatedSettings = aggregateIndexSettings(
3037+
ClusterState.EMPTY_STATE,
3038+
request,
3039+
Settings.EMPTY,
3040+
null,
3041+
Settings.EMPTY,
3042+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3043+
randomShardLimitService(),
3044+
Collections.emptySet(),
3045+
clusterSettings
3046+
);
3047+
3048+
assertEquals(Long.toString(customCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3049+
}
3050+
3051+
public void testCreateIndexWithCustomCreationDateInFuture() {
3052+
// Test creating an index with a custom creation_date in the future
3053+
long futureCreationDate = System.currentTimeMillis() + TimeValue.timeValueDays(30).millis();
3054+
3055+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3056+
final Settings.Builder requestSettings = Settings.builder();
3057+
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, futureCreationDate);
3058+
request.settings(requestSettings.build());
3059+
3060+
Settings aggregatedSettings = aggregateIndexSettings(
3061+
ClusterState.EMPTY_STATE,
3062+
request,
3063+
Settings.EMPTY,
3064+
null,
3065+
Settings.EMPTY,
3066+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3067+
randomShardLimitService(),
3068+
Collections.emptySet(),
3069+
clusterSettings
3070+
);
3071+
3072+
assertEquals(Long.toString(futureCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3073+
}
3074+
3075+
public void testCreateIndexWithoutCustomCreationDate() {
3076+
// Test that default behavior still works when creation_date is not provided
3077+
long beforeCreation = System.currentTimeMillis();
3078+
3079+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3080+
3081+
Settings aggregatedSettings = aggregateIndexSettings(
3082+
ClusterState.EMPTY_STATE,
3083+
request,
3084+
Settings.EMPTY,
3085+
null,
3086+
Settings.EMPTY,
3087+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3088+
randomShardLimitService(),
3089+
Collections.emptySet(),
3090+
clusterSettings
3091+
);
3092+
3093+
long afterCreation = System.currentTimeMillis();
3094+
long actualCreationDate = Long.parseLong(aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3095+
3096+
// Verify the creation date is set to current time (within reasonable bounds)
3097+
assertTrue("Creation date should be >= beforeCreation", actualCreationDate >= beforeCreation);
3098+
assertTrue("Creation date should be <= afterCreation", actualCreationDate <= afterCreation);
3099+
}
3100+
3101+
public void testCreateIndexWithNegativeCreationDate() {
3102+
// Test creating an index with a negative timestamp (dates before epoch)
3103+
long negativeCreationDate = -1000000000L; // Some time before 1970
3104+
3105+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3106+
final Settings.Builder requestSettings = Settings.builder();
3107+
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, negativeCreationDate);
3108+
request.settings(requestSettings.build());
3109+
3110+
Settings aggregatedSettings = aggregateIndexSettings(
3111+
ClusterState.EMPTY_STATE,
3112+
request,
3113+
Settings.EMPTY,
3114+
null,
3115+
Settings.EMPTY,
3116+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3117+
randomShardLimitService(),
3118+
Collections.emptySet(),
3119+
clusterSettings
3120+
);
3121+
3122+
assertEquals(Long.toString(negativeCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3123+
}
3124+
3125+
public void testCreateIndexWithZeroCreationDate() {
3126+
// Test creating an index with creation_date set to 0 (epoch time)
3127+
long epochCreationDate = 0L;
3128+
3129+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3130+
final Settings.Builder requestSettings = Settings.builder();
3131+
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, epochCreationDate);
3132+
request.settings(requestSettings.build());
3133+
3134+
Settings aggregatedSettings = aggregateIndexSettings(
3135+
ClusterState.EMPTY_STATE,
3136+
request,
3137+
Settings.EMPTY,
3138+
null,
3139+
Settings.EMPTY,
3140+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3141+
randomShardLimitService(),
3142+
Collections.emptySet(),
3143+
clusterSettings
3144+
);
3145+
3146+
assertEquals(Long.toString(epochCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3147+
}
3148+
3149+
public void testCustomCreationDatePreservedInIndexMetadata() {
3150+
// Test that custom creation_date is properly stored in IndexMetadata
3151+
long customCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(7).millis();
3152+
3153+
Settings indexSettings = Settings.builder()
3154+
.put("index.version.created", Version.CURRENT)
3155+
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
3156+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
3157+
.put(IndexMetadata.SETTING_CREATION_DATE, customCreationDate)
3158+
.build();
3159+
3160+
IndexMetadata indexMetadata = IndexMetadata.builder("test").settings(indexSettings).build();
3161+
3162+
assertEquals(customCreationDate, indexMetadata.getCreationDate());
3163+
}
3164+
3165+
public void testCustomCreationDateWithTemplates() {
3166+
// Test that custom creation_date from request takes precedence over template
3167+
long templateCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(60).millis();
3168+
long requestCreationDate = System.currentTimeMillis() - TimeValue.timeValueDays(30).millis();
3169+
3170+
IndexTemplateMetadata templateMetadata = addMatchingTemplate(builder -> {
3171+
builder.settings(Settings.builder().put(IndexMetadata.SETTING_CREATION_DATE, templateCreationDate));
3172+
});
3173+
3174+
request = new CreateIndexClusterStateUpdateRequest("create index", "test", "test");
3175+
final Settings.Builder requestSettings = Settings.builder();
3176+
requestSettings.put(IndexMetadata.SETTING_CREATION_DATE, requestCreationDate);
3177+
request.settings(requestSettings.build());
3178+
3179+
Settings aggregatedSettings = aggregateIndexSettings(
3180+
ClusterState.EMPTY_STATE,
3181+
request,
3182+
templateMetadata.settings(),
3183+
null,
3184+
Settings.EMPTY,
3185+
IndexScopedSettings.DEFAULT_SCOPED_SETTINGS,
3186+
randomShardLimitService(),
3187+
Collections.emptySet(),
3188+
clusterSettings
3189+
);
3190+
3191+
// Request setting should take precedence over template
3192+
assertEquals(Long.toString(requestCreationDate), aggregatedSettings.get(IndexMetadata.SETTING_CREATION_DATE));
3193+
}
3194+
30273195
}

0 commit comments

Comments
 (0)