Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate index name time format setting at parse time #47911

Merged
merged 9 commits into from
Nov 5, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,26 @@ public Iterator<Setting<?>> settings() {
/**
* Every {@code Exporter} allows users to use a different index time format.
*/
private static final Setting.AffixSetting<String> INDEX_NAME_TIME_FORMAT_SETTING =
static final Setting.AffixSetting<String> INDEX_NAME_TIME_FORMAT_SETTING =
Setting.affixKeySetting("xpack.monitoring.exporters.","index.name.time_format",
key -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope));
key -> Setting.simpleString(
key,
Exporter.INDEX_FORMAT,
new Setting.Validator<String>() {
@Override
public void validate(String value) {
try {
if (value != null) {
DateFormatter.forPattern(value).withZone(ZoneOffset.UTC);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the generic type for this AffixSetting wrong? It seems like if we are going to parse into a DateFormatter, we should be doing that once, not duplicating here and in Exporter.dateTimeFormatter (where it also looks like we have default value logic?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rjernst, it is true that a DateFormatter instance is ultimately what is produced for this setting. I could change INDEX_NAME_TIME_FORMAT_SETTING from its original AffixSetting<String> to a AffixSetting<DateFormatter> if that would be preferable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes the most sense. In general, a major goal of the settings infrastructure is to do type parsing and validation for the intended type. In this case it seems we are adding checking, but the parsing isn't actually happening within the Setting instance.

}
} catch (RuntimeException e) {
throw new SettingsException("[" + INDEX_NAME_TIME_FORMAT_SETTING.getKey() +
"] invalid index name time format: [" + value + "]", e);
}
}
},
Property.Dynamic,
Property.NodeScope));

private static final String INDEX_FORMAT = "yyyy.MM.dd";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,19 @@ public void testHostsMustBeSetIfTypeIsHttp() {
assertThat(e.getCause(), hasToString(containsString("host list for [" + prefix + ".host] is empty")));
}

public void testIndexNameTimeFormatMustBeValid() {
final String prefix = "xpack.monitoring.exporters.example";
final String setting = ".index.name.time_format";
final String value = "yyyy.MM.dd.j";
final Settings settings = Settings.builder().put(prefix + setting, value).build();
final IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> Exporter.INDEX_NAME_TIME_FORMAT_SETTING.getConcreteSetting(prefix + setting).get(settings));
assertThat(e, hasToString(containsString("Failed to parse value [" + value + "] for setting [" + prefix + setting)));
assertThat(e.getCause(), instanceOf(SettingsException.class));
assertThat(e.getCause(), hasToString(containsString("invalid index name time format: [" + value + "]")));
}

public void testExporterIndexPattern() {
Exporter.Config config = mock(Exporter.Config.class);
when(config.name()).thenReturn("anything");
Expand Down