forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ILM: parse origination date from index name (elastic#46755)
* ILM: parse origination date from index name Introduce the `index.lifecycle.parse_origination_date` setting that indicates if the origination date should be parsed from the index name. If set to true an index which doesn't match the expected format (namely `indexName-{dateFormat}-optional_digits` will fail before being created. The origination date will be parsed when initialising a lifecycle for an index and it will be set as the `index.lifecycle.origination_date` for that index. A user set value for `index.lifecycle.origination_date` will always override a possible parsable date from the index name. (cherry picked from commit c363d27) Signed-off-by: Andrei Dan <[email protected]>
- Loading branch information
Showing
9 changed files
with
314 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
...e/src/main/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleOriginationDateParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.core.ilm; | ||
|
||
import org.elasticsearch.ElasticsearchParseException; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.time.DateFormatter; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import static org.elasticsearch.xpack.core.ilm.LifecycleSettings.LIFECYCLE_ORIGINATION_DATE; | ||
import static org.elasticsearch.xpack.core.ilm.LifecycleSettings.LIFECYCLE_PARSE_ORIGINATION_DATE; | ||
|
||
public class IndexLifecycleOriginationDateParser { | ||
|
||
private static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("yyyy.MM.dd"); | ||
private static final String INDEX_NAME_REGEX = "^.*-(\\d{4}.\\d{2}.\\d{2})(-[\\d]+)?$"; | ||
private static final Pattern INDEX_NAME_PATTERN = Pattern.compile(INDEX_NAME_REGEX); | ||
|
||
/** | ||
* Determines if the origination date needs to be parsed from the index name. | ||
*/ | ||
public static boolean shouldParseIndexName(Settings indexSettings) { | ||
return indexSettings.getAsLong(LIFECYCLE_ORIGINATION_DATE, -1L) == -1L && | ||
indexSettings.getAsBoolean(LIFECYCLE_PARSE_ORIGINATION_DATE, false); | ||
} | ||
|
||
/** | ||
* Parses the index according to the supported format and extracts the origination date. If the index does not match the expected | ||
* format or the date in the index name doesn't match the `yyyy.MM.dd` format it throws an {@link IllegalArgumentException} | ||
*/ | ||
public static long parseIndexNameAndExtractDate(String indexName) { | ||
Matcher matcher = INDEX_NAME_PATTERN.matcher(indexName); | ||
if (matcher.matches()) { | ||
String dateAsString = matcher.group(1); | ||
try { | ||
return DATE_FORMATTER.parseMillis(dateAsString); | ||
} catch (ElasticsearchParseException | IllegalArgumentException e) { | ||
throw new IllegalArgumentException("index name [" + indexName + "] contains date [" + dateAsString + "] which " + | ||
"couldn't be parsed using the 'yyyy.MM.dd' format", e); | ||
} | ||
} | ||
|
||
throw new IllegalArgumentException("index name [" + indexName + "] does not match pattern '" + INDEX_NAME_REGEX + "'"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
.../test/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleOriginationDateParserTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.core.ilm; | ||
|
||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
import java.text.ParseException; | ||
import java.text.SimpleDateFormat; | ||
import java.util.Locale; | ||
import java.util.TimeZone; | ||
|
||
import static org.elasticsearch.xpack.core.ilm.IndexLifecycleOriginationDateParser.parseIndexNameAndExtractDate; | ||
import static org.elasticsearch.xpack.core.ilm.IndexLifecycleOriginationDateParser.shouldParseIndexName; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
public class IndexLifecycleOriginationDateParserTests extends ESTestCase { | ||
|
||
public void testShouldParseIndexNameReturnsFalseWhenOriginationDateIsSet() { | ||
Settings settings = Settings.builder() | ||
.put(LifecycleSettings.LIFECYCLE_ORIGINATION_DATE, 1L) | ||
.build(); | ||
assertThat(shouldParseIndexName(settings), is(false)); | ||
} | ||
|
||
public void testShouldParseIndexNameReturnsFalseIfParseOriginationDateIsDisabled() { | ||
Settings settings = Settings.builder() | ||
.put(LifecycleSettings.LIFECYCLE_PARSE_ORIGINATION_DATE, false) | ||
.build(); | ||
assertThat(shouldParseIndexName(settings), is(false)); | ||
} | ||
|
||
public void testShouldParseIndexNameReturnsTrueIfParseOriginationDateIsTrueAndOriginationDateIsNotSet() { | ||
Settings settings = Settings.builder() | ||
.put(LifecycleSettings.LIFECYCLE_PARSE_ORIGINATION_DATE, true) | ||
.build(); | ||
assertThat(shouldParseIndexName(settings), is(true)); | ||
} | ||
|
||
public void testParseIndexNameThatMatchesExpectedFormat() throws ParseException { | ||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd", Locale.getDefault()); | ||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); | ||
long expectedDate = dateFormat.parse("2019.09.04").getTime(); | ||
|
||
{ | ||
long parsedDate = parseIndexNameAndExtractDate("indexName-2019.09.04"); | ||
assertThat("indexName-yyyy.MM.dd is a valid index format", parsedDate, is(expectedDate)); | ||
} | ||
|
||
{ | ||
long parsedDate = parseIndexNameAndExtractDate("indexName-2019.09.04-0000001"); | ||
assertThat("indexName-yyyy.MM.dd-\\d+$ is a valid index format", parsedDate, is(expectedDate)); | ||
} | ||
|
||
{ | ||
long parsedDate = parseIndexNameAndExtractDate("indexName-2019.09.04-2019.09.24"); | ||
long secondDateInIndexName = dateFormat.parse("2019.09.24").getTime(); | ||
assertThat("indexName-yyyy.MM.dd-yyyy.MM.dd is a valid index format and the second date should be parsed", | ||
parsedDate, is(secondDateInIndexName)); | ||
} | ||
|
||
{ | ||
long parsedDate = parseIndexNameAndExtractDate("index-2019.09.04-2019.09.24-00002"); | ||
long secondDateInIndexName = dateFormat.parse("2019.09.24").getTime(); | ||
assertThat("indexName-yyyy.MM.dd-yyyy.MM.dd-digits is a valid index format and the second date should be parsed", | ||
parsedDate, is(secondDateInIndexName)); | ||
} | ||
} | ||
|
||
public void testParseIndexNameThrowsIllegalArgumentExceptionForInvalidIndexFormat() { | ||
expectThrows( | ||
IllegalArgumentException.class, | ||
"plainIndexName does not match the expected pattern", | ||
() -> parseIndexNameAndExtractDate("plainIndexName") | ||
); | ||
|
||
expectThrows( | ||
IllegalArgumentException.class, | ||
"indexName--00001 does not match the expected pattern as the origination date is missing", | ||
() -> parseIndexNameAndExtractDate("indexName--00001") | ||
); | ||
|
||
expectThrows( | ||
IllegalArgumentException.class, | ||
"indexName-00001 does not match the expected pattern as the origination date is missing", | ||
() -> parseIndexNameAndExtractDate("indexName-00001") | ||
); | ||
|
||
expectThrows( | ||
IllegalArgumentException.class, | ||
"indexName_2019.09.04_00001 does not match the expected pattern as _ is not the expected delimiter", | ||
() -> parseIndexNameAndExtractDate("indexName_2019.09.04_00001") | ||
); | ||
} | ||
|
||
public void testParseIndexNameThrowsIllegalArgumentExceptionForInvalidDateFormat() { | ||
expectThrows( | ||
IllegalArgumentException.class, | ||
"indexName-2019.04-00001 does not match the expected pattern as the date does not conform with the yyyy.MM.dd pattern", | ||
() -> parseIndexNameAndExtractDate("indexName-2019.04-00001") | ||
); | ||
|
||
expectThrows( | ||
IllegalArgumentException.class, | ||
"java.lang.IllegalArgumentException: failed to parse date field [2019.09.44] with format [yyyy.MM.dd]", | ||
() -> parseIndexNameAndExtractDate("index-2019.09.44") | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.