|
6 | 6 |
|
7 | 7 | import _ from 'lodash'; |
8 | 8 | import semver from 'semver'; |
| 9 | +import { Duration } from 'moment'; |
9 | 10 | // @ts-ignore |
10 | 11 | import numeral from '@elastic/numeral'; |
11 | 12 |
|
@@ -433,7 +434,7 @@ export function basicJobValidation( |
433 | 434 | messages.push({ id: 'bucket_span_empty' }); |
434 | 435 | valid = false; |
435 | 436 | } else { |
436 | | - if (isValidTimeFormat(job.analysis_config.bucket_span)) { |
| 437 | + if (isValidTimeInterval(job.analysis_config.bucket_span)) { |
437 | 438 | messages.push({ |
438 | 439 | id: 'bucket_span_valid', |
439 | 440 | bucketSpan: job.analysis_config.bucket_span, |
@@ -490,14 +491,14 @@ export function basicDatafeedValidation(datafeed: Datafeed): ValidationResults { |
490 | 491 |
|
491 | 492 | if (datafeed) { |
492 | 493 | let queryDelayMessage = { id: 'query_delay_valid' }; |
493 | | - if (isValidTimeFormat(datafeed.query_delay) === false) { |
| 494 | + if (isValidTimeInterval(datafeed.query_delay) === false) { |
494 | 495 | queryDelayMessage = { id: 'query_delay_invalid' }; |
495 | 496 | valid = false; |
496 | 497 | } |
497 | 498 | messages.push(queryDelayMessage); |
498 | 499 |
|
499 | 500 | let frequencyMessage = { id: 'frequency_valid' }; |
500 | | - if (isValidTimeFormat(datafeed.frequency) === false) { |
| 501 | + if (isValidTimeInterval(datafeed.frequency) === false) { |
501 | 502 | frequencyMessage = { id: 'frequency_invalid' }; |
502 | 503 | valid = false; |
503 | 504 | } |
@@ -591,12 +592,33 @@ export function validateGroupNames(job: Job): ValidationResults { |
591 | 592 | }; |
592 | 593 | } |
593 | 594 |
|
594 | | -function isValidTimeFormat(value: string | undefined): boolean { |
| 595 | +/** |
| 596 | + * Parses the supplied string to a time interval suitable for use in an ML anomaly |
| 597 | + * detection job or datafeed. |
| 598 | + * @param value the string to parse |
| 599 | + * @return {Duration} the parsed interval, or null if it does not represent a valid |
| 600 | + * time interval. |
| 601 | + */ |
| 602 | +export function parseTimeIntervalForJob(value: string | undefined): Duration | null { |
| 603 | + if (value === undefined) { |
| 604 | + return null; |
| 605 | + } |
| 606 | + |
| 607 | + // Must be a valid interval, greater than zero, |
| 608 | + // and if specified in ms must be a multiple of 1000ms. |
| 609 | + const interval = parseInterval(value, true); |
| 610 | + return interval !== null && interval.asMilliseconds() !== 0 && interval.milliseconds() === 0 |
| 611 | + ? interval |
| 612 | + : null; |
| 613 | +} |
| 614 | + |
| 615 | +// Checks that the value for a field which represents a time interval, |
| 616 | +// such as a job bucket span or datafeed query delay, is valid. |
| 617 | +function isValidTimeInterval(value: string | undefined): boolean { |
595 | 618 | if (value === undefined) { |
596 | 619 | return true; |
597 | 620 | } |
598 | | - const interval = parseInterval(value); |
599 | | - return interval !== null && interval.asMilliseconds() !== 0; |
| 621 | + return parseTimeIntervalForJob(value) !== null; |
600 | 622 | } |
601 | 623 |
|
602 | 624 | // Returns the latest of the last source data and last processed bucket timestamp, |
|
0 commit comments