diff --git a/server/src/main/java/org/elasticsearch/index/IndexSettings.java b/server/src/main/java/org/elasticsearch/index/IndexSettings.java index 9c2f4925011b8..966a53b151ac2 100644 --- a/server/src/main/java/org/elasticsearch/index/IndexSettings.java +++ b/server/src/main/java/org/elasticsearch/index/IndexSettings.java @@ -1021,12 +1021,15 @@ public void validate(Boolean enabled) { public void validate(Boolean enabled, Map, Object> settings) { if (enabled) { var indexVersion = (IndexVersion) settings.get(SETTING_INDEX_VERSION_CREATED); - if (indexVersion.onOrAfter(IndexVersions.DISABLE_SEQUENCE_NUMBERS) == false - && indexVersion.equals(IndexVersions.ZERO) == false) { - // We validate settings in different places before a real indexVersion has been assigned or - // is missing for other reasons. In those cases IndexVersion.ZERO is used as fallback value, - // and we don't want to fail those validations. At index creation time we _will_ validate with - // the creation version. + if (indexVersion.equals(IndexVersions.ZERO)) { + // Settings are validated in different places before a real indexVersion has been assigned or is missing for other + // reasons (eg. composable index templates). In those cases IndexVersion.ZERO is used as fallback value, and we + // don't want to fail those validations so we return early here because the next two validation checks require + // the IndexMetadata.SETTING_INDEX_VERSION_CREATED to be set. At index creation time we _will_ validate with the + // creation version. + return; + } + if (indexVersion.onOrAfter(IndexVersions.DISABLE_SEQUENCE_NUMBERS) == false) { throw new IllegalArgumentException( String.format( Locale.ROOT, diff --git a/x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/CcrTimeSeriesDataStreamsIT.java b/x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/CcrTimeSeriesDataStreamsIT.java index e7eb10ca7fe78..1334ed49ce907 100644 --- a/x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/CcrTimeSeriesDataStreamsIT.java +++ b/x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/CcrTimeSeriesDataStreamsIT.java @@ -30,6 +30,7 @@ import org.elasticsearch.index.mapper.IdFieldMapper; import org.elasticsearch.index.mapper.Uid; import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.index.seqno.SequenceNumbers; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.test.ClusterServiceUtils; @@ -82,7 +83,9 @@ private void executeTest(final boolean useSyntheticId) throws Exception { final var dataStreamName = randomIdentifier(); final int nbPrimaries = randomIntBetween(1, 5); final int nbReplicas = between(0, 1); - putDataStreamTemplate(leaderClient(), dataStreamName, nbPrimaries, nbReplicas, useSyntheticId); + final boolean disableSeqNo = IndexSettings.DISABLE_SEQUENCE_NUMBERS_FEATURE_FLAG && randomBoolean(); + final long expectedPrimaryTerm = disableSeqNo ? SequenceNumbers.UNASSIGNED_PRIMARY_TERM : 1L; + putDataStreamTemplate(leaderClient(), dataStreamName, nbPrimaries, nbReplicas, useSyntheticId, disableSeqNo); // Randomize between Auto Follow and Put Follow final var useAutoFollow = randomBoolean(); @@ -123,7 +126,7 @@ enum Operation { for (var result : bulkResponse.getItems()) { assertThat(result.getResponse().getResult(), equalTo(DocWriteResponse.Result.CREATED)); assertThat(result.getVersion(), equalTo(1L)); - assertThat(result.getResponse().getPrimaryTerm(), equalTo(1L)); + assertThat(result.getResponse().getPrimaryTerm(), equalTo(expectedPrimaryTerm)); var previous = docsIndicesById.put(result.getId(), result.getIndex()); assertThat(previous, nullValue()); } @@ -157,7 +160,7 @@ enum Operation { assertThat(deleteResponse.getIndex(), equalTo(deletedDocIndex)); assertThat(deleteResponse.getResult(), equalTo(DocWriteResponse.Result.DELETED)); assertThat(deleteResponse.getVersion(), equalTo(2L)); - assertThat(deleteResponse.getPrimaryTerm(), equalTo(1L)); + assertThat(deleteResponse.getPrimaryTerm(), equalTo(expectedPrimaryTerm)); } // Randomly executes a flush, refresh or nothing before checking the follower index @@ -229,7 +232,7 @@ enum Operation { for (var result : bulkResponse.getItems()) { assertThat(result.getResponse().getResult(), equalTo(DocWriteResponse.Result.CREATED)); assertThat(result.getVersion(), equalTo(1L)); - assertThat(result.getResponse().getPrimaryTerm(), equalTo(1L)); + assertThat(result.getResponse().getPrimaryTerm(), equalTo(expectedPrimaryTerm)); var previous = docsIndicesById.put(result.getId(), result.getIndex()); assertThat(previous, nullValue()); var added = nonDeletedDocs.add(result.getId()); @@ -247,7 +250,7 @@ enum Operation { assertThat(deleteResponse.getIndex(), equalTo(deletedDocIndex)); assertThat(deleteResponse.getResult(), equalTo(DocWriteResponse.Result.DELETED)); assertThat(deleteResponse.getVersion(), equalTo(2L)); - assertThat(deleteResponse.getPrimaryTerm(), equalTo(1L)); + assertThat(deleteResponse.getPrimaryTerm(), equalTo(expectedPrimaryTerm)); var removed = nonDeletedDocs.remove(deletedDocId); assertThat(removed, equalTo(true)); var added = deletedDocs.add(deletedDocId); @@ -274,14 +277,23 @@ enum Operation { leaderClient().execute(ForceMergeAction.INSTANCE, new ForceMergeRequest()).actionGet(); } - private static void putDataStreamTemplate(Client client, String dataStreamName, int primaries, int replicas, boolean useSyntheticId) - throws IOException { + private static void putDataStreamTemplate( + Client client, + String dataStreamName, + int primaries, + int replicas, + boolean useSyntheticId, + boolean disableSeqNo + ) throws IOException { var settingsBuilder = indexSettings(primaries, replicas).put(IndexSettings.MODE.getKey(), IndexMode.TIME_SERIES.getName()) .put(IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getKey(), -1) .put(IndexSettings.RECOVERY_USE_SYNTHETIC_SOURCE_SETTING.getKey(), randomBoolean()); if (IndexSettings.TSDB_SYNTHETIC_ID_FEATURE_FLAG) { settingsBuilder.put(IndexSettings.SYNTHETIC_ID.getKey(), useSyntheticId); } + if (disableSeqNo) { + settingsBuilder.put(IndexSettings.DISABLE_SEQUENCE_NUMBERS.getKey(), true); + } var putTemplateRequest = new TransportPutComposableIndexTemplateAction.Request(getTestClass().getName().toLowerCase(Locale.ROOT)) .indexTemplate( ComposableIndexTemplate.builder()