[ML] Forbid 'by' and 'over' as fieldnames for by/over (elastic/x-pack-elasticsearch#1007)
relates elastic/x-pack-elasticsearch#1002 Original commit: elastic/x-pack-elasticsearch@ba9005a58e
This commit is contained in:
parent
bf111dde7e
commit
8e2e26fc44
|
@ -137,6 +137,8 @@ public class Detector extends ToXContentToBytes implements Writeable {
|
|||
public static final String NON_NULL_SUM = "non_null_sum";
|
||||
public static final String LOW_NON_NULL_SUM = "low_non_null_sum";
|
||||
public static final String HIGH_NON_NULL_SUM = "high_non_null_sum";
|
||||
public static final String BY = "by";
|
||||
public static final String OVER = "over";
|
||||
/**
|
||||
* Population variance is called varp to match Splunk
|
||||
*/
|
||||
|
@ -674,7 +676,7 @@ public class Detector extends ToXContentToBytes implements Writeable {
|
|||
byFieldName));
|
||||
}
|
||||
|
||||
// by/over field names cannot be "count" - this requirement dates back to the early
|
||||
// by/over field names cannot be "count", "over', "by" - this requirement dates back to the early
|
||||
// days of the Splunk app and could be removed now BUT ONLY IF THE C++ CODE IS CHANGED
|
||||
// FIRST - see https://github.com/elastic/x-pack-elasticsearch/issues/858
|
||||
if (COUNT.equals(byFieldName)) {
|
||||
|
@ -686,6 +688,24 @@ public class Detector extends ToXContentToBytes implements Writeable {
|
|||
OVER_FIELD_NAME_FIELD.getPreferredName()));
|
||||
}
|
||||
|
||||
if (BY.equals(byFieldName)) {
|
||||
throw new IllegalArgumentException(Messages.getMessage(Messages.JOB_CONFIG_DETECTOR_BY_DISALLOWED,
|
||||
BY_FIELD_NAME_FIELD.getPreferredName()));
|
||||
}
|
||||
if (BY.equals(overFieldName)) {
|
||||
throw new IllegalArgumentException(Messages.getMessage(Messages.JOB_CONFIG_DETECTOR_BY_DISALLOWED,
|
||||
OVER_FIELD_NAME_FIELD.getPreferredName()));
|
||||
}
|
||||
|
||||
if (OVER.equals(byFieldName)) {
|
||||
throw new IllegalArgumentException(Messages.getMessage(Messages.JOB_CONFIG_DETECTOR_OVER_DISALLOWED,
|
||||
BY_FIELD_NAME_FIELD.getPreferredName()));
|
||||
}
|
||||
if (OVER.equals(overFieldName)) {
|
||||
throw new IllegalArgumentException(Messages.getMessage(Messages.JOB_CONFIG_DETECTOR_OVER_DISALLOWED,
|
||||
OVER_FIELD_NAME_FIELD.getPreferredName()));
|
||||
}
|
||||
|
||||
return new Detector(detectorDescription, function, fieldName, byFieldName, overFieldName, partitionFieldName,
|
||||
useNull, excludeFrequent, detectorRules);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,10 @@ public final class Messages {
|
|||
"{0} and {1} cannot be the same: ''{2}''";
|
||||
public static final String JOB_CONFIG_DETECTOR_COUNT_DISALLOWED =
|
||||
"''count'' is not a permitted value for {0}";
|
||||
public static final String JOB_CONFIG_DETECTOR_BY_DISALLOWED =
|
||||
"''by'' is not a permitted value for {0}";
|
||||
public static final String JOB_CONFIG_DETECTOR_OVER_DISALLOWED =
|
||||
"''over'' is not a permitted value for {0}";
|
||||
public static final String JOB_CONFIG_MAPPING_TYPE_CLASH =
|
||||
"A field has a different mapping type to an existing field with the same name. " +
|
||||
"Use the 'results_index_name' setting to assign the job to another index";
|
||||
|
|
|
@ -434,20 +434,20 @@ public class AnalysisConfigTests extends AbstractSerializingTestCase<AnalysisCon
|
|||
|
||||
// should work now
|
||||
Detector.Builder builder = new Detector.Builder("distinct_count", "somefield");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
new AnalysisConfig.Builder(Collections.singletonList(builder.build())).build();
|
||||
|
||||
builder = new Detector.Builder("info_content", "somefield");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
d = builder.build();
|
||||
new AnalysisConfig.Builder(Collections.singletonList(builder.build())).build();
|
||||
|
||||
builder.setByFieldName("by");
|
||||
builder.setByFieldName("by_field");
|
||||
new AnalysisConfig.Builder(Collections.singletonList(builder.build())).build();
|
||||
|
||||
try {
|
||||
builder = new Detector.Builder("made_up_function", "somefield");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
new AnalysisConfig.Builder(Collections.singletonList(builder.build())).build();
|
||||
assertTrue(false); // shouldn't get here
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
|
|
@ -24,15 +24,15 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
|
||||
public void testEquals_GivenEqual() {
|
||||
Detector.Builder builder = new Detector.Builder("mean", "field");
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.setPartitionFieldName("partition");
|
||||
builder.setUseNull(false);
|
||||
Detector detector1 = builder.build();
|
||||
|
||||
builder = new Detector.Builder("mean", "field");
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.setPartitionFieldName("partition");
|
||||
builder.setUseNull(false);
|
||||
Detector detector2 = builder.build();
|
||||
|
@ -60,7 +60,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
Detector.Builder builder = new Detector.Builder(detector2);
|
||||
builder.setByFieldName("by2");
|
||||
Condition condition = new Condition(Operator.GT, "5");
|
||||
DetectionRule rule = new DetectionRule("over", "targetValue", Connective.AND,
|
||||
DetectionRule rule = new DetectionRule("over_field", "targetValue", Connective.AND,
|
||||
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "by2", "val", condition, null)));
|
||||
builder.setDetectorRules(Collections.singletonList(rule));
|
||||
detector2 = builder.build();
|
||||
|
@ -82,19 +82,19 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
|
||||
public void testExtractAnalysisFields() {
|
||||
Detector detector = createDetector().build();
|
||||
assertEquals(Arrays.asList("by", "over", "partition"), detector.extractAnalysisFields());
|
||||
assertEquals(Arrays.asList("by_field", "over_field", "partition"), detector.extractAnalysisFields());
|
||||
Detector.Builder builder = new Detector.Builder(detector);
|
||||
builder.setPartitionFieldName(null);
|
||||
detector = builder.build();
|
||||
assertEquals(Arrays.asList("by", "over"), detector.extractAnalysisFields());
|
||||
assertEquals(Arrays.asList("by_field", "over_field"), detector.extractAnalysisFields());
|
||||
builder = new Detector.Builder(detector);
|
||||
Condition condition = new Condition(Operator.GT, "5");
|
||||
DetectionRule rule = new DetectionRule("over", "targetValue", Connective.AND,
|
||||
DetectionRule rule = new DetectionRule("over_field", "targetValue", Connective.AND,
|
||||
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, condition, null)));
|
||||
builder.setDetectorRules(Collections.singletonList(rule));
|
||||
builder.setByFieldName(null);
|
||||
detector = builder.build();
|
||||
assertEquals(Arrays.asList("over"), detector.extractAnalysisFields());
|
||||
assertEquals(Arrays.asList("over_field"), detector.extractAnalysisFields());
|
||||
builder = new Detector.Builder(detector);
|
||||
rule = new DetectionRule(null, null, Connective.AND,
|
||||
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, null, null, condition, null)));
|
||||
|
@ -107,8 +107,8 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
public void testExtractReferencedLists() {
|
||||
Detector.Builder builder = createDetector();
|
||||
builder.setDetectorRules(Arrays.asList(
|
||||
new DetectionRule(null, null, Connective.OR, Arrays.asList(RuleCondition.createCategorical("by", "list1"))),
|
||||
new DetectionRule(null, null, Connective.OR, Arrays.asList(RuleCondition.createCategorical("by", "list2")))));
|
||||
new DetectionRule(null, null, Connective.OR, Arrays.asList(RuleCondition.createCategorical("by_field", "list1"))),
|
||||
new DetectionRule(null, null, Connective.OR, Arrays.asList(RuleCondition.createCategorical("by_field", "list2")))));
|
||||
|
||||
Detector detector = builder.build();
|
||||
assertEquals(new HashSet<>(Arrays.asList("list1", "list2")), detector.extractReferencedFilters());
|
||||
|
@ -116,13 +116,13 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
|
||||
private Detector.Builder createDetector() {
|
||||
Detector.Builder detector = new Detector.Builder("mean", "field");
|
||||
detector.setByFieldName("by");
|
||||
detector.setOverFieldName("over");
|
||||
detector.setByFieldName("by_field");
|
||||
detector.setOverFieldName("over_field");
|
||||
detector.setPartitionFieldName("partition");
|
||||
detector.setUseNull(true);
|
||||
Condition condition = new Condition(Operator.GT, "5");
|
||||
DetectionRule rule = new DetectionRule("over", "targetValue", Connective.AND,
|
||||
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "by", "val", condition, null)));
|
||||
DetectionRule rule = new DetectionRule("over_field", "targetValue", Connective.AND,
|
||||
Collections.singletonList(new RuleCondition(RuleConditionType.NUMERICAL_ACTUAL, "by_field", "val", condition, null)));
|
||||
detector.setDetectorRules(Arrays.asList(rule));
|
||||
return detector;
|
||||
}
|
||||
|
@ -261,16 +261,16 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
|
||||
private static Detector.Builder createDetectorWithValidFieldNames() {
|
||||
Detector.Builder d = new Detector.Builder("metric", "field");
|
||||
d.setByFieldName("by");
|
||||
d.setOverFieldName("over");
|
||||
d.setByFieldName("by_field");
|
||||
d.setOverFieldName("over_field");
|
||||
d.setPartitionFieldName("partition");
|
||||
return d;
|
||||
}
|
||||
|
||||
private static Detector.Builder createDetectorWithSpecificFieldName(String fieldName) {
|
||||
Detector.Builder d = new Detector.Builder("metric", fieldName);
|
||||
d.setByFieldName("by");
|
||||
d.setOverFieldName("over");
|
||||
d.setByFieldName("by_field");
|
||||
d.setOverFieldName("over_field");
|
||||
d.setPartitionFieldName("partition");
|
||||
return d;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
Detector.LOW_NON_ZERO_COUNT, Detector.LOW_NZC, Detector.HIGH_NON_ZERO_COUNT,
|
||||
Detector.HIGH_NZC}) {
|
||||
Detector.Builder builder = new Detector.Builder(f, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
try {
|
||||
builder.build();
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
|
@ -352,7 +352,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
difference.remove(Detector.TIME_OF_WEEK);
|
||||
for (String f : difference) {
|
||||
Detector.Builder builder = new Detector.Builder(f, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
try {
|
||||
builder.build();
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
|
@ -369,15 +369,15 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
for (String f : new String[]{Detector.COUNT, Detector.HIGH_COUNT,
|
||||
Detector.LOW_COUNT}) {
|
||||
Detector.Builder builder = new Detector.Builder(f, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
}
|
||||
|
||||
for (String f : new String[]{Detector.RARE, Detector.FREQ_RARE}) {
|
||||
Detector.Builder builder = new Detector.Builder(f, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
Detector.LOW_NON_NULL_SUM, Detector.HIGH_NON_NULL_SUM, Detector.POPULATION_VARIANCE,
|
||||
Detector.LOW_POPULATION_VARIANCE, Detector.HIGH_POPULATION_VARIANCE}) {
|
||||
Detector.Builder builder = new Detector.Builder(f, "f");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build();
|
||||
try {
|
||||
builder.build(true);
|
||||
|
@ -437,7 +437,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
difference.remove(Detector.LAT_LONG);
|
||||
for (String f : difference) {
|
||||
Detector.Builder builder = new Detector.Builder(f, "f");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
try {
|
||||
builder.build();
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
|
@ -461,12 +461,12 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
}
|
||||
|
||||
Detector.Builder builder = new Detector.Builder(Detector.FREQ_RARE, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.setByFieldName("b");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
builder = new Detector.Builder(Detector.FREQ_RARE, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.setByFieldName("b");
|
||||
builder.build();
|
||||
|
||||
|
@ -538,7 +538,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
|
||||
builder = new Detector.Builder(Detector.FREQ_RARE, "field");
|
||||
builder.setByFieldName("b");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
try {
|
||||
builder.build();
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
|
@ -554,7 +554,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
for (String f : new String[]{Detector.HIGH_COUNT,
|
||||
Detector.LOW_COUNT, Detector.NON_ZERO_COUNT, Detector.NZC}) {
|
||||
builder = new Detector.Builder(f, null);
|
||||
builder.setByFieldName("by");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
}
|
||||
|
@ -562,7 +562,7 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
for (String f : new String[]{Detector.COUNT, Detector.HIGH_COUNT,
|
||||
Detector.LOW_COUNT}) {
|
||||
builder = new Detector.Builder(f, null);
|
||||
builder.setOverFieldName("over");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
}
|
||||
|
@ -570,8 +570,8 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
for (String f : new String[]{Detector.HIGH_COUNT,
|
||||
Detector.LOW_COUNT}) {
|
||||
builder = new Detector.Builder(f, null);
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build();
|
||||
builder.build(true);
|
||||
}
|
||||
|
@ -579,16 +579,16 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
for (String f : new String[]{Detector.NON_ZERO_COUNT, Detector.NZC}) {
|
||||
try {
|
||||
builder = new Detector.Builder(f, "field");
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build();
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
try {
|
||||
builder = new Detector.Builder(f, "field");
|
||||
builder.setByFieldName("by");
|
||||
builder.setOverFieldName("over");
|
||||
builder.setByFieldName("by_field");
|
||||
builder.setOverFieldName("over_field");
|
||||
builder.build(true);
|
||||
Assert.fail("IllegalArgumentException not thrown when expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -666,6 +666,38 @@ public class DetectorTests extends AbstractSerializingTestCase<Detector> {
|
|||
assertEquals("'count' is not a permitted value for over_field_name", e.getMessage());
|
||||
}
|
||||
|
||||
public void testVerify_GivenByIsBy() {
|
||||
Detector.Builder detector = new Detector.Builder("count", "");
|
||||
detector.setByFieldName("by");
|
||||
IllegalArgumentException e = ESTestCase.expectThrows(IllegalArgumentException.class, detector::build);
|
||||
|
||||
assertEquals("'by' is not a permitted value for by_field_name", e.getMessage());
|
||||
}
|
||||
|
||||
public void testVerify_GivenOverIsBy() {
|
||||
Detector.Builder detector = new Detector.Builder("count", "");
|
||||
detector.setOverFieldName("by");
|
||||
IllegalArgumentException e = ESTestCase.expectThrows(IllegalArgumentException.class, detector::build);
|
||||
|
||||
assertEquals("'by' is not a permitted value for over_field_name", e.getMessage());
|
||||
}
|
||||
|
||||
public void testVerify_GivenByIsOver() {
|
||||
Detector.Builder detector = new Detector.Builder("count", "");
|
||||
detector.setByFieldName("over");
|
||||
IllegalArgumentException e = ESTestCase.expectThrows(IllegalArgumentException.class, detector::build);
|
||||
|
||||
assertEquals("'over' is not a permitted value for by_field_name", e.getMessage());
|
||||
}
|
||||
|
||||
public void testVerify_GivenOverIsOver() {
|
||||
Detector.Builder detector = new Detector.Builder("count", "");
|
||||
detector.setOverFieldName("over");
|
||||
IllegalArgumentException e = ESTestCase.expectThrows(IllegalArgumentException.class, detector::build);
|
||||
|
||||
assertEquals("'over' is not a permitted value for over_field_name", e.getMessage());
|
||||
}
|
||||
|
||||
public void testExcludeFrequentForString() {
|
||||
assertEquals(Detector.ExcludeFrequent.ALL, Detector.ExcludeFrequent.forString("all"));
|
||||
assertEquals(Detector.ExcludeFrequent.ALL, Detector.ExcludeFrequent.forString("ALL"));
|
||||
|
|
|
@ -161,10 +161,10 @@ public class JobTests extends AbstractSerializingTestCase<Job> {
|
|||
*/
|
||||
public void testAnalysisConfigRequiredFields() {
|
||||
Detector.Builder d1 = new Detector.Builder("max", "field");
|
||||
d1.setByFieldName("by");
|
||||
d1.setByFieldName("by_field");
|
||||
|
||||
Detector.Builder d2 = new Detector.Builder("metric", "field2");
|
||||
d2.setOverFieldName("over");
|
||||
d2.setOverFieldName("over_field");
|
||||
|
||||
AnalysisConfig.Builder ac = new AnalysisConfig.Builder(Arrays.asList(d1.build(), d2.build()));
|
||||
ac.setSummaryCountFieldName("agg");
|
||||
|
@ -174,9 +174,9 @@ public class JobTests extends AbstractSerializingTestCase<Job> {
|
|||
|
||||
assertTrue(analysisFields.contains("agg"));
|
||||
assertTrue(analysisFields.contains("field"));
|
||||
assertTrue(analysisFields.contains("by"));
|
||||
assertTrue(analysisFields.contains("by_field"));
|
||||
assertTrue(analysisFields.contains("field2"));
|
||||
assertTrue(analysisFields.contains("over"));
|
||||
assertTrue(analysisFields.contains("over_field"));
|
||||
|
||||
assertFalse(analysisFields.contains("max"));
|
||||
assertFalse(analysisFields.contains(""));
|
||||
|
@ -193,10 +193,10 @@ public class JobTests extends AbstractSerializingTestCase<Job> {
|
|||
|
||||
assertTrue(analysisFields.contains("partition"));
|
||||
assertTrue(analysisFields.contains("field"));
|
||||
assertTrue(analysisFields.contains("by"));
|
||||
assertTrue(analysisFields.contains("by_field"));
|
||||
assertTrue(analysisFields.contains("by2"));
|
||||
assertTrue(analysisFields.contains("field2"));
|
||||
assertTrue(analysisFields.contains("over"));
|
||||
assertTrue(analysisFields.contains("over_field"));
|
||||
|
||||
assertFalse(analysisFields.contains("count"));
|
||||
assertFalse(analysisFields.contains("max"));
|
||||
|
|
Loading…
Reference in New Issue