- { isFullScreenMode && }
+ {isFullScreenMode && }
);
}
-
-DashboardViewport.propTypes = {
- getEmbeddableFactory: PropTypes.func,
- maximizedPanelId: PropTypes.string,
- panelCount: PropTypes.number,
- title: PropTypes.string,
- description: PropTypes.string,
- useMargins: PropTypes.bool.isRequired,
-};
diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js b/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js
index 1f39cdf458216..c7cb877be676b 100644
--- a/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js
+++ b/src/legacy/core_plugins/kibana/public/dev_tools/directives/dev_tools_app.js
@@ -20,7 +20,6 @@
import { uiModules } from 'ui/modules';
import { DevToolsRegistryProvider } from 'ui/registry/dev_tools';
import template from '../partials/dev_tools_app.html';
-import 'ui/kbn_top_nav';
uiModules
.get('apps/dev_tools')
diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js
index 6e0e07104fa80..bf69fa09823f2 100644
--- a/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js
+++ b/src/legacy/core_plugins/kibana/public/dev_tools/hacks/__tests__/hide_empty_tools.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import chrome from 'ui/chrome';
diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/index.js b/src/legacy/core_plugins/kibana/public/dev_tools/index.js
index 27e388fe10e26..3218a6b823274 100644
--- a/src/legacy/core_plugins/kibana/public/dev_tools/index.js
+++ b/src/legacy/core_plugins/kibana/public/dev_tools/index.js
@@ -20,6 +20,7 @@
import uiRoutes from 'ui/routes';
import { DevToolsRegistryProvider } from 'ui/registry/dev_tools';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
+import 'ui/directives/kbn_href';
import './directives/dev_tools_app';
uiRoutes
diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js
index 211773a5ae867..50e9067b48367 100644
--- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js
+++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js
@@ -22,7 +22,7 @@ import angular from 'angular';
import _ from 'lodash';
import sinon from 'sinon';
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import 'ui/private';
import '../../components/field_chooser/discover_field';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js
index 46c77e26c0ac5..cce6127ed9c47 100644
--- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js
+++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js
@@ -21,7 +21,7 @@
import _ from 'lodash';
import ngMock from 'ng_mock';
import { fieldCalculator } from '../../components/field_chooser/lib/field_calculator';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import 'ui/private';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js
index 6920c058e1eac..f76a0ab72b212 100644
--- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js
+++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js
@@ -21,7 +21,7 @@ import angular from 'angular';
import ngMock from 'ng_mock';
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import $ from 'jquery';
import 'ui/private';
import '../../components/field_chooser/field_chooser';
diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js
deleted file mode 100644
index c73cd2b56f752..0000000000000
--- a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-import _ from 'lodash';
-import ngMock from 'ng_mock';
-import expect from 'expect.js';
-import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn';
-
-describe('hit sort function', function () {
- let createHitSortFn;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function (Private) {
- createHitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider);
- }));
-
-
- const runSortTest = function (dir, sortOpts) {
- const groupSize = _.random(10, 30);
- const total = sortOpts.length * groupSize;
-
- sortOpts = sortOpts.map(function (opt) {
- if (Array.isArray(opt)) return opt;
- else return [opt];
- });
- const sortOptLength = sortOpts.length;
-
- const hits = _.times(total, function (i) {
- return {
- _source: {},
- sort: sortOpts[i % sortOptLength]
- };
- });
-
- hits.sort(createHitSortFn(dir))
- .forEach(function (hit, i) {
- const group = Math.floor(i / groupSize);
- expect(hit.sort).to.eql(sortOpts[group]);
- });
- };
-
-
- it('sorts a list of hits in ascending order', function () {
- runSortTest('asc', [200, 404, 500]);
- });
-
- it('sorts a list of hits in descending order', function () {
- runSortTest('desc', [10, 3, 1]);
- });
-
- it('breaks ties in ascending order', function () {
- runSortTest('asc', [
- [ 'apache', 200, 'facebook.com' ],
- [ 'apache', 200, 'twitter.com' ],
- [ 'apache', 301, 'facebook.com' ],
- [ 'apache', 301, 'twitter.com' ],
- [ 'nginx', 200, 'facebook.com' ],
- [ 'nginx', 200, 'twitter.com' ],
- [ 'nginx', 301, 'facebook.com' ],
- [ 'nginx', 301, 'twitter.com' ]
- ]);
- });
-
- it('breaks ties in descending order', function () {
- runSortTest('desc', [
- [ 'nginx', 301, 'twitter.com' ],
- [ 'nginx', 301, 'facebook.com' ],
- [ 'nginx', 200, 'twitter.com' ],
- [ 'nginx', 200, 'facebook.com' ],
- [ 'apache', 301, 'twitter.com' ],
- [ 'apache', 301, 'facebook.com' ],
- [ 'apache', 200, 'twitter.com' ],
- [ 'apache', 200, 'facebook.com' ]
- ]);
- });
-});
diff --git a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js
deleted file mode 100644
index ce5311e46d655..0000000000000
--- a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
-export default function HitSortFnFactory() {
- /**
- * Creates a sort function that will resort hits based on the value
- * es used to sort them.
- *
- * background:
- * When a hit is sorted by elasticsearch, es will write the values that it used
- * to sort them into an array at the top level of the hit like so
- *
- * ```
- * hits: {
- * total: x,
- * hits: [
- * {
- * _id: i,
- * _source: {},
- * sort: [
- * // all values used to sort, in the order of precedence
- * ]
- * }
- * ]
- * };
- * ```
- *
- * @param {[type]} field [description]
- * @param {[type]} direction [description]
- * @return {[type]} [description]
- */
- return function createHitSortFn(direction) {
- const descending = (direction === 'desc');
-
- return function sortHits(hitA, hitB) {
- let bBelowa = null;
-
- const aSorts = hitA.sort || [];
- const bSorts = hitB.sort || [];
-
- // walk each sort value, and compare until one is different
- for (let i = 0; i < bSorts.length; i++) {
- const a = aSorts[i];
- const b = bSorts[i];
-
- if (a == null || b > a) {
- bBelowa = !descending;
- break;
- }
-
- if (b < a) {
- bBelowa = descending;
- break;
- }
- }
-
- if (bBelowa !== null) {
- return bBelowa ? -1 : 1;
- } else {
- return 0;
- }
-
- };
- };
-}
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
index 65b26da9afa4c..fcc8de845c334 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/_field_chooser.scss
@@ -2,3 +2,10 @@
color: $euiColorMediumShade;
margin-left: $euiSizeS !important;
}
+
+/*
+ Fixes EUI known issue https://github.com/elastic/eui/issues/1749
+*/
+.dscProgressBarTooltip__anchor {
+ display: block;
+}
\ No newline at end of file
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js
index 66b8eb8ab6cd2..1f4b3103af7c1 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js
@@ -22,6 +22,7 @@ import html from './discover_field.html';
import _ from 'lodash';
import 'ui/directives/css_truncate';
import 'ui/directives/field_name';
+import './string_progress_bar';
import detailsHtml from './lib/detail_views/string.html';
import { uiModules } from 'ui/modules';
const app = uiModules.get('apps/discover');
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html
index b0eb97ea5b62e..37786c3812ec5 100644
--- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html
@@ -77,15 +77,10 @@
-
-
- {{bucket.percent}}%
-
-
+
diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js
new file mode 100644
index 0000000000000..ae00df6dfbbf8
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js
@@ -0,0 +1,70 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import { wrapInI18nContext } from 'ui/i18n';
+import { uiModules } from 'ui/modules';
+
+import React from 'react';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiProgress,
+ EuiText,
+ EuiToolTip,
+} from '@elastic/eui';
+
+const module = uiModules.get('discover/field_chooser');
+
+function StringFieldProgressBar(props) {
+ return (
+
+
+
+
+
+
+
+ {props.percent}%
+
+
+
+
+ );
+}
+
+module.directive('stringFieldProgressBar', function (reactDirective) {
+ return reactDirective(wrapInI18nContext(StringFieldProgressBar));
+});
diff --git a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js
index 3c8da5dd3ab8f..a91ec2e5b446b 100644
--- a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js
+++ b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js
@@ -26,9 +26,9 @@ import * as columnActions from 'ui/doc_table/actions/columns';
import * as filterActions from 'ui/doc_table/actions/filter';
import dateMath from '@elastic/datemath';
import 'ui/doc_table';
+import 'ui/listen';
import 'ui/visualize';
import 'ui/fixed_scroll';
-import 'ui/directives/validate_json';
import 'ui/filters/moment';
import 'ui/index_patterns';
import 'ui/state_management/app_state';
@@ -39,7 +39,6 @@ import { toastNotifications } from 'ui/notify';
import { VisProvider } from 'ui/vis';
import { VislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib';
import { DocTitleProvider } from 'ui/doc_title';
-import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn';
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
import { intervalOptions } from 'ui/agg_types/buckets/_interval_options';
import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
@@ -67,6 +66,12 @@ import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_s
import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs';
import { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline';
+const fetchStatuses = {
+ UNINITIALIZED: 'uninitialized',
+ LOADING: 'loading',
+ COMPLETE: 'complete',
+};
+
const app = uiModules.get('apps/discover', [
'kibana/notify',
'kibana/courier',
@@ -170,7 +175,6 @@ function discoverController(
let visualizeHandler;
const Vis = Private(VisProvider);
const docTitle = Private(DocTitleProvider);
- const HitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider);
const queryFilter = Private(FilterBarQueryFilterProvider);
const responseHandler = Private(VislibSeriesResponseHandlerProvider).handler;
const filterManager = Private(FilterManagerProvider);
@@ -190,6 +194,7 @@ function discoverController(
$scope.intervalOptions = intervalOptions;
$scope.showInterval = false;
$scope.minimumVisibleRows = 50;
+ $scope.fetchStatus = fetchStatuses.UNINITIALIZED;
$scope.intervalEnabled = function (interval) {
return interval.val !== 'custom';
@@ -373,18 +378,16 @@ function discoverController(
const getFieldCounts = async () => {
// the field counts aren't set until we have the data back,
// so we wait for the fetch to be done before proceeding
- if (!$scope.fetchStatus) {
+ if ($scope.fetchStatus === fetchStatuses.COMPLETE) {
return $scope.fieldCounts;
}
return await new Promise(resolve => {
const unwatch = $scope.$watch('fetchStatus', (newValue) => {
- if (newValue) {
- return;
+ if (newValue === fetchStatuses.COMPLETE) {
+ unwatch();
+ resolve($scope.fieldCounts);
}
-
- unwatch();
- resolve($scope.fieldCounts);
});
});
};
@@ -567,13 +570,9 @@ function discoverController(
if (rows == null && oldRows == null) return status.LOADING;
const rowsEmpty = _.isEmpty(rows);
- // An undefined fetchStatus means the requests are still being
- // prepared to be sent. When all requests are completed,
- // fetchStatus is set to null, so it's important that we
- // specifically check for undefined to determine a loading status.
- const preparingForFetch = _.isUndefined(fetchStatus);
+ const preparingForFetch = fetchStatus === fetchStatuses.UNINITIALIZED;
if (preparingForFetch) return status.LOADING;
- else if (rowsEmpty && fetchStatus) return status.LOADING;
+ else if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING;
else if (!rowsEmpty) return status.READY;
else return status.NO_RESULTS;
}
@@ -662,6 +661,8 @@ function discoverController(
.then(setupVisualization)
.then(function () {
$state.save();
+ $scope.fetchStatus = fetchStatuses.LOADING;
+ logInspectorRequest();
return courier.fetch();
})
.catch(notify.error);
@@ -673,176 +674,72 @@ function discoverController(
$scope.fetch();
};
-
- function handleSegmentedFetch(segmented) {
- function flushResponseData() {
- $scope.fetchError = undefined;
- $scope.hits = 0;
- $scope.failures = [];
- $scope.rows = [];
- $scope.fieldCounts = {};
- }
-
- if (!$scope.rows) flushResponseData();
-
- const sort = $state.sort;
- const timeField = $scope.indexPattern.timeFieldName;
-
- /**
- * Basically an emum.
- *
- * opts:
- * "time" - sorted by the timefield
- * "non-time" - explicitly sorted by a non-time field, NOT THE SAME AS `sortBy !== "time"`
- * "implicit" - no sorting set, NOT THE SAME AS "non-time"
- *
- * @type {String}
- */
- const sortBy = (function () {
- if (!Array.isArray(sort)) return 'implicit';
- else if (sort[0] === '_score') return 'implicit';
- else if (sort[0] === timeField) return 'time';
- else return 'non-time';
- }());
-
- let sortFn = null;
- if (sortBy !== 'implicit') {
- sortFn = new HitSortFn(sort[1]);
- }
-
- $scope.updateTime();
-
- if (sort[0] === '_score') {
- segmented.setMaxSegments(1);
- }
-
- segmented.setDirection(sortBy === 'time' ? (sort[1] || 'desc') : 'desc');
- segmented.setSortFn(sortFn);
- segmented.setSize($scope.opts.sampleSize);
-
- let inspectorRequests = [];
- function logResponseInInspector(resp) {
- if (inspectorRequests.length > 0) {
- const inspectorRequest = inspectorRequests.shift();
- inspectorRequest
- .stats(getResponseInspectorStats($scope.searchSource, resp))
- .ok({ json: resp });
- }
- }
-
- // triggered when the status updated
- segmented.on('status', function (status) {
- $scope.fetchStatus = status;
- if (status.complete === 0) {
- // starting new segmented search request
- inspectorAdapters.requests.reset();
- inspectorRequests = [];
- }
-
- if (status.remaining > 0) {
- const inspectorRequest = inspectorAdapters.requests.start(
- i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle', {
- defaultMessage: 'Segment {fetchCompleteStatus}',
- values: {
- fetchCompleteStatus: $scope.fetchStatus.complete,
+ function onResults(resp) {
+ logInspectorResponse(resp);
+
+ if ($scope.opts.timefield) {
+ const tabifiedData = tabifyAggResponse($scope.vis.aggs, resp);
+ $scope.searchSource.rawResponse = resp;
+ Promise
+ .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource }))
+ .then(resp => responseHandler(tabifiedData, resp))
+ .then(resp => {
+ visualizeHandler.render({
+ as: 'visualization',
+ value: {
+ visType: $scope.vis.type.name,
+ visData: resp,
+ visConfig: $scope.vis.params,
+ params: {},
}
- }),
- {
- description: i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription', {
- defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.',
- }),
});
- inspectorRequest.stats(getRequestInspectorStats($scope.searchSource));
- $scope.searchSource.getSearchRequestBody().then(body => {
- inspectorRequest.json(body);
});
- inspectorRequests.push(inspectorRequest);
- }
-
- });
+ }
- segmented.on('first', function () {
- flushResponseData();
- });
+ $scope.hits = resp.hits.total;
+ $scope.rows = resp.hits.hits;
- segmented.on('segment', (resp) => {
- logResponseInInspector(resp);
- if (resp._shards.failed > 0) {
- $scope.failures = _.union($scope.failures, resp._shards.failures);
- $scope.failures = _.uniq($scope.failures, false, function (failure) {
- return failure.index + failure.shard + failure.reason;
- });
- }
- });
+ // if we haven't counted yet, reset the counts
+ const counts = $scope.fieldCounts = $scope.fieldCounts || {};
- segmented.on('emptySegment', function (resp) {
- logResponseInInspector(resp);
+ $scope.rows.forEach(hit => {
+ const fields = Object.keys($scope.indexPattern.flattenHit(hit));
+ fields.forEach(fieldName => {
+ counts[fieldName] = (counts[fieldName] || 0) + 1;
+ });
});
- segmented.on('mergedSegment', function (merged) {
- $scope.mergedEsResp = merged;
-
- if ($scope.opts.timefield) {
- const tabifiedData = tabifyAggResponse($scope.vis.aggs, merged);
- $scope.searchSource.rawResponse = merged;
- Promise
- .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource }))
- .then(resp => responseHandler(tabifiedData, resp))
- .then(resp => {
- visualizeHandler.render({
- as: 'visualization',
- value: {
- visType: $scope.vis.type.name,
- visData: resp,
- visConfig: $scope.vis.params,
- params: {},
- }
- });
- });
- }
-
- $scope.hits = merged.hits.total;
-
- const indexPattern = $scope.searchSource.getField('index');
-
- // the merge rows, use a new array to help watchers
- $scope.rows = merged.hits.hits.slice();
+ $scope.fetchStatus = fetchStatuses.COMPLETE;
- let counts = $scope.fieldCounts;
-
- // if we haven't counted yet, or need a fresh count because we are sorting, reset the counts
- if (!counts || sortFn) counts = $scope.fieldCounts = {};
-
- $scope.rows.forEach(function (hit) {
- // skip this work if we have already done it
- if (hit.$$_counted) return;
+ return $scope.searchSource.onResults().then(onResults);
+ }
- // when we are sorting results, we need to redo the counts each time because the
- // "top 500" may change with each response, so don't mark this as counted
- if (!sortFn) hit.$$_counted = true;
+ let inspectorRequest;
- const fields = _.keys(indexPattern.flattenHit(hit));
- let n = fields.length;
- let field;
- while (field = fields[--n]) {
- if (counts[field]) counts[field] += 1;
- else counts[field] = 1;
- }
- });
+ function logInspectorRequest() {
+ inspectorAdapters.requests.reset();
+ const title = i18n('kbn.discover.inspectorRequestDataTitle', {
+ defaultMessage: 'Data',
});
-
- segmented.on('complete', function () {
- if ($scope.fetchStatus.hitCount === 0) {
- flushResponseData();
- }
-
- $scope.fetchStatus = null;
+ const description = i18n('kbn.discover.inspectorRequestDescription', {
+ defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.',
+ });
+ inspectorRequest = inspectorAdapters.requests.start(title, { description });
+ inspectorRequest.stats(getRequestInspectorStats($scope.searchSource));
+ $scope.searchSource.getSearchRequestBody().then(body => {
+ inspectorRequest.json(body);
});
}
+ function logInspectorResponse(resp) {
+ inspectorRequest
+ .stats(getResponseInspectorStats($scope.searchSource, resp))
+ .ok({ json: resp });
+ }
- function beginSegmentedFetch() {
- $scope.searchSource.onBeginSegmentedFetch(handleSegmentedFetch)
+ function startSearching() {
+ return $scope.searchSource.onResults()
+ .then(onResults)
.catch((error) => {
const fetchError = getPainlessError(error);
@@ -853,10 +750,11 @@ function discoverController(
}
// Restart. This enables auto-refresh functionality.
- beginSegmentedFetch();
+ startSearching();
});
}
- beginSegmentedFetch();
+
+ startSearching();
$scope.updateTime = function () {
$scope.timeRange = {
diff --git a/src/legacy/core_plugins/kibana/public/discover/index.html b/src/legacy/core_plugins/kibana/public/discover/index.html
index ecd6dcf5e6772..4def63c620d49 100644
--- a/src/legacy/core_plugins/kibana/public/discover/index.html
+++ b/src/legacy/core_plugins/kibana/public/discover/index.html
@@ -101,8 +101,6 @@
-
-
{{fetchStatus.complete}} / {{fetchStatus.total}}
diff --git a/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js b/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js
index a529650ae96a4..69ca21b2cf869 100644
--- a/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js
+++ b/src/legacy/core_plugins/kibana/public/doc/__tests__/doc.js
@@ -19,7 +19,7 @@
// Load the kibana app dependencies.
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import '..';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
import { timefilter } from 'ui/timefilter';
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js
index b02c87b1c111d..24c67c0dccbf3 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('Boolean Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js
index bebe202bf82d5..329624269ae1d 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('Color Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js
index 9e1f6015bd35f..e84d5e217cf7c 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_conformance.js
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import chrome from 'ui/chrome';
import { fieldFormats } from 'ui/registry/field_formats';
import { FieldFormat } from '../../../../../ui/field_formats/field_format';
@@ -43,7 +43,7 @@ const formatIds = [
'static_lookup'
];
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
+// eslint-disable-next-line @kbn/eslint/no-default-export
export default describe('conformance', function () {
const getConfig = (...args) => config.get(...args);
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js
index ac49c93f63cb5..33b3a4d4c73cf 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import moment from 'moment-timezone';
import { fieldFormats } from 'ui/registry/field_formats';
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js
index d12c616bec6e2..baa45caa4bcc3 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('Duration Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js
index a7b920f9eda1f..529bcf772a488 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('IP Address Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js
index 4726c3993771e..e254487679574 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js
@@ -19,7 +19,7 @@
import $ from 'jquery';
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { fieldFormats } from 'ui/registry/field_formats';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js
index c779c164b7d16..e4e11e288d1f4 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('String Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js
index d5c89f98182b8..0db4c844e2917 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('String Truncate Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js
index e00131caa84db..b62ba4b147cf2 100644
--- a/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js
+++ b/src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js
@@ -18,7 +18,7 @@
*/
import $ from 'jquery';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { fieldFormats } from 'ui/registry/field_formats';
describe('Url Format', function () {
diff --git a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap
index 4daa4eeebf4ab..ce99cbbf5408f 100644
--- a/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/home/components/__snapshots__/add_data.test.js.snap
@@ -47,9 +47,16 @@ exports[`apmUiEnabled 1`] = `
>
+ APM automatically collects in-depth performance metrics and errors from inside your applications.
+
+ }
footer={
+ Ingest logs from popular data sources and easily visualize in preconfigured dashboards.
+
+ }
footer={
+ Collect metrics from the operating system and services running on your servers.
+
+ }
footer={
+ Centralize security events for interactive investigation in ready-to-go visualizations.
+
+ }
footer={
+ Ingest logs from popular data sources and easily visualize in preconfigured dashboards.
+
+ }
footer={
+ Collect metrics from the operating system and services running on your servers.
+
+ }
footer={
+ Centralize security events for interactive investigation in ready-to-go visualizations.
+
+ }
footer={
+ APM automatically collects in-depth performance metrics and errors from inside your applications.
+
+ }
footer={
+ Ingest logs from popular data sources and easily visualize in preconfigured dashboards.
+
+ }
footer={
+ Collect metrics from the operating system and services running on your servers.
+
+ }
footer={
+ Centralize security events for interactive investigation in ready-to-go visualizations.
+
+ }
footer={
+ Ingest logs from popular data sources and easily visualize in preconfigured dashboards.
+
+ }
footer={
+ Collect metrics from the operating system and services running on your servers.
+
+ }
footer={
+ Centralize security events for interactive investigation in ready-to-go visualizations.
+
+ }
footer={
{
const renderCards = () => {
- const apmTitle = intl.formatMessage({
- id: 'kbn.home.addData.apm.nameTitle', defaultMessage: 'APM'
- });
- const apmDescription = intl.formatMessage({
- id: 'kbn.home.addData.apm.nameDescription',
- defaultMessage: 'APM automatically collects in-depth performance metrics and errors from inside your applications.'
- });
- const loggingTitle = intl.formatMessage({
- id: 'kbn.home.addData.logging.nameTitle', defaultMessage: 'Logging'
- });
- const loggingDescription = intl.formatMessage({
- id: 'kbn.home.addData.logging.nameDescription',
- defaultMessage: 'Ingest logs from popular data sources and easily visualize in preconfigured dashboards.'
- });
- const metricsTitle = intl.formatMessage({
- id: 'kbn.home.addData.metrics.nameTitle', defaultMessage: 'Metrics'
- });
- const metricsDescription = intl.formatMessage({
- id: 'kbn.home.addData.metrics.nameDescription',
- defaultMessage: 'Collect metrics from the operating system and services running on your servers.'
- });
- const securityTitle = intl.formatMessage({
- id: 'kbn.home.addData.security.nameTitle', defaultMessage: 'Security analytics'
- });
- const securityDescription = intl.formatMessage({
- id: 'kbn.home.addData.security.nameDescription',
- defaultMessage: 'Centralize security events for interactive investigation in ready-to-go visualizations.'
- });
+ const ampData = {
+ title: intl.formatMessage({
+ id: 'kbn.home.addData.apm.nameTitle', defaultMessage: 'APM'
+ }),
+ description: intl.formatMessage({
+ id: 'kbn.home.addData.apm.nameDescription',
+ defaultMessage: 'APM automatically collects in-depth performance metrics and errors from inside your applications.'
+ }),
+ ariaDescribedby: 'aria-describedby.addAmpButtonLabel'
+ };
+ const loggingData = {
+ title: intl.formatMessage({
+ id: 'kbn.home.addData.logging.nameTitle', defaultMessage: 'Logging'
+ }),
+ description: intl.formatMessage({
+ id: 'kbn.home.addData.logging.nameDescription',
+ defaultMessage: 'Ingest logs from popular data sources and easily visualize in preconfigured dashboards.'
+ }),
+ ariaDescribedby: 'aria-describedby.addLogDataButtonLabel'
+ };
+ const metricsData = {
+ title: intl.formatMessage({
+ id: 'kbn.home.addData.metrics.nameTitle', defaultMessage: 'Metrics'
+ }),
+ description: intl.formatMessage({
+ id: 'kbn.home.addData.metrics.nameDescription',
+ defaultMessage: 'Collect metrics from the operating system and services running on your servers.'
+ }),
+ ariaDescribedby: 'aria-describedby.addMetricsButtonLabel'
+ };
+ const securityData = {
+ title: intl.formatMessage({
+ id: 'kbn.home.addData.security.nameTitle', defaultMessage: 'Security analytics'
+ }),
+ description: intl.formatMessage({
+ id: 'kbn.home.addData.security.nameDescription',
+ defaultMessage: 'Centralize security events for interactive investigation in ready-to-go visualizations.'
+ }),
+ ariaDescribedby: 'aria-describedby.addSecurityButtonLabel'
+ };
const getApmCard = () => (
}
- title={apmTitle}
- description={apmDescription}
+ title={ampData.title}
+ description={{ampData.description}}
footer={
{
}
- title={loggingTitle}
- description={loggingDescription}
+ title={loggingData.title}
+ description={{loggingData.description}}
footer={
{
}
- title={metricsTitle}
- description={metricsDescription}
+ title={metricsData.title}
+ description={{metricsData.description}}
footer={
{
}
- title={securityTitle}
- description={securityDescription}
+ title={securityData.title}
+ description={{securityData.description}}
footer={
config.get(...args);
+ const docTitle = Private(DocTitleProvider);
const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider);
const kbnUrl = Private(KbnUrlProvider);
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
index a9184977dc802..c3cd781279bd8 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js
@@ -20,6 +20,7 @@
import _ from 'lodash';
import './index_header';
import './create_edit_field';
+import { DocTitleProvider } from 'ui/doc_title';
import { KbnUrlProvider } from 'ui/url';
import { IndicesEditSectionsProvider } from './edit_sections';
import { fatalError, toastNotifications } from 'ui/notify';
@@ -170,7 +171,7 @@ uiRoutes
uiModules.get('apps/management')
.controller('managementIndexPatternsEdit', function (
- $scope, $location, $route, config, indexPatterns, Private, AppState, docTitle, confirmModal) {
+ $scope, $location, $route, config, indexPatterns, Private, AppState, confirmModal) {
const $state = $scope.state = new AppState();
const { fieldWildcardMatcher } = Private(FieldWildcardProvider);
const indexPatternListProvider = Private(IndexPatternListFactory)();
@@ -182,6 +183,7 @@ uiModules.get('apps/management')
$scope.indexPatternListProvider = indexPatternListProvider;
$scope.indexPattern.tags = indexPatternListProvider.getIndexPatternTags($scope.indexPattern);
$scope.getFieldInfo = indexPatternListProvider.getFieldInfo;
+ const docTitle = Private(DocTitleProvider);
docTitle.change($scope.indexPattern.title);
const otherPatterns = _.filter($route.current.locals.indexPatterns, pattern => {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js
index f3b15caa92637..d12e0649ec8c5 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { DEFAULT_CATEGORY } from '../default_category';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js
index 59606b6677b40..e71cf3459a8da 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getAriaName } from '../get_aria_name';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js
index 939eca86afed2..d517e82395373 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getCategoryName } from '../get_category_name';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js
index 212e9c94f37e9..ac6436590fd9b 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getValType } from '../get_val_type';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js
index d668c6ff1dbc8..043230d5f9eab 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isDefaultValue } from '../is_default_value';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js
index 428b9852ff842..ad1ba30ece4b1 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { toEditableConfig } from '../to_editable_config';
describe('Settings', function () {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
index 62e764f60eae6..a84a805b2f1b9 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js
@@ -25,6 +25,7 @@ import 'ui/visualize';
import 'ui/collapsible_sidebar';
import 'ui/search_bar';
import 'ui/apply_filters';
+import 'ui/listen';
import chrome from 'ui/chrome';
import React from 'react';
import angular from 'angular';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/index.js b/src/legacy/core_plugins/kibana/public/visualize/index.js
index 14c1e48d04fe0..2d79e7f55c79d 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/index.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/index.js
@@ -24,6 +24,7 @@ import 'ui/draggable/draggable_handle';
import './saved_visualizations/_saved_vis';
import './saved_visualizations/saved_visualizations';
import 'ui/filters/sort_prefix_first';
+import 'ui/filter_bar';
import uiRoutes from 'ui/routes';
import visualizeListingTemplate from './listing/visualize_listing.html';
import { VisualizeListingController } from './listing/visualize_listing';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
index 35fa7761f3ba9..b904a59e690c4 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
+++ b/src/legacy/core_plugins/kibana/public/visualize/listing/visualize_listing.js
@@ -20,6 +20,7 @@
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import 'ui/pager_control';
import 'ui/pager';
+import 'ui/directives/kbn_href';
import { uiModules } from 'ui/modules';
import { timefilter } from 'ui/timefilter';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
index bc0bdddfdbc53..b638849ae0d62 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
@@ -162,7 +162,9 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
data-focus-lock-disabled="false"
>
@@ -89,7 +89,7 @@
type="number"
class="form-control"
name="range.to"
- greater-or-equal-than="{{range.from}}"
+ greater-or-equal-than="range.from"
required
step="any" />
diff --git a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js
index 76a709f5df24f..20ad8954f9617 100644
--- a/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js
+++ b/src/legacy/core_plugins/metric_vis/public/metric_vis_params.js
@@ -18,6 +18,7 @@
*/
import { uiModules } from 'ui/modules';
+import 'ui/directives/inequality';
import metricVisParamsTemplate from './metric_vis_params.html';
import _ from 'lodash';
const module = uiModules.get('kibana');
@@ -54,7 +55,7 @@ module.directive('metricVisParams', function (i18n) {
};
$scope.getGreaterThan = function (index) {
- if (index === 0) return 0;
+ if (index === 0) return -Infinity;
return $scope.editorState.params.metric.colorsRange[index - 1].to;
};
diff --git a/src/legacy/core_plugins/metrics/index.js b/src/legacy/core_plugins/metrics/index.js
index b0b3dbb8377e0..076d98931e328 100644
--- a/src/legacy/core_plugins/metrics/index.js
+++ b/src/legacy/core_plugins/metrics/index.js
@@ -31,6 +31,7 @@ export default function (kibana) {
visTypes: [
'plugins/metrics/kbn_vis_types',
],
+ interpreter: ['plugins/metrics/tsvb_fn'],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
},
diff --git a/src/legacy/core_plugins/metrics/public/components/vis_editor.js b/src/legacy/core_plugins/metrics/public/components/vis_editor.js
index 5c53bddf9bd27..c1701552a8936 100644
--- a/src/legacy/core_plugins/metrics/public/components/vis_editor.js
+++ b/src/legacy/core_plugins/metrics/public/components/vis_editor.js
@@ -1,173 +1,169 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import * as Rx from 'rxjs';
-import { share } from 'rxjs/operators';
-import VisEditorVisualization from './vis_editor_visualization';
-import Visualization from './visualization';
-import VisPicker from './vis_picker';
-import PanelConfig from './panel_config';
-import brushHandler from '../lib/create_brush_handler';
-import { fetchIndexPatternFields } from '../lib/fetch_fields';
-
-class VisEditor extends Component {
- constructor(props) {
- super(props);
- const { vis } = props;
- this.appState = vis.API.getAppState();
- this.state = {
- model: props.visParams,
- dirty: false,
- autoApply: true,
- visFields: props.visFields
- };
- this.onBrush = brushHandler(props.vis.API.timeFilter);
- this.visDataSubject = new Rx.Subject();
- this.visData$ = this.visDataSubject.asObservable().pipe(share());
- }
-
- get uiState() {
- return this.props.vis.getUiState();
- }
-
- getConfig = (...args) => {
- return this.props.config.get(...args);
- };
-
- handleUiState = (field, value) => {
- this.props.vis.uiStateVal(field, value);
- };
-
- handleChange = async (partialModel) => {
- const nextModel = { ...this.state.model, ...partialModel };
- this.props.vis.params = nextModel;
- if (this.state.autoApply) {
- this.props.vis.updateState();
- }
- this.setState({
- model: nextModel,
- dirty: !this.state.autoApply
- });
- const { params, fields } = this.props.vis;
- fetchIndexPatternFields(params, fields).then(visFields => {
- this.setState({ visFields });
- });
- };
-
- handleCommit = () => {
- this.props.vis.updateState();
- this.setState({ dirty: false });
- };
-
- handleAutoApplyToggle = (event) => {
- this.setState({ autoApply: event.target.checked });
- };
-
- onDataChange = ({ visData }) => {
- this.visDataSubject.next(visData);
- };
-
- render() {
- if (!this.props.isEditorMode) {
- if (!this.props.visParams || !this.props.visData) {
- return null;
- }
- return (
-
- );
- }
-
- const { model } = this.state;
-
- if (model) {
- return (
-
-
-
-
-
-
-
-
-
- );
- }
-
- return null;
- }
-
- componentDidMount() {
- this.props.renderComplete();
- }
-
- componentDidUpdate() {
- this.props.renderComplete();
- }
-}
-
-VisEditor.defaultProps = {
- visData: {}
-};
-
-VisEditor.propTypes = {
- vis: PropTypes.object,
- visData: PropTypes.object,
- visFields: PropTypes.object,
- renderComplete: PropTypes.func,
- config: PropTypes.object,
- isEditorMode: PropTypes.bool,
- savedObj: PropTypes.object,
- timeRange: PropTypes.object,
-};
-
-export default VisEditor;
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import * as Rx from 'rxjs';
+import { share } from 'rxjs/operators';
+import VisEditorVisualization from './vis_editor_visualization';
+import Visualization from './visualization';
+import VisPicker from './vis_picker';
+import PanelConfig from './panel_config';
+import brushHandler from '../lib/create_brush_handler';
+import { fetchIndexPatternFields } from '../lib/fetch_fields';
+
+class VisEditor extends Component {
+ constructor(props) {
+ super(props);
+ const { vis } = props;
+ this.appState = vis.API.getAppState();
+ this.state = {
+ model: props.visParams,
+ dirty: false,
+ autoApply: true,
+ visFields: props.visFields
+ };
+ this.onBrush = brushHandler(props.vis.API.timeFilter);
+ this.visDataSubject = new Rx.Subject();
+ this.visData$ = this.visDataSubject.asObservable().pipe(share());
+ }
+
+ get uiState() {
+ return this.props.vis.getUiState();
+ }
+
+ getConfig = (...args) => {
+ return this.props.config.get(...args);
+ };
+
+ handleUiState = (field, value) => {
+ this.props.vis.uiStateVal(field, value);
+ };
+
+ handleChange = async (partialModel) => {
+ const nextModel = { ...this.state.model, ...partialModel };
+ this.props.vis.params = nextModel;
+ if (this.state.autoApply) {
+ this.props.vis.updateState();
+ }
+ this.setState({
+ model: nextModel,
+ dirty: !this.state.autoApply
+ });
+ const { params, fields } = this.props.vis;
+ fetchIndexPatternFields(params, fields).then(visFields => {
+ this.setState({ visFields });
+ });
+ };
+
+ handleCommit = () => {
+ this.props.vis.updateState();
+ this.setState({ dirty: false });
+ };
+
+ handleAutoApplyToggle = (event) => {
+ this.setState({ autoApply: event.target.checked });
+ };
+
+ onDataChange = ({ visData }) => {
+ this.visDataSubject.next(visData);
+ };
+
+ render() {
+ if (!this.props.isEditorMode) {
+ if (!this.props.visParams || !this.props.visData) {
+ return null;
+ }
+ return (
+
+ );
+ }
+
+ const { model } = this.state;
+
+ if (model) {
+ return (
+
\ No newline at end of file
diff --git a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html
old mode 100755
new mode 100644
index b464bbb0f3090..eed4ca7d93016
--- a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html
+++ b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip-popup.html
@@ -1,4 +1,4 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js
index 94199dadb8dbd..b59b2922d8089 100755
--- a/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js
+++ b/src/legacy/ui/public/angular-bootstrap/tooltip/tooltip.js
@@ -1,9 +1,11 @@
+import './position';
+
/**
* The following features are still outstanding: animation as a
* function, placement as a function, inside, support for more triggers than
* just mouse enter/leave, html tooltips, and selector delegation.
*/
-angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] )
+angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] )
/**
* The $tooltip service creates tooltip- and popover-like directives as well as
@@ -345,28 +347,28 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap
}];
})
-.directive( 'tooltipPopup', function () {
- return {
- restrict: 'EA',
- replace: true,
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
- templateUrl: 'template/tooltip/tooltip-popup.html'
- };
-})
-
.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {
return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );
}])
-.directive( 'tooltipHtmlUnsafePopup', function () {
- return {
- restrict: 'EA',
- replace: true,
- scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
- templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
- };
+.directive( 'tooltipPopup', function () {
+ return {
+ restrict: 'EA',
+ replace: true,
+ scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
+ templateUrl: 'template/tooltip/tooltip-popup.html'
+ };
})
.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
-}]);
+}])
+
+.directive( 'tooltipHtmlUnsafePopup', function () {
+ return {
+ restrict: 'EA',
+ replace: true,
+ scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
+ templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
+ };
+});
\ No newline at end of file
diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html
deleted file mode 100755
index d79e10a18f8a0..0000000000000
--- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-match.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html
deleted file mode 100755
index e1bd0c1c476d8..0000000000000
--- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead-popup.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js b/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js
deleted file mode 100755
index 53d7162da84b2..0000000000000
--- a/src/legacy/ui/public/angular-bootstrap/typeahead/typeahead.js
+++ /dev/null
@@ -1,398 +0,0 @@
-angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])
-
-/**
- * A helper service that can parse typeahead's syntax (string provided by users)
- * Extracted to a separate service for ease of unit testing
- */
- .factory('typeaheadParser', ['$parse', function ($parse) {
-
- // 00000111000000000000022200000000000000003333333333333330000000000044000
- var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;
-
- return {
- parse:function (input) {
-
- var match = input.match(TYPEAHEAD_REGEXP);
- if (!match) {
- throw new Error(
- 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
- ' but got "' + input + '".');
- }
-
- return {
- itemName:match[3],
- source:$parse(match[4]),
- viewMapper:$parse(match[2] || match[1]),
- modelMapper:$parse(match[1])
- };
- }
- };
-}])
-
- .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser',
- function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) {
-
- var HOT_KEYS = [9, 13, 27, 38, 40];
-
- return {
- require:'ngModel',
- link:function (originalScope, element, attrs, modelCtrl) {
-
- //SUPPORTED ATTRIBUTES (OPTIONS)
-
- //minimal no of characters that needs to be entered before typeahead kicks-in
- var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
-
- //minimal wait time after last character typed before typehead kicks-in
- var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
-
- //should it restrict model values to the ones selected from the popup only?
- var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
-
- //binding to a variable that indicates if matches are being retrieved asynchronously
- var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
-
- //a callback executed when a match is selected
- var onSelectCallback = $parse(attrs.typeaheadOnSelect);
-
- var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
-
- var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;
-
- var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;
-
- //INTERNAL VARIABLES
-
- //model setter executed upon match selection
- var $setModelValue = $parse(attrs.ngModel).assign;
-
- //expressions used by typeahead
- var parserResult = typeaheadParser.parse(attrs.typeahead);
-
- var hasFocus;
-
- //create a child scope for the typeahead directive so we are not polluting original scope
- //with typeahead-specific data (matches, query etc.)
- var scope = originalScope.$new();
- originalScope.$on('$destroy', function(){
- scope.$destroy();
- });
-
- // WAI-ARIA
- var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
- element.attr({
- 'aria-autocomplete': 'list',
- 'aria-expanded': false,
- 'aria-owns': popupId
- });
-
- //pop-up element used to display matches
- var popUpEl = angular.element('');
- popUpEl.attr({
- id: popupId,
- matches: 'matches',
- active: 'activeIdx',
- select: 'select(activeIdx)',
- query: 'query',
- position: 'position'
- });
- //custom item template
- if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
- popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
- }
-
- var resetMatches = function() {
- scope.matches = [];
- scope.activeIdx = -1;
- element.attr('aria-expanded', false);
- };
-
- var getMatchId = function(index) {
- return popupId + '-option-' + index;
- };
-
- // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
- // This attribute is added or removed automatically when the `activeIdx` changes.
- scope.$watch('activeIdx', function(index) {
- if (index < 0) {
- element.removeAttr('aria-activedescendant');
- } else {
- element.attr('aria-activedescendant', getMatchId(index));
- }
- });
-
- var getMatchesAsync = function(inputValue) {
-
- var locals = {$viewValue: inputValue};
- isLoadingSetter(originalScope, true);
- $q.when(parserResult.source(originalScope, locals)).then(function(matches) {
-
- //it might happen that several async queries were in progress if a user were typing fast
- //but we are interested only in responses that correspond to the current view value
- var onCurrentRequest = (inputValue === modelCtrl.$viewValue);
- if (onCurrentRequest && hasFocus) {
- if (matches.length > 0) {
-
- scope.activeIdx = focusFirst ? 0 : -1;
- scope.matches.length = 0;
-
- //transform labels
- for(var i=0; i= minSearch) {
- if (waitTime > 0) {
- cancelPreviousTimeout();
- scheduleSearchWithTimeout(inputValue);
- } else {
- getMatchesAsync(inputValue);
- }
- } else {
- isLoadingSetter(originalScope, false);
- cancelPreviousTimeout();
- resetMatches();
- }
-
- if (isEditable) {
- return inputValue;
- } else {
- if (!inputValue) {
- // Reset in case user had typed something previously.
- modelCtrl.$setValidity('editable', true);
- return inputValue;
- } else {
- modelCtrl.$setValidity('editable', false);
- return undefined;
- }
- }
- });
-
- modelCtrl.$formatters.push(function (modelValue) {
-
- var candidateViewValue, emptyViewValue;
- var locals = {};
-
- if (inputFormatter) {
-
- locals.$model = modelValue;
- return inputFormatter(originalScope, locals);
-
- } else {
-
- //it might happen that we don't have enough info to properly render input value
- //we need to check for this situation and simply return model value if we can't apply custom formatting
- locals[parserResult.itemName] = modelValue;
- candidateViewValue = parserResult.viewMapper(originalScope, locals);
- locals[parserResult.itemName] = undefined;
- emptyViewValue = parserResult.viewMapper(originalScope, locals);
-
- return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
- }
- });
-
- scope.select = function (activeIdx) {
- //called from within the $digest() cycle
- var locals = {};
- var model, item;
-
- locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
- model = parserResult.modelMapper(originalScope, locals);
- $setModelValue(originalScope, model);
- modelCtrl.$setValidity('editable', true);
-
- onSelectCallback(originalScope, {
- $item: item,
- $model: model,
- $label: parserResult.viewMapper(originalScope, locals)
- });
-
- resetMatches();
-
- //return focus to the input element if a match was selected via a mouse click event
- // use timeout to avoid $rootScope:inprog error
- $timeout(function() { element[0].focus(); }, 0, false);
- };
-
- //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
- element.bind('keydown', function (evt) {
-
- //typeahead is open and an "interesting" key was pressed
- if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
- return;
- }
-
- // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything
- if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) {
- return;
- }
-
- evt.preventDefault();
-
- if (evt.which === 40) {
- scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
- scope.$digest();
-
- } else if (evt.which === 38) {
- scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
- scope.$digest();
-
- } else if (evt.which === 13 || evt.which === 9) {
- scope.$apply(function () {
- scope.select(scope.activeIdx);
- });
-
- } else if (evt.which === 27) {
- evt.stopPropagation();
-
- resetMatches();
- scope.$digest();
- }
- });
-
- element.bind('blur', function (evt) {
- hasFocus = false;
- });
-
- // Keep reference to click handler to unbind it.
- var dismissClickHandler = function (evt) {
- if (element[0] !== evt.target) {
- resetMatches();
- scope.$digest();
- }
- };
-
- $document.bind('click', dismissClickHandler);
-
- originalScope.$on('$destroy', function(){
- $document.unbind('click', dismissClickHandler);
- if (appendToBody) {
- $popup.remove();
- }
- });
-
- var $popup = $compile(popUpEl)(scope);
- if (appendToBody) {
- $document.find('body').append($popup);
- } else {
- element.after($popup);
- }
- }
- };
-
-}])
-
- .directive('typeaheadPopup', function () {
- return {
- restrict:'EA',
- scope:{
- matches:'=',
- query:'=',
- active:'=',
- position:'=',
- select:'&'
- },
- replace:true,
- templateUrl:'template/typeahead/typeahead-popup.html',
- link:function (scope, element, attrs) {
-
- scope.templateUrl = attrs.templateUrl;
-
- scope.isOpen = function () {
- return scope.matches.length > 0;
- };
-
- scope.isActive = function (matchIdx) {
- return scope.active == matchIdx;
- };
-
- scope.selectActive = function (matchIdx) {
- scope.active = matchIdx;
- };
-
- scope.selectMatch = function (activeIdx) {
- scope.select({activeIdx:activeIdx});
- };
- }
- };
- })
-
- .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {
- return {
- restrict:'EA',
- scope:{
- index:'=',
- match:'=',
- query:'='
- },
- link:function (scope, element, attrs) {
- var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';
- $http.get(tplUrl, {cache: $templateCache}).then(function(resp){
- element.replaceWith($compile(resp.data.trim())(scope));
- });
- }
- };
- }])
-
- .filter('typeaheadHighlight', function() {
-
- function escapeRegexp(queryToEscape) {
- return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
- }
-
- return function(matchItem, query) {
- return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem;
- };
- });
diff --git a/src/legacy/ui/public/autoload/all.js b/src/legacy/ui/public/autoload/all.js
index b1aa11cb72494..9ecfbfcf307c5 100644
--- a/src/legacy/ui/public/autoload/all.js
+++ b/src/legacy/ui/public/autoload/all.js
@@ -19,7 +19,6 @@
import './accessibility';
import './modules';
-import './directives';
import './filters';
import './settings';
import './styles';
diff --git a/src/legacy/ui/public/autoload/modules.js b/src/legacy/ui/public/autoload/modules.js
index 698d3ff8e27c0..511c2eed3dd9b 100644
--- a/src/legacy/ui/public/autoload/modules.js
+++ b/src/legacy/ui/public/autoload/modules.js
@@ -19,23 +19,10 @@
import 'angular';
import '../chrome';
-import '../bind';
-import '../kbn_top_nav';
-import '../bound_to_config_obj';
import '../config';
import '../courier';
-import '../debounce';
-import '../doc_title';
import '../es';
-import '../events';
-import '../fancy_forms';
-import '../filter_bar';
-import '../filter_manager';
-import '../index_patterns';
-import '../listen';
import '../notify';
-import '../parse_query';
-import '../persisted_log';
import '../private';
import '../promises';
import '../modals';
@@ -43,15 +30,11 @@ import '../state_management/app_state';
import '../state_management/global_state';
import '../storage';
import '../style_compile';
-import '../timefilter';
-import '../timepicker';
import '../tooltip';
import '../url';
import '../watch_multi';
-import '../saved_objects/ui/saved_object_save_as_checkbox';
import '../react_components';
import '../i18n';
-import '../query_bar/directive';
import '@elastic/ui-ace';
import { uiModules } from 'ui/modules';
diff --git a/src/legacy/ui/public/bind/__tests__/bind.js b/src/legacy/ui/public/bind/__tests__/bind.js
index ce59076df923d..e439ea7dbcdda 100644
--- a/src/legacy/ui/public/bind/__tests__/bind.js
+++ b/src/legacy/ui/public/bind/__tests__/bind.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
describe('$scope.$bind', function () {
diff --git a/src/legacy/ui/public/binder/__tests__/binder.js b/src/legacy/ui/public/binder/__tests__/binder.js
index 3a0ddff2137a4..703b9ec413313 100644
--- a/src/legacy/ui/public/binder/__tests__/binder.js
+++ b/src/legacy/ui/public/binder/__tests__/binder.js
@@ -18,7 +18,7 @@
*/
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { Binder } from '..';
diff --git a/src/legacy/ui/public/chrome/__tests__/nav_controls.js b/src/legacy/ui/public/chrome/__tests__/nav_controls.js
index cf664b943190c..9d43d83248703 100644
--- a/src/legacy/ui/public/chrome/__tests__/nav_controls.js
+++ b/src/legacy/ui/public/chrome/__tests__/nav_controls.js
@@ -19,7 +19,7 @@
import ngMock from 'ng_mock';
import $ from 'jquery';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { chromeNavControlsRegistry } from '../../registry/chrome_nav_controls';
import { uiRegistry } from '../../registry/_registry';
diff --git a/src/legacy/ui/public/chrome/api/__tests__/apps.js b/src/legacy/ui/public/chrome/api/__tests__/apps.js
index e640d1717c2cb..8515332efa36f 100644
--- a/src/legacy/ui/public/chrome/api/__tests__/apps.js
+++ b/src/legacy/ui/public/chrome/api/__tests__/apps.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import setup from '../apps';
diff --git a/src/legacy/ui/public/chrome/api/__tests__/nav.js b/src/legacy/ui/public/chrome/api/__tests__/nav.js
index 4b42c33ec8227..faf43058259e8 100644
--- a/src/legacy/ui/public/chrome/api/__tests__/nav.js
+++ b/src/legacy/ui/public/chrome/api/__tests__/nav.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { initChromeNavApi } from '../nav';
import { StubBrowserStorage } from 'test_utils/stub_browser_storage';
diff --git a/src/legacy/ui/public/chrome/api/__tests__/xsrf.js b/src/legacy/ui/public/chrome/api/__tests__/xsrf.js
index 27b8a400adf47..52da8fb545c7d 100644
--- a/src/legacy/ui/public/chrome/api/__tests__/xsrf.js
+++ b/src/legacy/ui/public/chrome/api/__tests__/xsrf.js
@@ -18,7 +18,7 @@
*/
import $ from 'jquery';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import ngMock from 'ng_mock';
diff --git a/src/legacy/ui/public/chrome/api/apps.js b/src/legacy/ui/public/chrome/api/apps.js
index feb339e163a64..7779b9612b63e 100644
--- a/src/legacy/ui/public/chrome/api/apps.js
+++ b/src/legacy/ui/public/chrome/api/apps.js
@@ -20,7 +20,7 @@
import { clone, get } from 'lodash';
import { resolve } from 'url';
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
+// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (chrome, internals) {
if (get(internals, 'app.navLink.url')) {
diff --git a/src/legacy/ui/public/chrome/api/template.js b/src/legacy/ui/public/chrome/api/template.js
index d1295dc8dddaa..58281c1af6c9d 100644
--- a/src/legacy/ui/public/chrome/api/template.js
+++ b/src/legacy/ui/public/chrome/api/template.js
@@ -17,7 +17,7 @@
* under the License.
*/
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
+// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (chrome, internals) {
/**
diff --git a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js b/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js
index fc411b5638b3b..5ce42b9c72916 100644
--- a/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js
+++ b/src/legacy/ui/public/chrome/directives/__tests__/sub_url_route_filter.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { SubUrlRouteFilterProvider } from '../sub_url_route_filter';
diff --git a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx
index d8426805f57ba..d8aec7997fdbf 100644
--- a/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx
+++ b/src/legacy/ui/public/chrome/directives/header_global_nav/components/header.tsx
@@ -54,6 +54,7 @@ import { HeaderBreadcrumbs } from './header_breadcrumbs';
import { HeaderHelpMenu } from './header_help_menu';
import { HeaderNavControls } from './header_nav_controls';
+import { i18n } from '@kbn/i18n';
import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
import chrome, { NavLink } from 'ui/chrome';
import { HelpExtension } from 'ui/chrome';
@@ -88,10 +89,23 @@ function extendRecentlyAccessedHistoryItem(
const href = relativeToAbsolute(chrome.addBasePath(recentlyAccessed.link));
const navLink = navLinks.find(nl => href.startsWith(nl.subUrlBase));
+ let titleAndAriaLabel = recentlyAccessed.label;
+ if (navLink) {
+ const objectTypeForAriaAppendix = navLink.title;
+ titleAndAriaLabel = i18n.translate('common.ui.recentLinks.linkItem.screenReaderLabel', {
+ defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}',
+ values: {
+ recentlyAccessedItemLinklabel: recentlyAccessed.label,
+ pageType: objectTypeForAriaAppendix,
+ },
+ });
+ }
+
return {
...recentlyAccessed,
href,
euiIconType: navLink ? navLink.euiIconType : undefined,
+ title: titleAndAriaLabel,
};
}
@@ -248,9 +262,8 @@ class HeaderUI extends Component {
}),
listItems: recentlyAccessed.map(item => ({
label: truncateRecentItemLabel(item.label),
- // TODO: Add what type of app/saved object to title attr
- title: `${item.label}`,
- 'aria-label': item.label,
+ title: item.title,
+ 'aria-label': item.title,
href: item.href,
iconType: item.euiIconType,
})),
diff --git a/src/legacy/ui/public/chrome/index.js b/src/legacy/ui/public/chrome/index.js
index ad62192704a1e..a322485b25513 100644
--- a/src/legacy/ui/public/chrome/index.js
+++ b/src/legacy/ui/public/chrome/index.js
@@ -19,5 +19,5 @@
import { chrome } from './chrome';
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
+// eslint-disable-next-line @kbn/eslint/no-default-export
export default chrome;
diff --git a/src/legacy/ui/public/config/__tests__/config.js b/src/legacy/ui/public/config/__tests__/config.js
index 55dcbd65880f8..52a573417f3c5 100644
--- a/src/legacy/ui/public/config/__tests__/config.js
+++ b/src/legacy/ui/public/config/__tests__/config.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import ngMock from 'ng_mock';
diff --git a/src/legacy/ui/public/courier/courier.js b/src/legacy/ui/public/courier/courier.js
index 2689f914065c9..f34f47e0571be 100644
--- a/src/legacy/ui/public/courier/courier.js
+++ b/src/legacy/ui/public/courier/courier.js
@@ -22,6 +22,7 @@ import _ from 'lodash';
import { timefilter } from 'ui/timefilter';
import '../es';
+import '../listen';
import '../index_patterns';
import { uiModules } from '../modules';
import { addFatalErrorCallback } from '../notify';
diff --git a/src/legacy/ui/public/courier/fetch/__tests__/call_client.js b/src/legacy/ui/public/courier/fetch/__tests__/call_client.js
index ec261d65dd6fa..bdaef283f2d35 100644
--- a/src/legacy/ui/public/courier/fetch/__tests__/call_client.js
+++ b/src/legacy/ui/public/courier/fetch/__tests__/call_client.js
@@ -18,7 +18,7 @@
*/
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import NoDigestPromises from 'test_utils/no_digest_promises';
import { delay } from 'bluebird';
diff --git a/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js b/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js
index 079a7893785f0..19032ce1f4ca3 100644
--- a/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js
+++ b/src/legacy/ui/public/courier/fetch/__tests__/fetch_now.js
@@ -18,7 +18,7 @@
*/
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { CallClientProvider } from '../call_client';
diff --git a/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js b/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js
index aeddc6e065455..ecac8cd474098 100644
--- a/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js
+++ b/src/legacy/ui/public/courier/fetch/request/search_request/__tests__/search_request.js
@@ -19,7 +19,7 @@
import ngMock from 'ng_mock';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { SearchRequestProvider } from '../search_request';
import { searchRequestQueue } from '../../../../search_request_queue';
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js
deleted file mode 100644
index 714bbb340969d..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import sinon from 'sinon';
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-
-import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
-
-import { SegmentedSearchRequestProvider } from '../segmented_search_request';
-
-describe('SegmentedSearchRequest _createQueue', () => {
- let Promise;
- let SegmentedSearchRequest;
- let MockSource;
-
- require('test_utils/no_digest_promises').activateForSuite();
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject((Private, $injector) => {
- Promise = $injector.get('Promise');
- SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
-
- MockSource = class {
- constructor() {
- return $injector.invoke(StubbedSearchSourceProvider);
- }
- };
- }));
-
- it('manages the req._queueCreated flag', async function () {
- const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
- req._queueCreated = null;
-
- const promise = req._createQueue();
- expect(req._queueCreated).to.be(false);
- await promise;
- expect(req._queueCreated).to.be(true);
- });
-
- it('relies on indexPattern.toDetailedIndexList to generate queue', async function () {
- const searchSource = new MockSource();
- const indexPattern = searchSource.getField('index');
- const indices = [1, 2, 3];
- sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve(indices));
-
- const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} });
- const output = await req._createQueue();
- expect(output).to.equal(indices);
- });
-
- it('tells the index pattern its direction', async function () {
- const searchSource = new MockSource();
- const indexPattern = searchSource.getField('index');
- const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} });
- sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([1, 2, 3]));
-
- req.setDirection('asc');
- await req._createQueue();
- expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('asc');
-
- req.setDirection('desc');
- await req._createQueue();
- expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('desc');
- });
-});
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js
deleted file mode 100644
index b1cc13d057f90..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import ngMock from 'ng_mock';
-import expect from 'expect.js';
-import { times } from 'lodash';
-import sinon from 'sinon';
-
-import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn';
-import NoDigestPromises from 'test_utils/no_digest_promises';
-import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
-
-import { SegmentedSearchRequestProvider } from '../segmented_search_request';
-
-describe('SegmentedSearchRequest index selection', function () {
- let Promise;
- let SegmentedSearchRequest;
- let MockSource;
- let HitSortFn;
-
- NoDigestPromises.activateForSuite();
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject((Private, $injector) => {
- Promise = $injector.get('Promise');
- HitSortFn = Private(HitSortFnProv);
- SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
-
- MockSource = class {
- constructor() {
- return $injector.invoke(StubbedSearchSourceProvider);
- }
- };
- }));
-
- it('queries with size until all 500 docs returned', async function () {
- const searchSource = new MockSource();
- const indexPattern = searchSource.getField('index');
- sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([
- { index: 'one', min: 0, max: 1 },
- { index: 'two', min: 0, max: 1 },
- { index: 'three', min: 0, max: 1 },
- { index: 'four', min: 0, max: 1 },
- { index: 'five', min: 0, max: 1 },
- ]));
-
- const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} });
- req._handle.setDirection('desc');
- req._handle.setSortFn(new HitSortFn('desc'));
- req._handle.setSize(500);
- await req.start();
-
- // first 200
- expect((await req.getFetchParams()).body.size).to.be(500);
- await req.handleResponse({
- hits: { total: 1000, hits: times(200, (i) => ({ i })) }
- });
-
- // total = 400
- expect((await req.getFetchParams()).body.size).to.be(500);
- await req.handleResponse({
- hits: { total: 1000, hits: times(200, (i) => ({ i })) }
- });
-
- // total = 600
- expect((await req.getFetchParams()).body.size).to.be(500);
- await req.handleResponse({
- hits: { total: 1000, hits: times(200, (i) => ({ i })) }
- });
-
- expect((await req.getFetchParams()).body.size).to.be(0);
- await req.handleResponse({
- hits: { total: 1000, hits: times(200, (i) => ({ i })) }
- });
-
- expect((await req.getFetchParams()).body.size).to.be(0);
- await req.handleResponse({
- hits: { total: 1000, hits: times(200, (i) => ({ i })) }
- });
- });
-
- it(`sets size 0 for indices that couldn't preclude hits`, async function () {
- const searchSource = new MockSource();
- const indexPattern = searchSource.getField('index');
-
- // the segreq is looking for 10 documents, and we will give it ten docs with time:5 in the first response.
- // on the second index it should still request 10 documents because it could produce documents with time:5.
- // the next two indexes will get size 0, since they couldn't produce documents with the time:5
- // the final index will get size:10, because it too can produce docs with time:5
- sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([
- { index: 'one', min: 0, max: 10 },
- { index: 'two', min: 0, max: 10 },
- { index: 'three', min: 12, max: 20 },
- { index: 'four', min: 15, max: 20 },
- { index: 'five', min: 5, max: 50 },
- ]));
-
- const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} });
- req._handle.setDirection('desc');
- req._handle.setSortFn(new HitSortFn('desc'));
- req._handle.setSize(10);
- await req.start();
-
- // first 10
- expect((await req.getFetchParams()).body.size).to.be(10);
- await req.handleResponse({
- hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) }
- });
-
- // total = 400
- expect((await req.getFetchParams()).body.size).to.be(10);
- await req.handleResponse({
- hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) }
- });
-
- // total = 600
- expect((await req.getFetchParams()).body.size).to.be(0);
- await req.handleResponse({
- hits: { total: 1000, hits: [] }
- });
-
- expect((await req.getFetchParams()).body.size).to.be(0);
- await req.handleResponse({
- hits: { total: 1000, hits: [] }
- });
-
- expect((await req.getFetchParams()).body.size).to.be(10);
- await req.handleResponse({
- hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) }
- });
- });
-});
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js
deleted file mode 100644
index b875e57e5d3cf..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import sinon from 'sinon';
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-
-import { SegmentedSearchRequestProvider } from '../segmented_search_request';
-import { SearchRequestProvider } from '../../search_request';
-
-describe('SegmentedSearchRequest', () => {
- let Promise;
- let SegmentedSearchRequest;
- let segmentedReq;
- let abstractReqStart;
-
- beforeEach(ngMock.module('kibana'));
-
- beforeEach(ngMock.inject((Private, $injector) => {
- Promise = $injector.get('Promise');
- SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
-
- const SearchRequest = Private(SearchRequestProvider);
- abstractReqStart = sinon.stub(SearchRequest.prototype, 'start').callsFake(() => {
- const promise = Promise.resolve();
- sinon.spy(promise, 'then');
- return promise;
- });
- }));
-
- describe('#start()', () => {
- let returned;
- beforeEach(() => {
- init();
- returned = segmentedReq.start();
- });
-
- it('returns promise', () => {
- expect(returned.then).to.be.Function;
- });
-
- it('calls AbstractReq#start()', () => {
- sinon.assert.calledOnce(abstractReqStart);
- });
-
- it('listens to promise from super.start()', () => {
- sinon.assert.calledOnce(abstractReqStart);
- const promise = abstractReqStart.firstCall.returnValue;
- sinon.assert.calledOnce(promise.then);
- });
- });
-
- function init() {
- segmentedReq = new SegmentedSearchRequest({ source: mockSource(), errorHandler: () => {} });
- }
-
- function mockSource() {
- return {
- get: sinon.stub().returns(mockIndexPattern()),
- };
- }
-
- function mockIndexPattern() {
- return {
- toDetailedIndexList: sinon.stub().returns(Promise.resolve([
- { index: 1, min: 0, max: 1 },
- { index: 2, min: 0, max: 1 },
- { index: 3, min: 0, max: 1 },
- ]))
- };
- }
-});
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js
deleted file mode 100644
index b882b3ae5fedf..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import ngMock from 'ng_mock';
-import expect from 'expect.js';
-
-import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn';
-import NoDigestPromises from 'test_utils/no_digest_promises';
-import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
-
-import { SegmentedSearchRequestProvider } from '../segmented_search_request';
-
-describe('SegmentedSearchRequest size picking', function () {
- let SegmentedSearchRequest;
- let MockSource;
- let HitSortFn;
-
- NoDigestPromises.activateForSuite();
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject((Private, $injector) => {
- HitSortFn = Private(HitSortFnProv);
- SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
-
- MockSource = class {
- constructor() {
- return $injector.invoke(StubbedSearchSourceProvider);
- }
- };
- }));
-
- describe('without a size', function () {
- it('does not set the request size', async function () {
- const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
- req._handle.setDirection('desc');
- req._handle.setSortFn(new HitSortFn('desc'));
- await req.start();
-
- expect((await req.getFetchParams()).body).to.not.have.property('size');
- });
- });
-
- describe('with a size', function () {
- it('sets the request size to the entire desired size', async function () {
- const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
- req._handle.setDirection('desc');
- req._handle.setSize(555);
- req._handle.setSortFn(new HitSortFn('desc'));
- await req.start();
-
- expect((await req.getFetchParams()).body).to.have.property('size', 555);
- });
- });
-});
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js
deleted file mode 100644
index b7a638b4ed159..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { EventsProvider } from '../../../../events';
-
-export function SegmentedHandleProvider(Private) {
- const Events = Private(EventsProvider);
-
- const segmentedRequest = Symbol('Actual Segmented Request');
-
- /**
- * Simple class for creating an object to send to the
- * requester of a SegmentedSearchRequest. Since the SegmentedSearchRequest
- * extends AbstractRequest, it wasn't able to be the event
- * emitter it was born to be. This provides a channel for
- * setting values on the segmented request, and an event
- * emitter for the request to speak outwardly
- *
- * @param {SegmentedSearchRequest} - req - the request this handle relates to
- */
- return class SegmentedHandle extends Events {
- constructor(req) {
- super();
- this[segmentedRequest] = req;
- }
-
- setDirection(...args) {
- this[segmentedRequest].setDirection(...args);
- }
-
- setSize(...args) {
- this[segmentedRequest].setSize(...args);
- }
-
- setMaxSegments(...args) {
- this[segmentedRequest].setMaxSegments(...args);
- }
-
- setSortFn(...args) {
- this[segmentedRequest].setSortFn(...args);
- }
- };
-}
diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js
deleted file mode 100644
index 6ab49eee4fe65..0000000000000
--- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import _ from 'lodash';
-import { timefilter } from 'ui/timefilter';
-import { SearchRequestProvider } from '../search_request';
-import { SegmentedHandleProvider } from './segmented_handle';
-import { pushAll } from '../../../../utils/collection';
-
-export function SegmentedSearchRequestProvider(Private, config) {
- const SearchRequest = Private(SearchRequestProvider);
- const SegmentedHandle = Private(SegmentedHandleProvider);
-
- class SegmentedSearchRequest extends SearchRequest {
- constructor({ source, defer, errorHandler, initFn }) {
- super({ source, defer, errorHandler });
-
- this.type = 'segmented';
-
- // segmented request specific state
- this._initFn = initFn;
-
- this._desiredSize = null;
- this._maxSegments = config.get('courier:maxSegmentCount');
- this._direction = 'desc';
- this._sortFn = null;
- this._queueCreated = false;
- this._handle = new SegmentedHandle(this);
-
- this._hitWindow = null;
-
- // prevent the source from changing between requests,
- // all calls will return the same promise
- this._getFlattenedSource = _.once(this._getFlattenedSource);
- }
-
- /*********
- ** SearchReq overrides
- *********/
-
- start() {
- return super.start().then(() => {
- this._complete = [];
- this._active = null;
- this._segments = [];
- this._all = [];
- this._queue = [];
-
- this._mergedResp = {
- took: 0,
- hits: {
- hits: [],
- total: 0,
- max_score: 0
- }
- };
-
- // give the request consumer a chance to receive each segment and set
- // parameters via the handle
- if (_.isFunction(this._initFn)) this._initFn(this._handle);
- return this._createQueue();
- })
- .then((queue) => {
- if (this.stopped) return;
-
- this._all = queue.slice(0);
-
- // Send the initial fetch status
- return this._reportStatus();
- });
- }
-
- continue() {
- return this._reportStatus();
- }
-
- getFetchParams() {
- return this._getFlattenedSource().then(flatSource => {
- const params = _.cloneDeep(flatSource);
-
- // calculate the number of indices to fetch in this request in order to prevent
- // more than this._maxSegments requests. We use Math.max(1, n) to ensure that each request
- // has at least one index pattern, and Math.floor() to make sure that if the
- // number of indices does not round out evenly the extra index is tacked onto the last
- // request, making sure the first request returns faster.
- const remainingSegments = this._maxSegments - this._segments.length;
- const indexCount = Math.max(1, Math.floor(this._queue.length / remainingSegments));
-
- const indices = this._active = this._queue.splice(0, indexCount);
- params.index = indices.map(({ index }) => index).join(',');
-
- if (_.isNumber(this._desiredSize)) {
- params.body.size = this._pickSizeForIndices(indices);
- }
-
- return params;
- });
- }
-
- handleResponse(resp) {
- return this._consumeSegment(resp);
- }
-
- filterError(resp) {
- if (/ClusterBlockException.*index\sclosed/.test(resp.error)) {
- this._consumeSegment(false);
- return true;
- }
- }
-
- isIncomplete() {
- const queueNotCreated = !this._queueCreated;
- const queueNotEmpty = this._queue.length > 0;
- return queueNotCreated || queueNotEmpty;
- }
-
- clone() {
- return new SegmentedSearchRequest(this.source, this.defer, this._initFn);
- }
-
- complete() {
- this._reportStatus();
- this._handle.emit('complete');
- return super.complete();
- }
-
- /*********
- ** SegmentedSearchRequest specific methods
- *********/
-
-
- /**
- * Set the sort total number of segments to emit
- *
- * @param {number}
- */
- setMaxSegments(maxSegments) {
- this._maxSegments = Math.max(_.parseInt(maxSegments), 1);
- }
-
- /**
- * Set the sort direction for the request.
- *
- * @param {string} dir - one of 'asc' or 'desc'
- */
- setDirection(dir) {
- switch (dir) {
- case 'asc':
- case 'desc':
- return (this._direction = dir);
- default:
- throw new TypeError('unknown sort direction "' + dir + '"');
- }
- }
-
- /**
- * Set the function that will be used to sort the rows
- *
- * @param {fn}
- */
- setSortFn(sortFn) {
- this._sortFn = sortFn;
- }
-
- /**
- * Set the sort total number of documents to
- * emit
- *
- * Setting to false will not limit the documents,
- * if a number is set the size of the request to es
- * will be updated on each new request
- *
- * @param {number|false}
- */
- setSize(totalSize) {
- this._desiredSize = _.parseInt(totalSize);
- if (isNaN(this._desiredSize)) this._desiredSize = null;
- }
-
- _createQueue() {
- const timeBounds = timefilter.getBounds();
- const indexPattern = this.source.getField('index');
- this._queueCreated = false;
-
- return indexPattern.toDetailedIndexList(timeBounds.min, timeBounds.max, this._direction)
- .then(queue => {
- this._queue = queue;
- this._queueCreated = true;
- return queue;
- });
- }
-
- _reportStatus() {
- return this._handle.emit('status', {
- total: this._queueCreated ? this._all.length : NaN,
- complete: this._queueCreated ? this._complete.length : NaN,
- remaining: this._queueCreated ? this._queue.length : NaN,
- hitCount: this._queueCreated ? this._mergedResp.hits.hits.length : NaN
- });
- }
-
- _getFlattenedSource() {
- return this.source._flatten();
- }
-
- _consumeSegment(seg) {
- const index = this._active;
- this._complete.push(index);
- if (!seg) return; // segment was ignored/filtered, don't store it
-
- const hadHits = _.get(this._mergedResp, 'hits.hits.length') > 0;
- const gotHits = _.get(seg, 'hits.hits.length') > 0;
- const firstHits = !hadHits && gotHits;
- const haveHits = hadHits || gotHits;
-
- this._mergeSegment(seg);
- this.resp = _.omit(this._mergedResp, '_bucketIndex');
-
- if (firstHits) this._handle.emit('first', seg);
- gotHits ? this._handle.emit('segment', seg) : this._handle.emit('emptySegment', seg);
- if (haveHits) this._handle.emit('mergedSegment', this.resp);
- }
-
- _mergeHits(hits) {
- const mergedHits = this._mergedResp.hits.hits;
- const desiredSize = this._desiredSize;
- const sortFn = this._sortFn;
-
- pushAll(hits, mergedHits);
-
- if (sortFn) {
- mergedHits.sort(sortFn);
- }
-
- if (_.isNumber(desiredSize)) {
- this._mergedResp.hits.hits = mergedHits.slice(0, desiredSize);
- }
- }
-
- _mergeSegment(seg) {
- const merged = this._mergedResp;
-
- this._segments.push(seg);
-
- merged.took += seg.took;
- merged.hits.total += seg.hits.total;
- merged.hits.max_score = Math.max(merged.hits.max_score, seg.hits.max_score);
-
- if (_.size(seg.hits.hits)) {
- this._mergeHits(seg.hits.hits);
- this._detectHitsWindow(merged.hits.hits);
- }
-
- if (!seg.aggregations) return;
-
- Object.keys(seg.aggregations).forEach(function (aggKey) {
-
- if (!merged.aggregations) {
- // start merging aggregations
- merged.aggregations = {};
- merged._bucketIndex = {};
- }
-
- if (!merged.aggregations[aggKey]) {
- merged.aggregations[aggKey] = {
- buckets: []
- };
- }
-
- seg.aggregations[aggKey].buckets.forEach(function (bucket) {
- let mbucket = merged._bucketIndex[bucket.key];
- if (mbucket) {
- mbucket.doc_count += bucket.doc_count;
- return;
- }
-
- mbucket = merged._bucketIndex[bucket.key] = bucket;
- merged.aggregations[aggKey].buckets.push(mbucket);
- });
- });
- }
-
- _detectHitsWindow(hits) {
- hits = hits || [];
- const indexPattern = this.source.getField('index');
- const desiredSize = this._desiredSize;
-
- const size = _.size(hits);
- if (!_.isNumber(desiredSize) || size < desiredSize) {
- this._hitWindow = {
- size: size,
- min: -Infinity,
- max: Infinity
- };
- return;
- }
-
- let min;
- let max;
-
- hits.forEach(function (deepHit) {
- const hit = indexPattern.flattenHit(deepHit);
- const time = hit[indexPattern.timeFieldName];
- if (min == null || time < min) min = time;
- if (max == null || time > max) max = time;
- });
-
- this._hitWindow = { size, min, max };
- }
-
- _pickSizeForIndices(indices) {
- const hitWindow = this._hitWindow;
- const desiredSize = this._desiredSize;
-
- if (!_.isNumber(desiredSize)) return null;
- // we don't have any hits yet, get us more info!
- if (!hitWindow) return desiredSize;
- // the order of documents isn't important, just get us more
- if (!this._sortFn) return Math.max(desiredSize - hitWindow.size, 0);
- // if all of the documents in every index fall outside of our current doc set, we can ignore them.
- const someOverlap = indices.some(function (index) {
- return index.min <= hitWindow.max && hitWindow.min <= index.max;
- });
-
- return someOverlap ? desiredSize : 0;
- }
- }
-
- return SegmentedSearchRequest;
-}
diff --git a/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js b/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js
index 84548e6626752..47c50d726c9fc 100644
--- a/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js
+++ b/src/legacy/ui/public/courier/fetch/request/serialize_fetch_params/__tests__/serialize_fetch_params.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import StubIndexPatternProvider from 'test_utils/stub_index_pattern';
diff --git a/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js b/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js
index 434894e07c21a..f6b4e4bef20c2 100644
--- a/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js
+++ b/src/legacy/ui/public/courier/search_request_queue/__tests__/search_request_queue.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { searchRequestQueue } from '../search_request_queue';
diff --git a/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js b/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js
index 810f9cf045495..2358fdb520715 100644
--- a/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js
+++ b/src/legacy/ui/public/courier/search_source/__tests__/normalize_sort_request.js
@@ -19,7 +19,7 @@
import '../../../private';
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { NormalizeSortRequestProvider } from '../_normalize_sort_request';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
import _ from 'lodash';
diff --git a/src/legacy/ui/public/courier/search_source/__tests__/search_source.js b/src/legacy/ui/public/courier/search_source/__tests__/search_source.js
index 2034c63e0605f..8297c751da5fe 100644
--- a/src/legacy/ui/public/courier/search_source/__tests__/search_source.js
+++ b/src/legacy/ui/public/courier/search_source/__tests__/search_source.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { searchRequestQueue } from '../../search_request_queue';
diff --git a/src/legacy/ui/public/courier/search_source/search_source.js b/src/legacy/ui/public/courier/search_source/search_source.js
index 8fc71bff40a84..7943973bf51ed 100644
--- a/src/legacy/ui/public/courier/search_source/search_source.js
+++ b/src/legacy/ui/public/courier/search_source/search_source.js
@@ -76,7 +76,6 @@ import { buildEsQuery, getEsQueryConfig, filterMatchesIndex } from '@kbn/es-quer
import '../../promises';
import { NormalizeSortRequestProvider } from './_normalize_sort_request';
import { SearchRequestProvider } from '../fetch/request';
-import { SegmentedSearchRequestProvider } from '../fetch/request/segmented_search_request';
import { searchRequestQueue } from '../search_request_queue';
import { FetchSoonProvider } from '../fetch';
@@ -117,7 +116,6 @@ function isIndexPattern(val) {
export function SearchSourceProvider(Promise, Private, config) {
const SearchRequest = Private(SearchRequestProvider);
- const SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
const normalizeSortRequest = Private(NormalizeSortRequestProvider);
const fetchSoon = Private(FetchSoonProvider);
const { fieldWildcardFilter } = Private(FieldWildcardProvider);
@@ -390,26 +388,6 @@ export function SearchSourceProvider(Promise, Private, config) {
});
}
- onBeginSegmentedFetch(initFunction) {
- const self = this;
- return new Promise((resolve, reject) => {
- function addRequest() {
- const defer = Promise.defer();
- const errorHandler = (request, error) => {
- reject(error);
- request.abort();
- };
- const req = new SegmentedSearchRequest({ source: self, defer, errorHandler, initFn: initFunction });
-
- // Return promises created by the completion handler so that
- // errors will bubble properly
- return req.getCompletePromise().then(addRequest);
- }
-
- addRequest();
- });
- }
-
async getSearchRequestBody() {
const searchRequest = await this._flatten();
return searchRequest.body;
diff --git a/src/legacy/ui/public/debounce/__tests__/debounce.js b/src/legacy/ui/public/debounce/__tests__/debounce.js
index 5aa4233613ce1..e5138643101f5 100644
--- a/src/legacy/ui/public/debounce/__tests__/debounce.js
+++ b/src/legacy/ui/public/debounce/__tests__/debounce.js
@@ -19,7 +19,7 @@
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { DebounceProvider } from '..';
diff --git a/src/legacy/ui/public/directives/__tests__/css_truncate.js b/src/legacy/ui/public/directives/__tests__/css_truncate.js
index 3c851a7df6842..ec46448962dc3 100644
--- a/src/legacy/ui/public/directives/__tests__/css_truncate.js
+++ b/src/legacy/ui/public/directives/__tests__/css_truncate.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/directives/__tests__/fixed_scroll.js b/src/legacy/ui/public/directives/__tests__/fixed_scroll.js
index cec917cf4d1f7..651e3af550e44 100644
--- a/src/legacy/ui/public/directives/__tests__/fixed_scroll.js
+++ b/src/legacy/ui/public/directives/__tests__/fixed_scroll.js
@@ -18,7 +18,7 @@
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../../fixed_scroll';
import $ from 'jquery';
diff --git a/src/legacy/ui/public/directives/__tests__/inequality.js b/src/legacy/ui/public/directives/__tests__/inequality.js
index a513520e49791..0e6a537d69f7c 100644
--- a/src/legacy/ui/public/directives/__tests__/inequality.js
+++ b/src/legacy/ui/public/directives/__tests__/inequality.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../inequality';
@@ -33,7 +33,6 @@ describe('greater_than model validator directive', function () {
$rootScope = _$rootScope_;
}));
- // no value is the same as 0
describe('without value', function () {
let element;
beforeEach(function () {
@@ -60,6 +59,33 @@ describe('greater_than model validator directive', function () {
});
});
+ describe('with string values', function () {
+ let element;
+ beforeEach(function () {
+ html = ``;
+ element = $compile(html)($rootScope);
+ });
+
+ it('should be valid for greater than 10', function () {
+ $rootScope.value = '15';
+ $rootScope.$digest();
+ expect(element.hasClass('ng-valid')).to.be.ok();
+ });
+
+ it('should be invalid for 10', function () {
+ $rootScope.value = '10';
+ $rootScope.$digest();
+ expect(element.hasClass('ng-invalid')).to.be.ok();
+ });
+
+ // Edge case because '5' > '10' as strings
+ it('should be invalid less than 10', function () {
+ $rootScope.value = '5';
+ $rootScope.$digest();
+ expect(element.hasClass('ng-invalid')).to.be.ok();
+ });
+ });
+
[0, 1, 10, 42, -12].forEach(function (num) {
describe('with value ' + num, function () {
let element;
@@ -85,7 +111,14 @@ describe('greater_than model validator directive', function () {
$rootScope.$digest();
expect(element.hasClass('ng-invalid')).to.be.ok();
});
+
+ it('should be valid for empty model values', () => {
+ [undefined, null, ''].forEach(val => {
+ $rootScope.value = val;
+ $rootScope.$digest();
+ expect(element.hasClass('ng-valid')).to.be.ok();
+ });
+ });
});
});
-
});
diff --git a/src/legacy/ui/public/directives/__tests__/input_focus.js b/src/legacy/ui/public/directives/__tests__/input_focus.js
index 9b1bbe25c844c..5336c01d74d80 100644
--- a/src/legacy/ui/public/directives/__tests__/input_focus.js
+++ b/src/legacy/ui/public/directives/__tests__/input_focus.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import $ from 'jquery';
import '../input_focus';
diff --git a/src/legacy/ui/public/directives/__tests__/json_input.js b/src/legacy/ui/public/directives/__tests__/json_input.js
index 43ecea162f166..b2ad6c8c47321 100644
--- a/src/legacy/ui/public/directives/__tests__/json_input.js
+++ b/src/legacy/ui/public/directives/__tests__/json_input.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../json_input';
diff --git a/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js b/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js
index 5246cc3568fd8..319b16c6a3233 100644
--- a/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js
+++ b/src/legacy/ui/public/directives/__tests__/paginated_selectable_list.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import _ from 'lodash';
diff --git a/src/legacy/ui/public/directives/__tests__/parse_query.js b/src/legacy/ui/public/directives/__tests__/parse_query.js
index 3239bbceae248..12d9d12053286 100644
--- a/src/legacy/ui/public/directives/__tests__/parse_query.js
+++ b/src/legacy/ui/public/directives/__tests__/parse_query.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
// Load the kibana app dependencies.
diff --git a/src/legacy/ui/public/directives/__tests__/truncate.js b/src/legacy/ui/public/directives/__tests__/truncate.js
index 864db63805691..7cf0d2e3799b1 100644
--- a/src/legacy/ui/public/directives/__tests__/truncate.js
+++ b/src/legacy/ui/public/directives/__tests__/truncate.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/directives/__tests__/validate_json.js b/src/legacy/ui/public/directives/__tests__/validate_json.js
deleted file mode 100644
index b59ee7bccf7ec..0000000000000
--- a/src/legacy/ui/public/directives/__tests__/validate_json.js
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import angular from 'angular';
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-import '../validate_json';
-
-// Load the kibana app dependencies.
-
-let $parentScope;
-let $elemScope;
-let $elem;
-const mockScope = '';
-
-const input = {
- valid: '{ "test": "json input" }',
- invalid: 'strings are not json'
-};
-
-const markup = {
- textarea: '',
- input: ''
-};
-
-const init = function (type) {
- // Load the application
- ngMock.module('kibana');
- type = type || 'input';
- const elMarkup = markup[type];
-
- // Create the scope
- ngMock.inject(function ($injector, $rootScope, $compile) {
- // Give us a scope
- $parentScope = $rootScope;
- $parentScope.mockModel = mockScope;
-
- $elem = angular.element(elMarkup);
- $compile($elem)($parentScope);
- $elemScope = $elem.isolateScope();
- });
-};
-
-describe('validate-json directive', function () {
- const checkValid = function (inputVal, className) {
- $parentScope.mockModel = inputVal;
- $elem.scope().$digest();
- expect($elem.hasClass(className)).to.be(true);
- };
-
- describe('initialization', function () {
- beforeEach(function () {
- init();
- });
-
- it('should use the model', function () {
- expect($elemScope).to.have.property('ngModel');
- });
-
- });
-
- Object.keys(markup).forEach(function (inputType) {
- describe(inputType, function () {
- beforeEach(function () {
- init(inputType);
- });
-
- it('should be an input', function () {
- expect($elem.get(0).tagName).to.be(inputType.toUpperCase());
- });
-
- it('should set valid state', function () {
- checkValid(input.valid, 'ng-valid');
- });
-
- it('should be valid when empty', function () {
- checkValid('', 'ng-valid');
- });
-
- it('should set invalid state', function () {
- checkValid(input.invalid, 'ng-invalid');
- });
-
- it('should be invalid if a number', function () {
- checkValid('0', 'ng-invalid');
- });
-
- it('should update validity on changes', function () {
- checkValid(input.valid, 'ng-valid');
- checkValid(input.invalid, 'ng-invalid');
- checkValid(input.valid, 'ng-valid');
- });
- });
- });
-});
diff --git a/src/legacy/ui/public/directives/inequality.js b/src/legacy/ui/public/directives/inequality.js
index d3c80d1ff2e96..a08b617ceb929 100644
--- a/src/legacy/ui/public/directives/inequality.js
+++ b/src/legacy/ui/public/directives/inequality.js
@@ -24,12 +24,7 @@ function makeDirectiveDef(id, compare) {
return {
require: 'ngModel',
link: function ($scope, $el, $attr, ngModel) {
- const getBound = function () { return $parse($attr[id])(); };
- const defaultVal = {
- 'greaterThan': -Infinity,
- 'greaterOrEqualThan': -Infinity,
- 'lessThan': Infinity
- }[id];
+ const getBound = function () { return $parse($attr[id])($scope); };
ngModel.$parsers.push(validate);
ngModel.$formatters.push(validate);
@@ -38,12 +33,20 @@ function makeDirectiveDef(id, compare) {
validate(ngModel.$viewValue);
});
+ // We only set it to invalid when both the model value and the value to compare against are
+ // provided, and the values do not meet the condition.
function validate(val) {
- const bound = !isNaN(getBound()) ? +getBound() : defaultVal;
- const valid = !isNaN(bound) && !isNaN(val) && compare(val, bound);
- ngModel.$setValidity(id, valid);
+ const bound = getBound();
+ const left = parseFloat(val);
+ const right = parseFloat(bound);
+ const isValid = isEmpty(val) || isEmpty(bound) || compare(left, right);
+ ngModel.$setValidity(id, isValid);
return val;
}
+
+ function isEmpty(val) {
+ return typeof val === 'undefined' || val === null || val === '';
+ }
}
};
};
diff --git a/src/legacy/ui/public/directives/paginated_selectable_list.js b/src/legacy/ui/public/directives/paginated_selectable_list.js
index 417273668dae7..7484e2a1840b5 100644
--- a/src/legacy/ui/public/directives/paginated_selectable_list.js
+++ b/src/legacy/ui/public/directives/paginated_selectable_list.js
@@ -19,6 +19,8 @@
import _ from 'lodash';
import { uiModules } from '../modules';
+import './paginate';
+import './kbn_href';
import paginatedSelectableListTemplate from '../partials/paginated_selectable_list.html';
const module = uiModules.get('kibana');
diff --git a/src/legacy/ui/public/directives/saved_object_finder.js b/src/legacy/ui/public/directives/saved_object_finder.js
index 0b107dc085f2d..f73e378f8ba8a 100644
--- a/src/legacy/ui/public/directives/saved_object_finder.js
+++ b/src/legacy/ui/public/directives/saved_object_finder.js
@@ -23,6 +23,8 @@ import { keyMap } from '../utils/key_map';
import { SavedObjectRegistryProvider } from '../saved_objects/saved_object_registry';
import { uiModules } from '../modules';
import savedObjectFinderTemplate from '../partials/saved_object_finder.html';
+import './input_focus';
+import './paginate';
const module = uiModules.get('kibana');
diff --git a/src/legacy/ui/public/directives/validate_json.js b/src/legacy/ui/public/directives/validate_json.js
deleted file mode 100644
index 396cfd13daf88..0000000000000
--- a/src/legacy/ui/public/directives/validate_json.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { uiModules } from '../modules';
-
-const module = uiModules.get('kibana');
-
-module.directive('validateJson', function () {
- return {
- restrict: 'A',
- require: 'ngModel',
- scope: {
- 'ngModel': '=',
- 'queryInput': '=?',
- },
- link: function ($scope, $elem, attr, ngModel) {
- $scope.$watch('ngModel', validator);
-
- function validator(newValue) {
- if (!newValue || newValue.length === 0) {
- setValid();
- return;
- }
-
- // We actually need a proper object in all JSON inputs
- newValue = (newValue || '').trim();
- if (newValue[0] === '{' || newValue[0] === '[') {
- try {
- JSON.parse(newValue);
- setValid();
- } catch (e) {
- setInvalid();
- }
- } else {
- setInvalid();
- }
- }
-
- function setValid() {
- ngModel.$setValidity('jsonInput', true);
- }
-
- function setInvalid() {
- ngModel.$setValidity('jsonInput', false);
- }
- }
- };
-});
diff --git a/src/legacy/ui/public/doc_table/__tests__/actions/filter.js b/src/legacy/ui/public/doc_table/__tests__/actions/filter.js
index 4a050797f94f7..496ec7dc87396 100644
--- a/src/legacy/ui/public/doc_table/__tests__/actions/filter.js
+++ b/src/legacy/ui/public/doc_table/__tests__/actions/filter.js
@@ -21,7 +21,7 @@ import { addFilter } from '../../actions/filter';
import { FilterManagerProvider } from '../../../filter_manager';
import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
import NoDigestPromises from 'test_utils/no_digest_promises';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import sinon from 'sinon';
diff --git a/src/legacy/ui/public/doc_table/__tests__/doc_table.js b/src/legacy/ui/public/doc_table/__tests__/doc_table.js
index 5395ddb4f216f..56cd15b66b37e 100644
--- a/src/legacy/ui/public/doc_table/__tests__/doc_table.js
+++ b/src/legacy/ui/public/doc_table/__tests__/doc_table.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import _ from 'lodash';
import ngMock from 'ng_mock';
import '../../private';
diff --git a/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js b/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js
index 3ea586f457993..bec26d38d0fa7 100644
--- a/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js
+++ b/src/legacy/ui/public/doc_table/__tests__/lib/get_sort.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { getSort } from '../../lib/get_sort';
diff --git a/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js b/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js
index 1cbe730aace39..b2660facf7a5a 100644
--- a/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js
+++ b/src/legacy/ui/public/doc_table/__tests__/lib/rows_headers.js
@@ -20,7 +20,7 @@
import angular from 'angular';
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { getFakeRow, getFakeRowVals } from 'fixtures/fake_row';
import $ from 'jquery';
diff --git a/src/legacy/ui/public/doc_table/doc_table.js b/src/legacy/ui/public/doc_table/doc_table.js
index 05311556869e1..4c33f8a526704 100644
--- a/src/legacy/ui/public/doc_table/doc_table.js
+++ b/src/legacy/ui/public/doc_table/doc_table.js
@@ -20,7 +20,7 @@
import _ from 'lodash';
import html from './doc_table.html';
import { getSort } from './lib/get_sort';
-import '../directives/infinite_scroll';
+import './infinite_scroll';
import './components/table_header';
import './components/table_row';
import { dispatchRenderComplete } from '../render_complete';
diff --git a/src/legacy/ui/public/directives/infinite_scroll.js b/src/legacy/ui/public/doc_table/infinite_scroll.js
similarity index 97%
rename from src/legacy/ui/public/directives/infinite_scroll.js
rename to src/legacy/ui/public/doc_table/infinite_scroll.js
index 6f8132e1ee7d9..67913062eb2a5 100644
--- a/src/legacy/ui/public/directives/infinite_scroll.js
+++ b/src/legacy/ui/public/doc_table/infinite_scroll.js
@@ -19,7 +19,7 @@
import $ from 'jquery';
import { uiModules } from '../modules';
-const module = uiModules.get('kibana');
+const module = uiModules.get('app/discover');
module.directive('kbnInfiniteScroll', function () {
return {
diff --git a/src/legacy/ui/public/doc_title/__tests__/doc_title.js b/src/legacy/ui/public/doc_title/__tests__/doc_title.js
index 4c459a17a6c69..2c0ec6766cb14 100644
--- a/src/legacy/ui/public/doc_title/__tests__/doc_title.js
+++ b/src/legacy/ui/public/doc_title/__tests__/doc_title.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { DocTitleProvider } from '..';
diff --git a/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js b/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js
index e55718374be16..b6ba1f7206a19 100644
--- a/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js
+++ b/src/legacy/ui/public/doc_viewer/__tests__/doc_viewer.js
@@ -19,7 +19,7 @@
import angular from 'angular';
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../../private';
diff --git a/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js b/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js
index 22e6d8ecfbff6..60ab7a03576c3 100644
--- a/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js
+++ b/src/legacy/ui/public/documentation_links/__tests__/documentation_links.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { documentationLinks } from '../documentation_links';
import { metadata } from '../../metadata';
diff --git a/src/legacy/ui/public/draggable/__tests__/draggable.js b/src/legacy/ui/public/draggable/__tests__/draggable.js
index 8cba8a8ebb11c..fc0601a9b67e9 100644
--- a/src/legacy/ui/public/draggable/__tests__/draggable.js
+++ b/src/legacy/ui/public/draggable/__tests__/draggable.js
@@ -18,7 +18,7 @@
*/
import angular from 'angular';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
let init;
diff --git a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts
index 152fdee9f7fff..d43f1d16aefd1 100644
--- a/src/legacy/ui/public/embeddable/context_menu_actions/index.ts
+++ b/src/legacy/ui/public/embeddable/context_menu_actions/index.ts
@@ -21,3 +21,4 @@ export { ContextMenuPanel } from './context_menu_panel';
export { ContextMenuAction } from './context_menu_action';
export { ContextMenuActionsRegistryProvider } from './context_menu_actions_registry';
export { buildEuiContextMenuPanels } from './build_eui_context_menu_panels';
+export { PanelActionAPI } from './types';
diff --git a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js
index 75d114e397fb8..48b92b79c0b7e 100644
--- a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js
+++ b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { IE_REGEX } from '../url_overflow_service.js';
describe('IE_REGEX', () => {
diff --git a/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js b/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx
similarity index 76%
rename from src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js
rename to src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx
index 9e985426e8f41..4fc17a7dbca38 100644
--- a/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.js
+++ b/src/legacy/ui/public/exit_full_screen/exit_full_screen_button.tsx
@@ -17,39 +17,37 @@
* under the License.
*/
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import React, { PureComponent } from 'react';
-import PropTypes from 'prop-types';
import chrome from 'ui/chrome';
-import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
-import {
- KuiButton,
-} from '@kbn/ui-framework/components';
+// @ts-ignore
+import { KuiButton } from '@kbn/ui-framework/components';
-import {
- keyCodes,
- EuiScreenReaderOnly,
-} from '@elastic/eui';
+import { EuiScreenReaderOnly, keyCodes } from '@elastic/eui';
-class ExitFullScreenButtonUi extends PureComponent {
+interface Props extends ReactIntl.InjectedIntlProps {
+ onExitFullScreenMode: () => void;
+}
- onKeyDown = (e) => {
+class ExitFullScreenButtonUi extends PureComponent {
+ public onKeyDown = (e: KeyboardEvent) => {
if (e.keyCode === keyCodes.ESCAPE) {
this.props.onExitFullScreenMode();
}
};
- componentWillMount() {
+ public componentWillMount() {
document.addEventListener('keydown', this.onKeyDown, false);
chrome.setVisible(false);
}
- componentWillUnmount() {
+ public componentWillUnmount() {
document.removeEventListener('keydown', this.onKeyDown, false);
chrome.setVisible(true);
}
- render() {
+ public render() {
const { intl } = this.props;
return (
@@ -62,9 +60,7 @@ class ExitFullScreenButtonUi extends PureComponent {
/>
-
+
-
+
-
+
@@ -89,8 +88,4 @@ class ExitFullScreenButtonUi extends PureComponent {
}
}
-ExitFullScreenButtonUi.propTypes = {
- onExitFullScreenMode: PropTypes.func.isRequired,
-};
-
export const ExitFullScreenButton = injectI18n(ExitFullScreenButtonUi);
diff --git a/src/legacy/ui/public/exit_full_screen/index.js b/src/legacy/ui/public/exit_full_screen/index.ts
similarity index 100%
rename from src/legacy/ui/public/exit_full_screen/index.js
rename to src/legacy/ui/public/exit_full_screen/index.ts
diff --git a/src/legacy/ui/public/factories/__tests__/events.js b/src/legacy/ui/public/factories/__tests__/events.js
deleted file mode 100644
index c9ba7f5798544..0000000000000
--- a/src/legacy/ui/public/factories/__tests__/events.js
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-import _ from 'lodash';
-import sinon from 'sinon';
-import expect from 'expect.js';
-import ngMock from 'ng_mock';
-import '../../private';
-import { EventsProvider } from '../../events';
-import { createLegacyClass } from '../../utils/legacy_class';
-
-describe('Events', function () {
- require('test_utils/no_digest_promises').activateForSuite();
-
- let Events;
- let Promise;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(ngMock.inject(function ($injector, Private) {
- Promise = $injector.get('Promise');
- Events = Private(EventsProvider);
- }));
-
- it('should handle on events', function () {
- const obj = new Events();
- const prom = obj.on('test', function (message) {
- expect(message).to.equal('Hello World');
- });
-
- obj.emit('test', 'Hello World');
-
- return prom;
- });
-
- it('should work with inherited objects', function () {
- createLegacyClass(MyEventedObject).inherits(Events);
- function MyEventedObject() {
- MyEventedObject.Super.call(this);
- }
- const obj = new MyEventedObject();
-
- const prom = obj.on('test', function (message) {
- expect(message).to.equal('Hello World');
- });
-
- obj.emit('test', 'Hello World');
-
- return prom;
- });
-
- it('should clear events when off is called', function () {
- const obj = new Events();
- obj.on('test', _.noop);
- expect(obj._listeners).to.have.property('test');
- expect(obj._listeners.test).to.have.length(1);
- obj.off();
- expect(obj._listeners).to.not.have.property('test');
- });
-
- it('should clear a specific handler when off is called for an event', function () {
- const obj = new Events();
- const handler1 = sinon.stub();
- const handler2 = sinon.stub();
- obj.on('test', handler1);
- obj.on('test', handler2);
- expect(obj._listeners).to.have.property('test');
- obj.off('test', handler1);
-
- return obj.emit('test', 'Hello World')
- .then(function () {
- sinon.assert.calledOnce(handler2);
- sinon.assert.notCalled(handler1);
- });
- });
-
- it('should clear a all handlers when off is called for an event', function () {
- const obj = new Events();
- const handler1 = sinon.stub();
- obj.on('test', handler1);
- expect(obj._listeners).to.have.property('test');
- obj.off('test');
- expect(obj._listeners).to.not.have.property('test');
-
- return obj.emit('test', 'Hello World')
- .then(function () {
- sinon.assert.notCalled(handler1);
- });
- });
-
- it('should handle multiple identical emits in the same tick', function () {
- const obj = new Events();
- const handler1 = sinon.stub();
-
- obj.on('test', handler1);
- const emits = [
- obj.emit('test', 'one'),
- obj.emit('test', 'two'),
- obj.emit('test', 'three')
- ];
-
- return Promise
- .all(emits)
- .then(function () {
- expect(handler1.callCount).to.be(emits.length);
- expect(handler1.getCall(0).calledWith('one')).to.be(true);
- expect(handler1.getCall(1).calledWith('two')).to.be(true);
- expect(handler1.getCall(2).calledWith('three')).to.be(true);
- });
- });
-
- it('should handle emits from the handler', function () {
- const obj = new Events();
- const secondEmit = Promise.defer();
- const handler1 = sinon.spy(function () {
- if (handler1.calledTwice) {
- return;
- }
- obj.emit('test').then(_.bindKey(secondEmit, 'resolve'));
- });
-
- obj.on('test', handler1);
-
- return Promise
- .all([
- obj.emit('test'),
- secondEmit.promise
- ])
- .then(function () {
- expect(handler1.callCount).to.be(2);
- });
- });
-
- it('should only emit to handlers registered before emit is called', function () {
- const obj = new Events();
- const handler1 = sinon.stub();
- const handler2 = sinon.stub();
-
- obj.on('test', handler1);
- const emits = [
- obj.emit('test', 'one'),
- obj.emit('test', 'two'),
- obj.emit('test', 'three')
- ];
-
-
- return Promise.all(emits).then(function () {
- expect(handler1.callCount).to.be(emits.length);
-
- obj.on('test', handler2);
-
- const emits2 = [
- obj.emit('test', 'four'),
- obj.emit('test', 'five'),
- obj.emit('test', 'six')
- ];
-
- return Promise.all(emits2)
- .then(function () {
- expect(handler1.callCount).to.be(emits.length + emits2.length);
- expect(handler2.callCount).to.be(emits2.length);
- });
- });
- });
-
- it('should pass multiple arguments from the emitter', function () {
- const obj = new Events();
- const handler = sinon.stub();
- const payload = [
- 'one',
- { hello: 'tests' },
- null
- ];
-
- obj.on('test', handler);
-
- return obj.emit('test', payload[0], payload[1], payload[2])
- .then(function () {
- expect(handler.callCount).to.be(1);
- expect(handler.calledWithExactly(payload[0], payload[1], payload[2])).to.be(true);
- });
- });
-
- it('should preserve the scope of the handler', function () {
- const obj = new Events();
- const expected = 'some value';
- let testValue;
-
- function handler() {
- testValue = this.getVal();
- }
- handler.getVal = _.constant(expected);
-
- obj.on('test', handler);
- return obj.emit('test')
- .then(function () {
- expect(testValue).to.equal(expected);
- });
- });
-
- it('should always emit in the same order', function () {
- const handler = sinon.stub();
-
- const obj = new Events();
- obj.on('block', _.partial(handler, 'block'));
- obj.on('last', _.partial(handler, 'last'));
-
- return Promise
- .all([
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('block'),
- obj.emit('last')
- ])
- .then(function () {
- expect(handler.callCount).to.be(10);
- handler.args.forEach(function (args, i) {
- expect(args[0]).to.be(i < 9 ? 'block' : 'last');
- });
- });
- });
-});
diff --git a/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js b/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js
index 401255ba44d6b..4e1cbb2595c2c 100644
--- a/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js
+++ b/src/legacy/ui/public/fancy_forms/__tests__/fancy_forms.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import $ from 'jquery';
describe('fancy forms', function () {
diff --git a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js
index 005e6441b03a8..095007004ae7f 100644
--- a/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js
+++ b/src/legacy/ui/public/fancy_forms/__tests__/nested_fancy_forms.js
@@ -18,7 +18,8 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
+import testSubjSelector from '@kbn/test-subj-selector';
import sinon from 'sinon';
import $ from 'jquery';
@@ -85,7 +86,7 @@ describe('fancy forms', function () {
expect($scope.person.errorCount()).to.be(1);
expect($scope.person.softErrorCount()).to.be(0);
- $el.findTestSubject('submit').click();
+ $el.find(testSubjSelector('submit')).click();
expect($scope.person.errorCount()).to.be(1);
expect($scope.person.softErrorCount()).to.be(1);
});
@@ -96,7 +97,7 @@ describe('fancy forms', function () {
expect($scope.person.errorCount()).to.be(1);
sinon.assert.notCalled(onSubmit);
- $el.findTestSubject('submit').click();
+ $el.find(testSubjSelector('submit')).click();
expect($scope.person.errorCount()).to.be(1);
sinon.assert.notCalled(onSubmit);
@@ -106,7 +107,7 @@ describe('fancy forms', function () {
expect($scope.person.errorCount()).to.be(0);
sinon.assert.notCalled(onSubmit);
- $el.findTestSubject('submit').click();
+ $el.find(testSubjSelector('submit')).click();
expect($scope.person.errorCount()).to.be(0);
sinon.assert.calledOnce(onSubmit);
});
@@ -114,7 +115,7 @@ describe('fancy forms', function () {
it('new fields are no longer soft after blur', function () {
const { $scope, $el } = setup({ name: '' });
expect($scope.person.softErrorCount()).to.be(0);
- $el.findTestSubject('name').blur();
+ $el.find(testSubjSelector('name')).blur();
expect($scope.person.softErrorCount()).to.be(1);
});
@@ -139,7 +140,7 @@ describe('fancy forms', function () {
expect($scope.person.errorCount()).to.be(2);
expect($scope.person.softErrorCount()).to.be(0);
- $el.findTestSubject('taskDesc').first().blur();
+ $el.find(testSubjSelector('taskDesc')).first().blur();
expect($scope.person.errorCount()).to.be(2);
expect($scope.person.softErrorCount()).to.be(1);
@@ -177,7 +178,7 @@ describe('fancy forms', function () {
expect(form.softErrorCount()).to.be(0);
// blurs only count locally
- $task.findTestSubject('taskDesc').blur();
+ $task.find(testSubjSelector('taskDesc')).blur();
expect(form.softErrorCount()).to.be(1);
// but parent form see them
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap
index 8a0efdef72011..12492b0bb7b68 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.js.snap
@@ -14,7 +14,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = `
,
+ "content": ,
"data-test-subj": "syntaxTab",
"id": "syntax",
"name": "Syntax",
@@ -23,7 +23,7 @@ exports[`ScriptingHelpFlyout should render normally 1`] = `
tabs={
Array [
Object {
- "content": ,
+ "content": ,
"data-test-subj": "syntaxTab",
"id": "syntax",
"name": "Syntax",
diff --git a/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js b/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js
index 0bd5fe8e8ed77..aeffdbc8bfa6c 100644
--- a/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js
+++ b/src/legacy/ui/public/field_wildcard/__tests__/field_wildcard.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FieldWildcardProvider } from '../../field_wildcard';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js
index faa2378ad8bf5..49fbafdf4ee92 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_add_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import MockState from 'fixtures/mock_state';
import { FilterBarQueryFilterProvider } from '../query_filter';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js
index 5b0abd9efcdf4..3805ce1ccaf1e 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_get_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import MockState from 'fixtures/mock_state';
import { FilterBarQueryFilterProvider } from '../query_filter';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js
index 06e6ccea2eca5..e705cf22cf7fe 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_invert_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import MockState from 'fixtures/mock_state';
import { FilterBarQueryFilterProvider } from '../query_filter';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js
index d200cbec52c4d..2c9eb4f730ada 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_pin_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import MockState from 'fixtures/mock_state';
import { FilterBarQueryFilterProvider } from '../query_filter';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js
index 617a56da4c03c..a723031f67c4c 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_remove_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import MockState from 'fixtures/mock_state';
import { FilterBarQueryFilterProvider } from '../query_filter';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js b/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js
index 0fe5be25a12ef..d1eb26641a770 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/_toggle_filters.js
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import sinon from 'sinon';
import MockState from 'fixtures/mock_state';
diff --git a/src/legacy/ui/public/filter_bar/__tests__/push_filter.js b/src/legacy/ui/public/filter_bar/__tests__/push_filter.js
index 7d8e38b8af7f8..81b418e5665c6 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/push_filter.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/push_filter.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarPushFilterProvider } from '../push_filter';
describe('Filter Bar pushFilter()', function () {
diff --git a/src/legacy/ui/public/filter_bar/__tests__/query_filter.js b/src/legacy/ui/public/filter_bar/__tests__/query_filter.js
index e3d8a0e8b61d2..9e5d3b8973c09 100644
--- a/src/legacy/ui/public/filter_bar/__tests__/query_filter.js
+++ b/src/legacy/ui/public/filter_bar/__tests__/query_filter.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import './_get_filters';
import './_add_filters';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js b/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js
index b9916c1f08a06..52c54a4937cc8 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/change_time_filter.test.js
@@ -36,7 +36,7 @@ jest.mock('ui/chrome',
},
}), { virtual: true });
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { changeTimeFilter } from '../change_time_filter';
import { timefilter } from 'ui/timefilter';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js
index 9b6b56f8f2c10..cbe511b326c0b 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/dedup_filters.js
@@ -18,7 +18,7 @@
*/
import { dedupFilters } from '../dedup_filters';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Filter Bar Directive', function () {
describe('dedupFilters(existing, filters)', function () {
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js b/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js
index da85160ef1944..970d175526841 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/extract_time_filter.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibExtractTimeFilterProvider } from '../extract_time_filter';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js b/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js
index bcf6829184787..49f70b457f996 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js
@@ -18,7 +18,7 @@
*/
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibGenerateMappingChainProvider } from '../generate_mapping_chain';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js
index e09da2a0baed7..f979c4fd1450e 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapAndFlattenFiltersProvider } from '../map_and_flatten_filters';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js
index 52400ceeb2a21..e22f4639d97e1 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_default.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapDefaultProvider } from '../map_default';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js
index 8a36d5cf82af6..f0b09da6ba687 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_exists.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapExistsProvider } from '../map_exists';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js
index e15baab9e1182..0e307e2669ac2 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_filter.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapFilterProvider } from '../map_filter';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js
index 7f71845deed95..8b0ca4715d284 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapFlattenAndWrapFiltersProvider } from '../map_flatten_and_wrap_filters';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js
index 0a61d20f3ba35..6f9d757f4b9b8 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapGeoBoundingBoxProvider } from '../map_geo_bounding_box';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js
index 9f501d68c1c9f..6b17ac5b6b691 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapGeoPolygonProvider } from '../map_geo_polygon';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js
index d092e6d7979c4..b12128929903b 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_match_all.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapMatchAllProvider } from '../map_match_all';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js
index 551898c8fbdda..005b8883be51c 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_missing.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { FilterBarLibMapMissingProvider } from '../map_missing';
describe('Filter Bar Directive', function () {
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js
index 0e646088a2dfc..4a0262d93a194 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_phrase.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapPhraseProvider } from '../map_phrase';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js
index a0d7a8f5b2876..056ba8b8a7de1 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_query_string.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapQueryStringProvider } from '../map_query_string';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js b/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js
index 9ec5725be2b2c..866a692751170 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/map_range.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterBarLibMapRangeProvider } from '../map_range';
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js b/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js
index 7bc9c6c58d2ed..a6f4c74a70bab 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/only_disabled.js
@@ -18,7 +18,7 @@
*/
import { onlyDisabled } from '../only_disabled';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Filter Bar Directive', function () {
describe('onlyDisabled()', function () {
diff --git a/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js b/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js
index e42cc71485ab5..569f03f28192b 100644
--- a/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js
+++ b/src/legacy/ui/public/filter_bar/lib/__tests__/uniq_filters.js
@@ -18,7 +18,7 @@
*/
import { uniqFilters } from '../uniq_filters';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Filter Bar Directive', function () {
describe('uniqFilter', function () {
diff --git a/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js b/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js
index 87a0ed052a1c3..f1f374e0a7c3e 100644
--- a/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js
+++ b/src/legacy/ui/public/filter_manager/__tests__/filter_manager.js
@@ -20,7 +20,7 @@
import _ from 'lodash';
import sinon from 'sinon';
import MockState from 'fixtures/mock_state';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { FilterManagerProvider } from '..';
import { FilterBarQueryFilterProvider } from '../../filter_bar/query_filter';
diff --git a/src/legacy/ui/public/filters/__tests__/comma_list.js b/src/legacy/ui/public/filters/__tests__/comma_list.js
index ec1333b1c616f..f5b155b989ac2 100644
--- a/src/legacy/ui/public/filters/__tests__/comma_list.js
+++ b/src/legacy/ui/public/filters/__tests__/comma_list.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../comma_list';
diff --git a/src/legacy/ui/public/filters/__tests__/field_type.js b/src/legacy/ui/public/filters/__tests__/field_type.js
index da1b5f3537d59..0b969095eb499 100644
--- a/src/legacy/ui/public/filters/__tests__/field_type.js
+++ b/src/legacy/ui/public/filters/__tests__/field_type.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import _ from 'lodash';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/filters/__tests__/label.js b/src/legacy/ui/public/filters/__tests__/label.js
index 7f702896b58c9..1696415229749 100644
--- a/src/legacy/ui/public/filters/__tests__/label.js
+++ b/src/legacy/ui/public/filters/__tests__/label.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/filters/__tests__/moment.js b/src/legacy/ui/public/filters/__tests__/moment.js
index e3550df031ee7..39d7a520851d4 100644
--- a/src/legacy/ui/public/filters/__tests__/moment.js
+++ b/src/legacy/ui/public/filters/__tests__/moment.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import moment from 'moment';
import ngMock from 'ng_mock';
diff --git a/src/legacy/ui/public/filters/__tests__/prop_filter.js b/src/legacy/ui/public/filters/__tests__/prop_filter.js
index 2b125c47c408b..ec60121960ecb 100644
--- a/src/legacy/ui/public/filters/__tests__/prop_filter.js
+++ b/src/legacy/ui/public/filters/__tests__/prop_filter.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { propFilter } from '../_prop_filter';
describe('prop filter', function () {
diff --git a/src/legacy/ui/public/filters/__tests__/rison.js b/src/legacy/ui/public/filters/__tests__/rison.js
index 671ef5debc659..62accfa8118a7 100644
--- a/src/legacy/ui/public/filters/__tests__/rison.js
+++ b/src/legacy/ui/public/filters/__tests__/rison.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/filters/__tests__/short_dots.js b/src/legacy/ui/public/filters/__tests__/short_dots.js
index 2d23715f7a9e2..747c2c280750e 100644
--- a/src/legacy/ui/public/filters/__tests__/short_dots.js
+++ b/src/legacy/ui/public/filters/__tests__/short_dots.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
import '../short_dots';
diff --git a/src/legacy/ui/public/filters/__tests__/start_from.js b/src/legacy/ui/public/filters/__tests__/start_from.js
index 4b93042779111..389522bcbf944 100644
--- a/src/legacy/ui/public/filters/__tests__/start_from.js
+++ b/src/legacy/ui/public/filters/__tests__/start_from.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../start_from';
diff --git a/src/legacy/ui/public/filters/__tests__/uriescape.js b/src/legacy/ui/public/filters/__tests__/uriescape.js
index 2e9e14d3b0783..49a7034593821 100644
--- a/src/legacy/ui/public/filters/__tests__/uriescape.js
+++ b/src/legacy/ui/public/filters/__tests__/uriescape.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import 'plugins/kibana/discover/index';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js b/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js
index 101032413cc2d..3d5fd961c9b51 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/_get_computed_fields.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
import { getComputedFields } from '../_get_computed_fields';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js b/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js
index 023e61bdf8a01..bf1234e95f9fc 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/_index_pattern.js
@@ -20,7 +20,7 @@
import _ from 'lodash';
import sinon from 'sinon';
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import Promise from 'bluebird';
import { DuplicateField } from '../../errors';
import { IndexedArray } from '../../indexed_array';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js b/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js
index 5615edad3453a..6470c0ae04749 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/flatten_hit.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { IndexPatternsFlattenHitProvider } from '../_flatten_hit';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js b/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js
index 6b32674b5e3ea..5a6cf3ba51c67 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/index_patterns.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { IndexPatternProvider } from '../_index_pattern';
import { IndexPatternsProvider } from '../index_patterns';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/intervals.js b/src/legacy/ui/public/index_patterns/__tests__/intervals.js
index 07e4ec81e2097..cc2ba5d5f4745 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/intervals.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/intervals.js
@@ -18,7 +18,7 @@
*/
import moment from 'moment';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { IndexPatternsIntervalsProvider } from '../_intervals';
diff --git a/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js b/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js
index 1a6c472593712..a3af1332136a8 100644
--- a/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js
+++ b/src/legacy/ui/public/index_patterns/__tests__/unsupported_time_patterns.js
@@ -18,7 +18,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import Chance from 'chance';
import { Storage } from '../../storage';
diff --git a/src/legacy/ui/public/index_patterns/route_setup/load_default.js b/src/legacy/ui/public/index_patterns/route_setup/load_default.js
index 6de1eb2b812a8..669b33d731983 100644
--- a/src/legacy/ui/public/index_patterns/route_setup/load_default.js
+++ b/src/legacy/ui/public/index_patterns/route_setup/load_default.js
@@ -59,7 +59,7 @@ function displayBanner() {
}, 15000);
}
-// eslint-disable-next-line @elastic/kibana-custom/no-default-export
+// eslint-disable-next-line @kbn/eslint/no-default-export
export default function (opts) {
opts = opts || {};
const whenMissingRedirectTo = opts.whenMissingRedirectTo || null;
diff --git a/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js b/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js
index e825df5d294ca..04503be6f7f78 100644
--- a/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js
+++ b/src/legacy/ui/public/index_patterns/static_utils/__tests__/index.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isFilterable } from '../index';
const mockField = {
diff --git a/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js b/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js
index 66966fe095198..ccce39cdfa4d1 100644
--- a/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js
+++ b/src/legacy/ui/public/indexed_array/__tests__/indexed_array.js
@@ -19,7 +19,7 @@
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { IndexedArray } from '..';
// this is generally a data-structure that IndexedArray is good for managing
diff --git a/src/legacy/ui/public/indexed_array/__tests__/inflector.js b/src/legacy/ui/public/indexed_array/__tests__/inflector.js
index ffdbbee361085..49ac79094e501 100644
--- a/src/legacy/ui/public/indexed_array/__tests__/inflector.js
+++ b/src/legacy/ui/public/indexed_array/__tests__/inflector.js
@@ -18,7 +18,7 @@
*/
import { inflector } from '../inflector';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('IndexedArray Inflector', function () {
it('returns a function', function () {
diff --git a/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap b/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap
index 9d5e8fe0725a0..aa16a91a4c9ad 100644
--- a/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap
+++ b/src/legacy/ui/public/inspector/ui/__snapshots__/inspector_panel.test.js.snap
@@ -242,8 +242,11 @@ exports[`InspectorPanel should render as expected 1`] = `
').attr('data-test-subj', subject);
-}
-
-describe('jQuery.findTestSubject', function () {
- it('finds all of the element with a subject', function () {
- const $container = $('
');
- const $match = $make('subject').appendTo($container);
- const $noMatch = $make('notSubject').appendTo($container);
-
- const $found = $container.findTestSubject('subject');
- expect($found.is($match)).to.be(true);
- expect($found.is($noMatch)).to.be(false);
- });
-
- it('finds multiple elements with a subject', function () {
- const $container = $('
');
- const $match = $make('subject').appendTo($container);
- const $otherMatch = $make('subject').appendTo($container);
-
- const $found = $container.findTestSubject('subject');
- expect($found.filter($match).length).to.be(1);
- expect($found.filter($otherMatch).length).to.be(1);
- });
-
- it('finds all of the elements with either subject', function () {
- const $container = $('
');
- const $match1 = $make('subject').appendTo($container);
- const $match2 = $make('alsoSubject').appendTo($container);
- const $noMatch = $make('notSubject').appendTo($container);
-
- const $found = $container.findTestSubject('subject', 'alsoSubject');
- expect($found.filter($match1).length).to.be(1);
- expect($found.filter($match2).length).to.be(1);
- expect($found.filter($noMatch).length).to.be(0);
- });
-
- it('finds all of the elements with a descendant selector', function () {
- const $container = $('
- (
-
- )}
+ items={errorGroupListData}
+ location={location}
/>
diff --git a/x-pack/plugins/apm/public/components/app/Main/GlobalFetchIndicator.tsx b/x-pack/plugins/apm/public/components/app/Main/GlobalFetchIndicator.tsx
new file mode 100644
index 0000000000000..0cd13009685ad
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/Main/GlobalFetchIndicator.tsx
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+import { EuiDelayHide, EuiPortal, EuiProgress } from '@elastic/eui';
+import React, { Fragment, useMemo, useReducer } from 'react';
+
+export const GlobalFetchContext = React.createContext({
+ statuses: {},
+ dispatchStatus: (action: Action) => undefined as void
+});
+
+interface State {
+ [key: string]: boolean;
+}
+
+interface Action {
+ isLoading: boolean;
+ name: string;
+}
+
+function reducer(statuses: State, action: Action) {
+ return { ...statuses, [action.name]: action.isLoading };
+}
+
+function getIsAnyLoading(statuses: State) {
+ return Object.values(statuses).some(isLoading => isLoading);
+}
+
+export function GlobalFetchIndicator({
+ children
+}: {
+ children: React.ReactNode;
+}) {
+ const [statuses, dispatchStatus] = useReducer(reducer, {});
+ const isLoading = useMemo(() => getIsAnyLoading(statuses), [statuses]);
+
+ return (
+
+ (
+
+
+
+ )}
+ />
+
+
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/index.ts b/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/index.ts
deleted file mode 100644
index f9a8b4ecb2dd3..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/index.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-import { get, some } from 'lodash';
-import { connect } from 'react-redux';
-import { IReduxState } from 'x-pack/plugins/apm/public/store/rootReducer';
-import { STATUS } from '../../../../constants/index';
-import { GlobalProgressView } from './view';
-
-function getIsLoading(state: IReduxState) {
- return some(
- state.reactReduxRequest,
- subState => get(subState, 'status') === STATUS.LOADING
- );
-}
-
-function mapStateToProps(state = {} as IReduxState) {
- return {
- isLoading: getIsLoading(state)
- };
-}
-
-export const GlobalProgress = connect(mapStateToProps)(GlobalProgressView);
diff --git a/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/view.tsx b/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/view.tsx
deleted file mode 100644
index 77995714eff42..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Main/GlobalProgress/view.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-import { EuiDelayHide, EuiPortal, EuiProgress } from '@elastic/eui';
-import React from 'react';
-
-interface Props {
- isLoading: boolean;
-}
-
-export function GlobalProgressView({ isLoading }: Props) {
- return (
- (
-
-
-
- )}
- />
- );
-}
diff --git a/x-pack/plugins/apm/public/components/app/Main/LicenseCheck/index.tsx b/x-pack/plugins/apm/public/components/app/Main/LicenseCheck/index.tsx
index 8db0127fb4a2b..1385096babdef 100644
--- a/x-pack/plugins/apm/public/components/app/Main/LicenseCheck/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/LicenseCheck/index.tsx
@@ -4,21 +4,31 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
-import { STATUS } from '../../../../constants/index';
-import { LicenceRequest } from '../../../../store/reactReduxRequest/license';
+import {
+ FETCH_STATUS,
+ useFetcher
+} from 'x-pack/plugins/apm/public/hooks/useFetcher';
+import { loadLicense } from 'x-pack/plugins/apm/public/services/rest/xpack';
import { InvalidLicenseNotification } from './InvalidLicenseNotification';
-export const LicenseCheck: React.FunctionComponent = ({ children }) => {
- return (
- {
- const hasValidLicense = licenseData.license.is_active;
- if (licenseStatus === STATUS.SUCCESS && !hasValidLicense) {
- return ;
- }
+const initialLicense = {
+ features: {
+ watcher: { is_available: false },
+ ml: { is_available: false }
+ },
+ license: { is_active: false }
+};
+export const LicenseContext = React.createContext(initialLicense);
+
+export const LicenseCheck: React.FC = ({ children }) => {
+ const { data = initialLicense, status } = useFetcher(() => loadLicense(), []);
+ const hasValidLicense = data.license.is_active;
+
+ // if license is invalid show an error message
+ if (status === FETCH_STATUS.SUCCESS && !hasValidLicense) {
+ return ;
+ }
- return children;
- }}
- />
- );
+ // render rest of application and pass down license via context
+ return ;
};
diff --git a/x-pack/plugins/apm/public/components/app/Main/index.tsx b/x-pack/plugins/apm/public/components/app/Main/index.tsx
index 407d1394f81f8..908a0f0211645 100644
--- a/x-pack/plugins/apm/public/components/app/Main/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/index.tsx
@@ -10,6 +10,7 @@ import styled from 'styled-components';
import { px, topNavHeight, unit, units } from '../../../style/variables';
// @ts-ignore
import ConnectRouterToRedux from '../../shared/ConnectRouterToRedux';
+import { GlobalFetchIndicator } from './GlobalFetchIndicator';
import { LicenseCheck } from './LicenseCheck';
import { routes } from './routeConfig';
import { ScrollToTopOnPathChange } from './ScrollToTopOnPathChange';
@@ -23,17 +24,19 @@ const MainContainer = styled.div`
export function Main() {
return (
-
-
-
-
-
-
- {routes.map((route, i) => (
-
- ))}
-
-
-
+
+
+
+
+
+
+
+ {routes.map((route, i) => (
+
+ ))}
+
+
+
+
);
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/CPUUsageChart.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/CPUUsageChart.tsx
index 46b3243e8649d..264aae21da89e 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceDetails/CPUUsageChart.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/CPUUsageChart.tsx
@@ -11,11 +11,11 @@ import React from 'react';
import CustomPlot from 'x-pack/plugins/apm/public/components/shared/charts/CustomPlot';
import { HoverXHandlers } from 'x-pack/plugins/apm/public/components/shared/charts/SyncChartGroup';
import { asPercent } from 'x-pack/plugins/apm/public/utils/formatters';
-import { CPUChartAPIResponse } from 'x-pack/plugins/apm/server/lib/metrics/get_cpu_chart_data/transformer';
import { Coordinate } from 'x-pack/plugins/apm/typings/timeseries';
+import { CPUMetricSeries } from '../../../store/selectors/chartSelectors';
interface Props {
- data: CPUChartAPIResponse;
+ data: CPUMetricSeries;
hoverXHandlers: HoverXHandlers;
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/MemoryUsageChart.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/MemoryUsageChart.tsx
index 4f620be40ec88..4356142add4c6 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceDetails/MemoryUsageChart.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/MemoryUsageChart.tsx
@@ -11,11 +11,11 @@ import React from 'react';
import CustomPlot from 'x-pack/plugins/apm/public/components/shared/charts/CustomPlot';
import { HoverXHandlers } from 'x-pack/plugins/apm/public/components/shared/charts/SyncChartGroup';
import { asPercent } from 'x-pack/plugins/apm/public/utils/formatters';
-import { MemoryChartAPIResponse } from 'x-pack/plugins/apm/server/lib/metrics/get_memory_chart_data/transformer';
import { Coordinate } from 'x-pack/plugins/apm/typings/timeseries';
+import { MemoryMetricSeries } from '../../../store/selectors/chartSelectors';
interface Props {
- data: MemoryChartAPIResponse;
+ data: MemoryMetricSeries;
hoverXHandlers: HoverXHandlers;
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx
deleted file mode 100644
index aea1ae113c532..0000000000000
--- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout.tsx
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * 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.
- */
-
-import {
- EuiButton,
- EuiCallOut,
- EuiFlexGroup,
- EuiFlexItem,
- EuiFlyout,
- EuiFlyoutBody,
- EuiFlyoutFooter,
- EuiFlyoutHeader,
- EuiFormRow,
- EuiSpacer,
- EuiText,
- EuiTitle
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { Location } from 'history';
-import React, { Component } from 'react';
-import { toastNotifications } from 'ui/notify';
-import { getMlJobId } from 'x-pack/plugins/apm/common/ml_job_constants';
-import { KibanaLink } from 'x-pack/plugins/apm/public/components/shared/Links/KibanaLink';
-import { MLJobLink } from 'x-pack/plugins/apm/public/components/shared/Links/MLJobLink';
-import { startMLJob } from 'x-pack/plugins/apm/public/services/rest/ml';
-import { getAPMIndexPattern } from 'x-pack/plugins/apm/public/services/rest/savedObjects';
-import { MLJobsRequest } from 'x-pack/plugins/apm/public/store/reactReduxRequest/machineLearningJobs';
-import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams';
-import { TransactionSelect } from './TransactionSelect';
-
-interface FlyoutProps {
- isOpen: boolean;
- onClose: () => void;
- urlParams: IUrlParams;
- location: Location;
- serviceTransactionTypes: string[];
-}
-
-interface FlyoutState {
- isLoading: boolean;
- hasMLJob: boolean;
- hasIndexPattern: boolean;
- selectedTransactionType?: string;
-}
-
-export class MachineLearningFlyout extends Component {
- public state = {
- isLoading: false,
- hasIndexPattern: false,
- hasMLJob: false,
- selectedTransactionType: this.props.urlParams.transactionType
- };
- public willUnmount = false;
-
- public componentWillUnmount() {
- this.willUnmount = true;
- }
-
- public async componentDidMount() {
- const indexPattern = await getAPMIndexPattern();
- if (!this.willUnmount) {
- this.setState({ hasIndexPattern: !!indexPattern });
- }
- }
-
- // TODO: This should use `getDerivedStateFromProps`
- public componentDidUpdate(prevProps: FlyoutProps) {
- if (
- prevProps.urlParams.transactionType !==
- this.props.urlParams.transactionType
- ) {
- this.setState({
- selectedTransactionType: this.props.urlParams.transactionType
- });
- }
- }
-
- public createJob = async () => {
- this.setState({ isLoading: true });
- try {
- const { serviceName, transactionType } = this.props.urlParams;
- if (!serviceName || !transactionType) {
- throw new Error(
- 'Service name and transaction type are required to create this ML job'
- );
- }
- const res = await startMLJob({ serviceName, transactionType });
- const didSucceed = res.datafeeds[0].success && res.jobs[0].success;
- if (!didSucceed) {
- throw new Error('Creating ML job failed');
- }
- this.addSuccessToast();
- } catch (e) {
- this.addErrorToast();
- }
-
- this.setState({ isLoading: false });
- this.props.onClose();
- };
-
- public addErrorToast = () => {
- const { urlParams } = this.props;
- const { serviceName } = urlParams;
-
- if (!serviceName) {
- return;
- }
-
- toastNotifications.addWarning({
- title: i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreationFailedNotificationTitle',
- {
- defaultMessage: 'Job creation failed'
- }
- ),
- text: (
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreationFailedNotificationText',
- {
- defaultMessage:
- 'Your current license may not allow for creating machine learning jobs, or this job may already exist.'
- }
- )}
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreatedNotificationText',
- {
- defaultMessage:
- 'The analysis is now running for {serviceName} ({transactionType}). It might take a while before results are added to the response times graph.',
- values: {
- serviceName,
- transactionType
- }
- }
- )}{' '}
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreatedNotificationText.viewJobLinkText',
- {
- defaultMessage: 'View job'
- }
- )}
-
-
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.manageMLJobDescription.mlJobsPageLinkText',
- {
- defaultMessage:
- 'Machine Learning jobs management page'
- }
- )}
-
- )
- }}
- />{' '}
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.manageMLJobDescription.noteText',
- {
- defaultMessage:
- 'Note: It might take a few minutes for the job to begin calculating results.'
- }
- )}
-
-
-
-
-
-
-
-
-
- {this.props.serviceTransactionTypes.length > 1 ? (
-
- this.setState({
- selectedTransactionType: value
- })
- }
- />
- ) : null}
-
-
-
-
- {i18n.translate(
- 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.createNewJobButtonLabel',
- {
- defaultMessage: 'Create new job'
- }
- )}
-
-
-
-
-
-
- );
- }}
- />
- );
- }
-}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/TransactionSelect.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/TransactionSelect.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/TransactionSelect.tsx
rename to x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/TransactionSelect.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx
new file mode 100644
index 0000000000000..0f32fb9c91359
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceIntegrations/MachineLearningFlyout/index.tsx
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+import { i18n } from '@kbn/i18n';
+import { Location } from 'history';
+import React, { Component } from 'react';
+import { toastNotifications } from 'ui/notify';
+import { MLJobLink } from 'x-pack/plugins/apm/public/components/shared/Links/MLJobLink';
+import { startMLJob } from 'x-pack/plugins/apm/public/services/rest/ml';
+import { getAPMIndexPattern } from 'x-pack/plugins/apm/public/services/rest/savedObjects';
+import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams';
+import { MachineLearningFlyoutView } from './view';
+
+interface Props {
+ isOpen: boolean;
+ onClose: () => void;
+ urlParams: IUrlParams;
+ location: Location;
+ serviceTransactionTypes: string[];
+}
+
+interface State {
+ isCreatingJob: boolean;
+ hasMLJob: boolean;
+ hasIndexPattern: boolean;
+ selectedTransactionType?: string;
+}
+
+export class MachineLearningFlyout extends Component {
+ public state: State = {
+ isCreatingJob: false,
+ hasIndexPattern: false,
+ hasMLJob: false,
+ selectedTransactionType: this.props.urlParams.transactionType
+ };
+ public willUnmount = false;
+
+ public componentWillUnmount() {
+ this.willUnmount = true;
+ }
+
+ public async componentDidMount() {
+ const indexPattern = await getAPMIndexPattern();
+ if (!this.willUnmount) {
+ // TODO: this is causing warning from react because setState happens after
+ // the component has been unmounted - dispite of the checks
+ this.setState({ hasIndexPattern: !!indexPattern });
+ }
+ }
+
+ // TODO: This should use `getDerivedStateFromProps`
+ public componentDidUpdate(prevProps: Props) {
+ if (
+ prevProps.urlParams.transactionType !==
+ this.props.urlParams.transactionType
+ ) {
+ this.setState({
+ selectedTransactionType: this.props.urlParams.transactionType
+ });
+ }
+ }
+
+ public onClickCreate = async () => {
+ this.setState({ isCreatingJob: true });
+ try {
+ const { serviceName, transactionType } = this.props.urlParams;
+ if (!serviceName || !transactionType) {
+ throw new Error(
+ 'Service name and transaction type are required to create this ML job'
+ );
+ }
+ const res = await startMLJob({ serviceName, transactionType });
+ const didSucceed = res.datafeeds[0].success && res.jobs[0].success;
+ if (!didSucceed) {
+ throw new Error('Creating ML job failed');
+ }
+ this.addSuccessToast();
+ } catch (e) {
+ this.addErrorToast();
+ }
+
+ this.setState({ isCreatingJob: false });
+ this.props.onClose();
+ };
+
+ public addErrorToast = () => {
+ const { urlParams } = this.props;
+ const { serviceName } = urlParams;
+
+ if (!serviceName) {
+ return;
+ }
+
+ toastNotifications.addWarning({
+ title: i18n.translate(
+ 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreationFailedNotificationTitle',
+ {
+ defaultMessage: 'Job creation failed'
+ }
+ ),
+ text: (
+
+ {i18n.translate(
+ 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreationFailedNotificationText',
+ {
+ defaultMessage:
+ 'Your current license may not allow for creating machine learning jobs, or this job may already exist.'
+ }
+ )}
+
+ {i18n.translate(
+ 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreatedNotificationText',
+ {
+ defaultMessage:
+ 'The analysis is now running for {serviceName} ({transactionType}). It might take a while before results are added to the response times graph.',
+ values: {
+ serviceName,
+ transactionType
+ }
+ }
+ )}{' '}
+
+ {i18n.translate(
+ 'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreatedNotificationText.viewJobLinkText',
+ {
+ defaultMessage: 'View job'
+ }
+ )}
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }}
+ transactionTypes={serviceDetailsData.types}
/>
- );
- }
+
+ );
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
index 0d9dd1ed1381f..8bb29b285e097 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
@@ -16,7 +16,7 @@ import { asDecimal, asMillis } from '../../../../utils/formatters';
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
interface Props {
- items: IServiceListItem[];
+ items?: IServiceListItem[];
noItemsMessage?: React.ReactNode;
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.js
deleted file mode 100644
index 2a6d3f8e5fd2e..0000000000000
--- a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-import React from 'react';
-import { shallow } from 'enzyme';
-import { ServiceOverview } from '../view';
-import { STATUS } from '../../../../constants';
-import * as apmRestServices from '../../../../services/rest/apm/status_check';
-jest.mock('../../../../services/rest/apm/status_check');
-
-describe('Service Overview -> View', () => {
- let mockAgentStatus;
- let wrapper;
- let instance;
-
- beforeEach(() => {
- mockAgentStatus = {
- dataFound: true
- };
-
- apmRestServices.loadAgentStatus = jest.fn(() =>
- Promise.resolve(mockAgentStatus)
- );
-
- wrapper = shallow();
- instance = wrapper.instance();
- });
-
- it('should render when historical data is found', () => {
- expect(wrapper).toMatchSnapshot();
- const List = wrapper
- .find('ServiceListRequest')
- .props()
- .render({});
- expect(List.props).toMatchSnapshot();
- });
-
- it('should render when historical data is not found', () => {
- wrapper.setState({ historicalDataFound: false });
- expect(wrapper).toMatchSnapshot();
- const List = wrapper
- .find('ServiceListRequest')
- .props()
- .render({});
- expect(List.props).toMatchSnapshot();
- });
-
- it('should check for historical data once', () => {});
-
- describe('checking for historical data', () => {
- it('should set historical data to true if data is found', async () => {
- const props = {
- serviceList: {
- status: STATUS.SUCCESS,
- data: []
- }
- };
- await instance.checkForHistoricalData(props);
- expect(wrapper.state('historicalDataFound')).toEqual(true);
- });
-
- it('should set historical data state to false if data is NOT found', async () => {
- const props = {
- serviceList: {
- status: STATUS.SUCCESS,
- data: []
- }
- };
- mockAgentStatus.dataFound = false;
- await instance.checkForHistoricalData(props);
- expect(wrapper.state('historicalDataFound')).toEqual(false);
- });
- });
-});
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx
new file mode 100644
index 0000000000000..a82be56866e39
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/ServiceOverview.test.tsx
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+import React from 'react';
+import { Provider } from 'react-redux';
+import { render, wait, waitForElement } from 'react-testing-library';
+import 'react-testing-library/cleanup-after-each';
+import * as apmRestServices from 'x-pack/plugins/apm/public/services/rest/apm/services';
+// @ts-ignore
+import configureStore from 'x-pack/plugins/apm/public/store/config/configureStore';
+import * as statusCheck from '../../../../services/rest/apm/status_check';
+import { ServiceOverview } from '../view';
+
+function Comp() {
+ const store = configureStore();
+
+ return (
+
+
+
+ );
+}
+
+describe('Service Overview -> View', () => {
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ // Suppress warnings about "act" until async/await syntax is supported: https://github.com/facebook/react/issues/14769
+ /* tslint:disable:no-console */
+ const originalError = console.error;
+ beforeAll(() => {
+ console.error = jest.fn();
+ });
+ afterAll(() => {
+ console.error = originalError;
+ });
+
+ it('should render services, when list is not empty', async () => {
+ // mock rest requests
+ const spy1 = jest
+ .spyOn(statusCheck, 'loadAgentStatus')
+ .mockResolvedValue(true);
+ const spy2 = jest
+ .spyOn(apmRestServices, 'loadServiceList')
+ .mockResolvedValue([
+ {
+ serviceName: 'My Python Service',
+ agentName: 'python',
+ transactionsPerMinute: 100,
+ errorsPerMinute: 200,
+ avgResponseTime: 300
+ },
+ {
+ serviceName: 'My Go Service',
+ agentName: 'go',
+ transactionsPerMinute: 400,
+ errorsPerMinute: 500,
+ avgResponseTime: 600
+ }
+ ]);
+
+ const { container, getByText } = render();
+
+ // wait for requests to be made
+ await wait(
+ () =>
+ expect(spy1).toHaveBeenCalledTimes(1) &&
+ expect(spy2).toHaveBeenCalledTimes(1)
+ );
+
+ await waitForElement(() => getByText('My Python Service'));
+
+ expect(container.querySelectorAll('.euiTableRow')).toMatchSnapshot();
+ });
+
+ it('should render getting started message, when list is empty and no historical data is found', async () => {
+ // mock rest requests
+ const spy1 = jest
+ .spyOn(statusCheck, 'loadAgentStatus')
+ .mockResolvedValue(false);
+
+ const spy2 = jest
+ .spyOn(apmRestServices, 'loadServiceList')
+ .mockResolvedValue([]);
+
+ const { container, getByText } = render();
+
+ // wait for requests to be made
+ await wait(
+ () =>
+ expect(spy1).toHaveBeenCalledTimes(1) &&
+ expect(spy2).toHaveBeenCalledTimes(1)
+ );
+
+ // wait for elements to be rendered
+ await waitForElement(() =>
+ getByText(
+ "Looks like you don't have any APM services installed. Let's add some!"
+ )
+ );
+
+ expect(container.querySelectorAll('.euiTableRow')).toMatchSnapshot();
+ });
+
+ it('should render empty message, when list is empty and historical data is found', async () => {
+ // mock rest requests
+ const spy1 = jest
+ .spyOn(statusCheck, 'loadAgentStatus')
+ .mockResolvedValue(true);
+ const spy2 = jest
+ .spyOn(apmRestServices, 'loadServiceList')
+ .mockResolvedValue([]);
+
+ const { container, getByText } = render();
+
+ // wait for requests to be made
+ await wait(
+ () =>
+ expect(spy1).toHaveBeenCalledTimes(1) &&
+ expect(spy2).toHaveBeenCalledTimes(1)
+ );
+
+ // wait for elements to be rendered
+ await waitForElement(() => getByText('No services found'));
+
+ expect(container.querySelectorAll('.euiTableRow')).toMatchSnapshot();
+ });
+});
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.js.snap b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.js.snap
deleted file mode 100644
index a08ba5312ba5c..0000000000000
--- a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.js.snap
+++ /dev/null
@@ -1,43 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Service Overview -> View should render when historical data is found 1`] = `
-
-
-
-`;
-
-exports[`Service Overview -> View should render when historical data is found 2`] = `
-Object {
- "items": Array [],
- "noItemsMessage": ,
-}
-`;
-
-exports[`Service Overview -> View should render when historical data is not found 1`] = `
-
-
-
-`;
-
-exports[`Service Overview -> View should render when historical data is not found 2`] = `
-Object {
- "items": Array [],
- "noItemsMessage": ,
-}
-`;
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap
new file mode 100644
index 0000000000000..b7f431249daf8
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/__test__/__snapshots__/ServiceOverview.test.tsx.snap
@@ -0,0 +1,296 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Service Overview -> View should render empty message, when list is empty and historical data is found 1`] = `
+NodeList [
+
+
+
+
+
+
+
+ No services found
+
+
+
+
+
+
+
+
,
+]
+`;
+
+exports[`Service Overview -> View should render getting started message, when list is empty and no historical data is found 1`] = `
+NodeList [
+
+
+
+
+
+
+
+ Looks like you don't have any APM services installed. Let's add some!
+
+
+
+
+ Upgrading from a pre-7.x version? Make sure you've also upgraded
+ your APM server instance(s) to at least 7.0.
+
@@ -86,7 +86,7 @@ export class CrossClusterReplicationHome extends PureComponent {
onClick={() => this.onSectionChange(tab.id)}
isSelected={tab.id === this.state.activeSection}
key={tab.id}
- data-test-subject={tab.testSubj}
+ data-test-subj={tab.testSubj}
>
{tab.name}
diff --git a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js
index 318c9e211a128..f8c8cc710964a 100644
--- a/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js
+++ b/x-pack/plugins/cross_cluster_replication/public/app/services/breadcrumbs.js
@@ -9,7 +9,7 @@ import { BASE_PATH } from '../../../common/constants';
export const listBreadcrumb = {
text: i18n.translate('xpack.crossClusterReplication.homeBreadcrumbTitle', {
- defaultMessage: 'Cross Cluster Replication',
+ defaultMessage: 'Cross-Cluster Replication',
}),
href: `#${BASE_PATH}`,
};
diff --git a/x-pack/plugins/cross_cluster_replication/public/index.scss b/x-pack/plugins/cross_cluster_replication/public/index.scss
index fc1b118a5f77f..6f65dc04d4427 100644
--- a/x-pack/plugins/cross_cluster_replication/public/index.scss
+++ b/x-pack/plugins/cross_cluster_replication/public/index.scss
@@ -1,7 +1,7 @@
// Import the EUI global scope so we can use EUI constants
@import 'src/legacy/ui/public/styles/_styling_constants';
-// Cross Cluster Replication plugin styles
+// Cross-Cluster Replication plugin styles
// Prefix all styles with "ccr" to avoid conflicts.
// Examples
diff --git a/x-pack/plugins/cross_cluster_replication/public/register_routes.js b/x-pack/plugins/cross_cluster_replication/public/register_routes.js
index 960ffe844fae6..f29bf4efaba8e 100644
--- a/x-pack/plugins/cross_cluster_replication/public/register_routes.js
+++ b/x-pack/plugins/cross_cluster_replication/public/register_routes.js
@@ -22,7 +22,7 @@ if (chrome.getInjected('ccrUiEnabled')) {
esSection.register('ccr', {
visible: true,
- display: i18n.translate('xpack.crossClusterReplication.appTitle', { defaultMessage: 'Cross Cluster Replication' }),
+ display: i18n.translate('xpack.crossClusterReplication.appTitle', { defaultMessage: 'Cross-Cluster Replication' }),
order: 4,
url: `#${BASE_PATH}`
});
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js b/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js
index fb99de8ab5d97..ddde694bc549a 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/check_license/check_license.js
@@ -7,7 +7,7 @@
import { i18n } from '@kbn/i18n';
export function checkLicense(xpackLicenseInfo) {
- const pluginName = 'Cross Cluster Replication';
+ const pluginName = 'Cross-Cluster Replication';
// If, for some reason, we cannot get the license information
// from Elasticsearch, assume worst case and disable
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js
index 443744ccb0cc8..f9c102be7a1ff 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_custom_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapCustomError } from '../wrap_custom_error';
describe('wrap_custom_error', () => {
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js
index b8d59590ebf33..f3237563edb45 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_es_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapEsError } from '../wrap_es_error';
describe('wrap_es_error', () => {
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
index 6d6a336417bef..85e0b2b3033ad 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapUnknownError } from '../wrap_unknown_error';
describe('wrap_unknown_error', () => {
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
index d50ff9480d3e4..76fdf7b36c3d0 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isEsErrorFactory } from '../is_es_error_factory';
import { set } from 'lodash';
diff --git a/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index ffbbd1395a418..dc641bef91085 100644
--- a/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/cross_cluster_replication/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
describe('license_pre_routing_factory', () => {
diff --git a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js
index d3f28a1556b8b..644d006de400e 100644
--- a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js
+++ b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_auth_scope.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
CONFIG_DASHBOARD_ONLY_MODE_ROLES,
diff --git a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js
index b8c46c9e97f15..7250293fd50b0 100644
--- a/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js
+++ b/x-pack/plugins/dashboard_mode/server/__tests__/dashboard_mode_request_interceptor.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import Hapi from 'hapi';
import Chance from 'chance';
diff --git a/x-pack/plugins/graph/public/__tests__/workspace.js b/x-pack/plugins/graph/public/__tests__/workspace.js
index 2b3fe539377a4..592872c96ee05 100644
--- a/x-pack/plugins/graph/public/__tests__/workspace.js
+++ b/x-pack/plugins/graph/public/__tests__/workspace.js
@@ -5,7 +5,7 @@
*/
const gws = require('../graphClientWorkspace.js');
-const expect = require('expect.js');
+const expect = require('@kbn/expect');
describe('graphui-workspace', function () {
describe('createWorkspace()', function () {
diff --git a/x-pack/plugins/graph/public/app.js b/x-pack/plugins/graph/public/app.js
index 173c7e9ca0538..305a229a80fce 100644
--- a/x-pack/plugins/graph/public/app.js
+++ b/x-pack/plugins/graph/public/app.js
@@ -14,7 +14,11 @@ import 'uiExports/fieldFormats';
import 'uiExports/savedObjectTypes';
import 'ui/autoload/all';
+// TODO: remove ui imports completely (move to plugins)
+import 'ui/kbn_top_nav';
import 'ui/directives/saved_object_finder';
+import 'ui/directives/input_focus';
+import 'ui/saved_objects/ui/saved_object_save_as_checkbox';
import chrome from 'ui/chrome';
import { uiModules } from 'ui/modules';
import uiRoutes from 'ui/routes';
diff --git a/x-pack/plugins/graph/server/lib/__tests__/check_license.js b/x-pack/plugins/graph/server/lib/__tests__/check_license.js
index abdb1fb316bdb..c341dfbc378ca 100644
--- a/x-pack/plugins/graph/server/lib/__tests__/check_license.js
+++ b/x-pack/plugins/graph/server/lib/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import sinon from 'sinon';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js
index 7d2c0d73c4421..556abf1a405b4 100644
--- a/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js
+++ b/x-pack/plugins/grokdebugger/server/lib/check_license/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index 9196b8b813470..5458dfa9599aa 100644
--- a/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/grokdebugger/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import Boom from 'boom';
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
diff --git a/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js b/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js
index a6bc0448a0d12..a87999873e40f 100644
--- a/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js
+++ b/x-pack/plugins/grokdebugger/server/models/grokdebugger_request/__tests__/grokdebugger_request.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { GrokdebuggerRequest } from '../grokdebugger_request';
describe('grokdebugger_request', () => {
diff --git a/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js b/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js
index f483352a70d3e..b4e7eb0814bf1 100644
--- a/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js
+++ b/x-pack/plugins/grokdebugger/server/models/grokdebugger_response/__tests__/grokdebugger_response.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { GrokdebuggerResponse } from '../grokdebugger_response';
describe('grokdebugger_response', () => {
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
index cf33fa7ba5187..95f01e49c3789 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap
@@ -524,8 +524,11 @@ exports[`ilm summary extension should return extension when index has lifecycle
{
@@ -52,6 +54,8 @@ export function indexLifecycleManagement(kibana) {
registerPoliciesRoutes(server);
registerLifecycleRoutes(server);
registerIndexRoutes(server);
+ registerIndexLifecycleManagementUsageCollector(server);
+
if (
server.config().get('xpack.ilm.ui.enabled') &&
server.plugins.index_management &&
diff --git a/x-pack/plugins/index_lifecycle_management/public/app.js b/x-pack/plugins/index_lifecycle_management/public/app.js
index e316d11017a14..b644ffdcf1df4 100644
--- a/x-pack/plugins/index_lifecycle_management/public/app.js
+++ b/x-pack/plugins/index_lifecycle_management/public/app.js
@@ -4,18 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { useEffect } from 'react';
import { HashRouter, Switch, Route, Redirect } from 'react-router-dom';
+import { BASE_PATH, UA_APP_LOAD } from '../common/constants';
import { EditPolicy } from './sections/edit_policy';
import { PolicyTable } from './sections/policy_table';
-import { BASE_PATH } from '../common/constants';
+import { trackUserAction } from './services';
-export const App = () => (
-
-
-
-
-
-
-
-);
+export const App = () => {
+ useEffect(() => trackUserAction(UA_APP_LOAD), []);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/constants.js b/x-pack/plugins/index_lifecycle_management/public/constants/index.js
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/public/store/constants.js
rename to x-pack/plugins/index_lifecycle_management/public/constants/index.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js
index f6470e5c66d3c..90c30d943f68f 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.container.js
@@ -17,7 +17,7 @@ import {
PHASE_COLD,
PHASE_HOT,
PHASE_ROLLOVER_ENABLED
-} from '../../../../store/constants';
+} from '../../../../constants';
export const ColdPhase = connect(
(state) => ({
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
index ee8759f5f6b0f..c95ef1ee75d4e 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
@@ -22,7 +22,7 @@ import {
PHASE_ENABLED,
PHASE_REPLICA_COUNT,
PHASE_FREEZE_ENABLED
-} from '../../../../store/constants';
+} from '../../../../constants';
import { ErrableFormRow } from '../../form_errors';
import { MinAgeInput } from '../min_age_input';
import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, OptionalLabel } from '../../../components';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js
index b7eb4164073c1..f7933815d9f33 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.container.js
@@ -8,7 +8,7 @@ import { connect } from 'react-redux';
import { DeletePhase as PresentationComponent } from './delete_phase';
import { getPhase } from '../../../../store/selectors';
import { setPhaseData } from '../../../../store/actions';
-import { PHASE_DELETE, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants';
+import { PHASE_DELETE, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../constants';
export const DeletePhase = connect(
state => ({
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
index a10ae5ab65595..0e7663a6aef7d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
@@ -19,7 +19,7 @@ import {
import {
PHASE_DELETE,
PHASE_ENABLED,
-} from '../../../../store/constants';
+} from '../../../../constants';
import { ActiveBadge, PhaseErrorMessage } from '../../../components';
export class DeletePhase extends PureComponent {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js
index 0361d287cd402..e1ef58660525c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.container.js
@@ -11,7 +11,7 @@ import { connect } from 'react-redux';
import { HotPhase as PresentationComponent } from './hot_phase';
import { getPhase } from '../../../../store/selectors';
import { setPhaseData } from '../../../../store/actions';
-import { PHASE_HOT, PHASE_WARM, WARM_PHASE_ON_ROLLOVER } from '../../../../store/constants';
+import { PHASE_HOT, PHASE_WARM, WARM_PHASE_ON_ROLLOVER } from '../../../../constants';
export const HotPhase = connect(
state => ({
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
index ccdb2a6479b15..be1023e9042a3 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
@@ -27,7 +27,7 @@ import {
PHASE_ROLLOVER_MAX_SIZE_STORED,
PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
PHASE_ROLLOVER_ENABLED,
-} from '../../../../store/constants';
+} from '../../../../constants';
import { SetPriorityInput } from '../set_priority_input';
import { ErrableFormRow } from '../../form_errors';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js
index d290a25d0636f..d52bc147138a8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/min_age_input.js
@@ -15,7 +15,7 @@ import {
import {
PHASE_ROLLOVER_MINIMUM_AGE,
PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
-} from '../../../store/constants';
+} from '../../../constants';
import { ErrableFormRow } from '../form_errors';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
const MinAgeInputUi = props => {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js
index 60f37c4be7296..0a0f3bf9d35a7 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_allocation/node_allocation.js
@@ -7,7 +7,7 @@
import React, { Component, Fragment } from 'react';
import { EuiSelect, EuiButtonEmpty, EuiCallOut, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-import { PHASE_NODE_ATTRS } from '../../../../store/constants';
+import { PHASE_NODE_ATTRS } from '../../../../constants';
import { ErrableFormRow } from '../../form_errors';
import { LearnMoreLink } from '../../../components/learn_more_link';
const learnMoreLinks = (
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js
index af65348171957..3f4c32b05a2dc 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js
@@ -12,7 +12,7 @@ import {
} from '@elastic/eui';
import {
PHASE_INDEX_PRIORITY,
-} from '../../../store/constants';
+} from '../../../constants';
import { ErrableFormRow } from '../form_errors';
import { FormattedMessage } from '@kbn/i18n/react';
export const SetPriorityInput = props => {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
index 5b66fcae24ec2..4e68a51aee931 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
@@ -13,7 +13,7 @@ import {
getPhase,
} from '../../../../store/selectors';
import { setPhaseData } from '../../../../store/actions';
-import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants';
+import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../constants';
export const WarmPhase = connect(
state => ({
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
index d9c9d0930daf9..b25e3db0cedab 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -26,7 +26,7 @@ import {
PHASE_PRIMARY_SHARD_COUNT,
PHASE_REPLICA_COUNT,
PHASE_SHRINK_ENABLED,
-} from '../../../../store/constants';
+} from '../../../../constants';
import { SetPriorityInput } from '../set_priority_input';
import { NodeAllocation } from '../node_allocation';
import { ErrableFormRow } from '../../form_errors';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 9daa0926b5710..8e9fcc281ad27 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -36,7 +36,7 @@ import {
PHASE_DELETE,
PHASE_WARM,
STRUCTURE_POLICY_NAME,
-} from '../../store/constants';
+} from '../../constants';
import { findFirstError } from '../../services/find_errors';
import { NodeAttrsDetails } from './components/node_attrs_details';
import { PolicyJsonFlyout } from './components/policy_json_flyout';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
index 891d608b6dd66..d31aae042fe07 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
@@ -8,11 +8,7 @@ import React, { Component, Fragment } from 'react';
import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-import { BASE_PATH } from '../../../../../common/constants';
-import { NoMatch } from '../no_match';
-import { getPolicyPath } from '../../../../services/navigation';
-import { flattenPanelTree } from '../../../../services/flatten_panel_tree';
-import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
+
import {
EuiBetaBadge,
EuiButton,
@@ -38,10 +34,17 @@ import {
EuiPageBody,
EuiPageContent,
} from '@elastic/eui';
+import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
+import { getIndexListUri } from '../../../../../../index_management/public/services/navigation';
+import { BASE_PATH, UA_EDIT_CLICK } from '../../../../../common/constants';
+import { getPolicyPath } from '../../../../services/navigation';
+import { flattenPanelTree } from '../../../../services/flatten_panel_tree';
+import { trackUserAction } from '../../../../services';
+import { NoMatch } from '../no_match';
import { ConfirmDelete } from './confirm_delete';
import { AddPolicyToTemplateConfirmModal } from './add_policy_to_template_confirm_modal';
-import { getIndexListUri } from '../../../../../../index_management/public/services/navigation';
+
const COLUMNS = {
name: {
label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.nameHeader', {
@@ -176,6 +179,7 @@ export class PolicyTableUi extends Component {
className="policyTable__link"
data-test-subj="policyTablePolicyNameLink"
href={getPolicyPath(value)}
+ onClick={() => trackUserAction(UA_EDIT_CLICK)}
>
{value}
diff --git a/x-pack/plugins/index_lifecycle_management/public/services/api.js b/x-pack/plugins/index_lifecycle_management/public/services/api.js
index a82cd3a0a7543..334f986b659d4 100644
--- a/x-pack/plugins/index_lifecycle_management/public/services/api.js
+++ b/x-pack/plugins/index_lifecycle_management/public/services/api.js
@@ -4,12 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
import chrome from 'ui/chrome';
+import {
+ UA_POLICY_DELETE,
+ UA_POLICY_ATTACH_INDEX,
+ UA_POLICY_ATTACH_INDEX_TEMPLATE,
+ UA_POLICY_DETACH_INDEX,
+ UA_INDEX_RETRY_STEP,
+} from '../../common/constants';
+import { trackUserAction } from './user_action';
let httpClient;
export const setHttpClient = (client) => {
httpClient = client;
};
-const getHttpClient = () => {
+export const getHttpClient = () => {
return httpClient;
};
const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management');
@@ -44,6 +52,8 @@ export async function loadPolicies(withIndices, httpClient = getHttpClient()) {
export async function deletePolicy(policyName, httpClient = getHttpClient()) {
const response = await httpClient.delete(`${apiPrefix}/policies/${encodeURIComponent(policyName)}`);
+ // Only track successful actions.
+ trackUserAction(UA_POLICY_DELETE, httpClient);
return response.data;
}
@@ -52,7 +62,6 @@ export async function saveLifecycle(lifecycle, httpClient = getHttpClient()) {
return response.data;
}
-
export async function getAffectedIndices(indexTemplateName, policyName, httpClient = getHttpClient()) {
const path = policyName
? `${apiPrefix}/indices/affected/${indexTemplateName}/${encodeURIComponent(policyName)}`
@@ -60,19 +69,31 @@ export async function getAffectedIndices(indexTemplateName, policyName, httpClie
const response = await httpClient.get(path);
return response.data;
}
+
export const retryLifecycleForIndex = async (indexNames, httpClient = getHttpClient()) => {
const response = await httpClient.post(`${apiPrefix}/index/retry`, { indexNames });
+ // Only track successful actions.
+ trackUserAction(UA_INDEX_RETRY_STEP, httpClient);
return response.data;
};
+
export const removeLifecycleForIndex = async (indexNames, httpClient = getHttpClient()) => {
const response = await httpClient.post(`${apiPrefix}/index/remove`, { indexNames });
+ // Only track successful actions.
+ trackUserAction(UA_POLICY_DETACH_INDEX, httpClient);
return response.data;
};
+
export const addLifecyclePolicyToIndex = async (body, httpClient = getHttpClient()) => {
const response = await httpClient.post(`${apiPrefix}/index/add`, body);
+ // Only track successful actions.
+ trackUserAction(UA_POLICY_ATTACH_INDEX, httpClient);
return response.data;
};
+
export const addLifecyclePolicyToTemplate = async (body, httpClient = getHttpClient()) => {
const response = await httpClient.post(`${apiPrefix}/template`, body);
+ // Only track successful actions.
+ trackUserAction(UA_POLICY_ATTACH_INDEX_TEMPLATE, httpClient);
return response.data;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/services/index.js b/x-pack/plugins/index_lifecycle_management/public/services/index.js
index a82b581309d29..d1160c4af8dbf 100644
--- a/x-pack/plugins/index_lifecycle_management/public/services/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/services/index.js
@@ -6,3 +6,4 @@
export { filterItems } from './filter_items';
export { sortTable } from './sort_table';
+export { trackUserAction, getUserActionsForPhases } from './user_action';
diff --git a/x-pack/plugins/index_lifecycle_management/public/services/user_action.js b/x-pack/plugins/index_lifecycle_management/public/services/user_action.js
new file mode 100644
index 0000000000000..d45b2f1ce4940
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/services/user_action.js
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+import { get } from 'lodash';
+
+import { createUserActionUri } from '../../../../common/user_action';
+
+import {
+ UA_APP_NAME,
+ UA_CONFIG_COLD_PHASE,
+ UA_CONFIG_WARM_PHASE,
+ UA_CONFIG_SET_PRIORITY,
+ UA_CONFIG_FREEZE_INDEX,
+} from '../../common/constants';
+
+import {
+ PHASE_HOT,
+ PHASE_WARM,
+ PHASE_COLD,
+ PHASE_INDEX_PRIORITY,
+} from '../constants';
+
+import {
+ defaultColdPhase,
+ defaultWarmPhase,
+ defaultHotPhase,
+} from '../store/defaults';
+
+import { getHttpClient } from './api';
+
+export function trackUserAction(actionType, httpClient = getHttpClient()) {
+ const userActionUri = createUserActionUri(UA_APP_NAME, actionType);
+ httpClient.post(userActionUri);
+}
+
+export function getUserActionsForPhases(phases) {
+ const possibleUserActions = [{
+ action: UA_CONFIG_COLD_PHASE,
+ isExecuted: () => Boolean(phases[PHASE_COLD]),
+ }, {
+ action: UA_CONFIG_WARM_PHASE,
+ isExecuted: () => Boolean(phases[PHASE_WARM]),
+ }, {
+ action: UA_CONFIG_SET_PRIORITY,
+ isExecuted: () => {
+ const phaseToDefaultIndexPriorityMap = {
+ [PHASE_HOT]: defaultHotPhase[PHASE_INDEX_PRIORITY],
+ [PHASE_WARM]: defaultWarmPhase[PHASE_INDEX_PRIORITY],
+ [PHASE_COLD]: defaultColdPhase[PHASE_INDEX_PRIORITY],
+ };
+
+ // We only care about whether the user has interacted with the priority of *any* phase at all.
+ return [ PHASE_HOT, PHASE_WARM, PHASE_COLD ].some(phase => {
+ // If the priority is different than the default, we'll consider it a user interaction,
+ // even if the user has set it to undefined.
+ return phases[phase] && get(phases[phase], 'actions.set_priority.priority') !== phaseToDefaultIndexPriorityMap[phase];
+ });
+ },
+ }, {
+ action: UA_CONFIG_FREEZE_INDEX,
+ isExecuted: () => phases[PHASE_COLD] && get(phases[PHASE_COLD], 'actions.freeze'),
+ }];
+
+ const executedUserActions = possibleUserActions.reduce((executed, { action, isExecuted }) => {
+ if (isExecuted()) {
+ executed.push(action);
+ }
+ return executed;
+ }, []);
+
+ return executedUserActions;
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js b/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js
new file mode 100644
index 0000000000000..a66a9140d9a67
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/services/user_action.test.js
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+import {
+ UA_CONFIG_COLD_PHASE,
+ UA_CONFIG_WARM_PHASE,
+ UA_CONFIG_SET_PRIORITY,
+ UA_CONFIG_FREEZE_INDEX,
+} from '../../common/constants';
+
+import {
+ defaultColdPhase,
+ defaultWarmPhase,
+} from '../store/defaults';
+
+import {
+ PHASE_INDEX_PRIORITY,
+} from '../constants';
+
+import { getUserActionsForPhases } from './user_action';
+
+describe('getUserActionsForPhases', () => {
+ test('gets cold phase', () => {
+ expect(getUserActionsForPhases({
+ cold: {
+ actions: {
+ set_priority: {
+ priority: defaultColdPhase[PHASE_INDEX_PRIORITY],
+ },
+ },
+ },
+ })).toEqual([UA_CONFIG_COLD_PHASE]);
+ });
+
+ test('gets warm phase', () => {
+ expect(getUserActionsForPhases({
+ warm: {
+ actions: {
+ set_priority: {
+ priority: defaultWarmPhase[PHASE_INDEX_PRIORITY],
+ },
+ },
+ },
+ })).toEqual([UA_CONFIG_WARM_PHASE]);
+ });
+
+ test(`gets index priority if it's different than the default value`, () => {
+ expect(getUserActionsForPhases({
+ warm: {
+ actions: {
+ set_priority: {
+ priority: defaultWarmPhase[PHASE_INDEX_PRIORITY] + 1,
+ },
+ },
+ },
+ })).toEqual([UA_CONFIG_WARM_PHASE, UA_CONFIG_SET_PRIORITY]);
+ });
+
+ test('gets freeze index', () => {
+ expect(getUserActionsForPhases({
+ cold: {
+ actions: {
+ freeze: {},
+ set_priority: {
+ priority: defaultColdPhase[PHASE_INDEX_PRIORITY],
+ },
+ },
+ },
+ })).toEqual([UA_CONFIG_COLD_PHASE, UA_CONFIG_FREEZE_INDEX]);
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
index 9dcd1249de71c..c7de1ba2e4ce4 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
@@ -5,9 +5,15 @@
*/
import { i18n } from '@kbn/i18n';
import { toastNotifications } from 'ui/notify';
+
+import {
+ UA_POLICY_CREATE,
+ UA_POLICY_UPDATE,
+} from '../../../common/constants';
+
import { showApiError } from '../../services/api_errors';
import { saveLifecycle as saveLifecycleApi } from '../../services/api';
-
+import { trackUserAction, getUserActionsForPhases } from '../../services';
export const saveLifecyclePolicy = (lifecycle, isNew) => async () => {
try {
@@ -23,6 +29,11 @@ export const saveLifecyclePolicy = (lifecycle, isNew) => async () => {
showApiError(err, title);
return false;
}
+
+ const userActions = getUserActionsForPhases(lifecycle.phases);
+ userActions.push(isNew ? UA_POLICY_CREATE : UA_POLICY_UPDATE);
+ trackUserAction(userActions.join(','));
+
const message = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.successfulSaveMessage',
{
defaultMessage: '{verb} lifecycle policy "{lifecycleName}"',
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
index a2a526e44298e..bb1f63c61cb23 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
@@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n';
import { createAction } from 'redux-actions';
import { showApiError } from '../../services/api_errors';
import { loadNodes, loadNodeDetails } from '../../services/api';
-import { SET_SELECTED_NODE_ATTRS } from '../constants';
+import { SET_SELECTED_NODE_ATTRS } from '../../constants';
export const setSelectedNodeAttrs = createAction(SET_SELECTED_NODE_ATTRS);
export const setSelectedPrimaryShardCount = createAction(
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
index fb2384855d92c..c089dfa7e7520 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
@@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import { showApiError } from '../../services/api_errors';
import { createAction } from 'redux-actions';
import { loadPolicies } from '../../services/api';
-import { SET_PHASE_DATA } from '../constants';
+import { SET_PHASE_DATA } from '../../constants';
export const fetchedPolicies = createAction('FETCHED_POLICIES');
export const setSelectedPolicy = createAction('SET_SELECTED_POLICY');
export const unsetSelectedPolicy = createAction('UNSET_SELECTED_POLICY');
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js
index 0a4f4e2206d65..0ff523a43867c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js
@@ -12,7 +12,7 @@ import {
PHASE_ROLLOVER_ALIAS,
PHASE_FREEZE_ENABLED,
PHASE_INDEX_PRIORITY,
-} from '../constants';
+} from '../../constants';
export const defaultColdPhase = {
[PHASE_ENABLED]: false,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js
index c449ba073fd24..901ac4f6a4668 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js
@@ -9,7 +9,7 @@ import {
PHASE_ROLLOVER_MINIMUM_AGE,
PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
PHASE_ROLLOVER_ALIAS,
-} from '../constants';
+} from '../../constants';
export const defaultDeletePhase = {
[PHASE_ENABLED]: false,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js
index 43ffc1b565e5b..ba88979435256 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js
@@ -12,7 +12,7 @@ import {
PHASE_ROLLOVER_MAX_DOCUMENTS,
PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
PHASE_INDEX_PRIORITY
-} from '../constants';
+} from '../../constants';
export const defaultHotPhase = {
[PHASE_ENABLED]: true,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js
index 8e55b5c72c4f0..7e6dcd41f4871 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js
@@ -16,7 +16,7 @@ import {
PHASE_SHRINK_ENABLED,
WARM_PHASE_ON_ROLLOVER,
PHASE_INDEX_PRIORITY
-} from '../constants';
+} from '../../constants';
export const defaultWarmPhase = {
[PHASE_ENABLED]: false,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
index 27b5304fec1fa..8fc0bc1b73766 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
@@ -27,7 +27,7 @@ import {
PHASE_COLD,
PHASE_DELETE,
PHASE_ATTRIBUTES_THAT_ARE_NUMBERS,
-} from '../constants';
+} from '../../constants';
import {
defaultColdPhase,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
index a25299d54675a..b89e74781b344 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -25,7 +25,7 @@ import {
WARM_PHASE_ON_ROLLOVER,
PHASE_INDEX_PRIORITY,
PHASE_ROLLOVER_MAX_DOCUMENTS
-} from '../constants';
+} from '../../constants';
import {
getPhase,
getPhases,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index 30649e8a62042..31af91c122019 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -32,7 +32,7 @@ import {
PHASE_FREEZE_ENABLED,
PHASE_INDEX_PRIORITY,
PHASE_ROLLOVER_MAX_DOCUMENTS
-} from '../constants';
+} from '../../constants';
import {
defaultEmptyDeletePhase,
defaultEmptyColdPhase,
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
index 19a7b56759269..394c2c4735c0c 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
index 443744ccb0cc8..f9c102be7a1ff 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapCustomError } from '../wrap_custom_error';
describe('wrap_custom_error', () => {
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
index 394c182140000..467cc4fcdae1f 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapEsError } from '../wrap_es_error';
describe('wrap_es_error', () => {
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
index 6d6a336417bef..85e0b2b3033ad 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapUnknownError } from '../wrap_unknown_error';
describe('wrap_unknown_error', () => {
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
index d50ff9480d3e4..76fdf7b36c3d0 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isEsErrorFactory } from '../is_es_error_factory';
import { set } from 'lodash';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index 359b3fb2ce6f4..24cbaae2b2b67 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
describe('license_pre_routing_factory', () => {
diff --git a/x-pack/plugins/index_lifecycle_management/server/usage/collector.js b/x-pack/plugins/index_lifecycle_management/server/usage/collector.js
new file mode 100644
index 0000000000000..4fb067a2eaa91
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/usage/collector.js
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+import { fetchUserActions } from '../../../../server/lib/user_action';
+import { UA_APP_NAME, USER_ACTIONS } from '../../common/constants';
+
+const INDEX_LIFECYCLE_MANAGEMENT_USAGE_TYPE = 'index_lifecycle_management';
+
+export function registerIndexLifecycleManagementUsageCollector(server) {
+ const collector = server.usage.collectorSet.makeUsageCollector({
+ type: INDEX_LIFECYCLE_MANAGEMENT_USAGE_TYPE,
+ fetch: async () => {
+ const userActions = await fetchUserActions(server, UA_APP_NAME, USER_ACTIONS);
+
+ return {
+ user_actions: userActions,
+ };
+ },
+ });
+
+ server.usage.collectorSet.register(collector);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/usage/index.js b/x-pack/plugins/index_lifecycle_management/server/usage/index.js
new file mode 100644
index 0000000000000..f0fec917cd56e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/usage/index.js
@@ -0,0 +1,7 @@
+/*
+ * 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.
+ */
+
+export { registerIndexLifecycleManagementUsageCollector } from './collector';
diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js
index 9e795c38979e9..fa7f82be5a2d7 100644
--- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js
+++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js
@@ -6,7 +6,7 @@
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
-import { App } from '../../public/app';
+import { AppWithoutRouter } from '../../public/app';
import { Provider } from 'react-redux';
import { loadIndicesSuccess } from '../../public/store/actions';
import { indexManagementStore } from '../../public/store';
@@ -123,7 +123,7 @@ describe('index table', () => {
component = (
-
+
);
diff --git a/x-pack/plugins/index_management/common/constants/user_action.js b/x-pack/plugins/index_management/common/constants/user_action.js
index 9f491e4918c4d..47eda91edfed7 100644
--- a/x-pack/plugins/index_management/common/constants/user_action.js
+++ b/x-pack/plugins/index_management/common/constants/user_action.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export const UA_APP_NAME = 'index-management';
+export const UA_APP_NAME = 'index_management';
export const UA_APP_LOAD = 'app_load';
export const UA_UPDATE_SETTINGS = 'update_settings';
diff --git a/x-pack/plugins/index_management/public/app.js b/x-pack/plugins/index_management/public/app.js
index 5446e20f18523..b7302f4836290 100644
--- a/x-pack/plugins/index_management/public/app.js
+++ b/x-pack/plugins/index_management/public/app.js
@@ -4,26 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component } from 'react';
-import { Switch, Route, Redirect } from 'react-router-dom';
+import React, { useEffect } from 'react';
+import { HashRouter, Switch, Route, Redirect } from 'react-router-dom';
import { BASE_PATH, UA_APP_LOAD } from '../common/constants';
import { IndexList } from './sections/index_list';
import { trackUserAction } from './services';
-export class App extends Component {
- componentWillMount() {
- trackUserAction(UA_APP_LOAD);
- }
+export const App = () => {
+ useEffect(() => trackUserAction(UA_APP_LOAD), []);
- render() {
- return (
-
-
-
-
-
-
-
- );
- }
-}
+ return (
+
+
+
+ );
+};
+
+// Exoprt this so we can test it with a different router.
+export const AppWithoutRouter = () => (
+
+
+
+
+
+);
diff --git a/x-pack/plugins/index_management/public/register_routes.js b/x-pack/plugins/index_management/public/register_routes.js
index a926d64d32743..41787befd5c23 100644
--- a/x-pack/plugins/index_management/public/register_routes.js
+++ b/x-pack/plugins/index_management/public/register_routes.js
@@ -7,7 +7,6 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
-import { HashRouter } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { setHttpClient } from './services/api';
import { setUrlService } from './services/navigation';
@@ -28,9 +27,7 @@ const renderReact = async (elem) => {
render(
-
-
-
+ ,
elem
diff --git a/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
index 69c02e1c7f7d7..b6f2aae12bddf 100644
--- a/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
+++ b/x-pack/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
@@ -36,9 +36,7 @@ export class SuggestionItem extends React.Component {
{suggestion.text}
-
+ {suggestion.description}
);
}
diff --git a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js
index 091e692d0bbd4..aec5ff6da99ce 100644
--- a/x-pack/plugins/infra/scripts/generate_types_from_graphql.js
+++ b/x-pack/plugins/infra/scripts/generate_types_from_graphql.js
@@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
+require('../../../../src/setup_node_env');
+
const { join, resolve } = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
const { generate } = require('graphql-code-generator');
@@ -28,7 +30,6 @@ async function main() {
config: SERVER_CONFIG_PATH,
out: OUTPUT_INTROSPECTION_PATH,
overwrite: true,
- require: ['ts-node/register'],
schema: SCHEMA_PATH,
template: 'graphql-codegen-introspection-template',
},
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js
index 496d15f6b32a9..17518ffa488c0 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/conjunction.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getSuggestionsProvider } from '../conjunction';
describe('Kuery conjunction suggestions', function () {
@@ -35,13 +35,14 @@ describe('Kuery conjunction suggestions', function () {
expect(suggestions.map(suggestion => suggestion.start)).to.eql([end, end]);
expect(suggestions.map(suggestion => suggestion.end)).to.eql([end, end]);
});
-
it('should have descriptions', function () {
const text = ' ';
const suggestions = getSuggestions({ text });
- expect(suggestions.length).to.be(2);
+ expect(typeof suggestions).to.be('object');
+ expect(Object.keys(suggestions).length).to.be(2);
suggestions.forEach(suggestion => {
- expect(suggestion.description.length).to.be.greaterThan(0);
+ expect(typeof suggestion).to.be('object');
+ expect(suggestion).to.have.property('description');
});
});
});
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js
index 9ec2086f8c599..ae43f5d7f8ca1 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/escape_kuery.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { escapeQuotes, escapeKuery } from '../escape_kuery';
describe('Kuery escape', function () {
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
index 6535886d372c3..de908491eee6a 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/field.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getSuggestionsProvider } from '../field';
import indexPatternResponse from '../__fixtures__/index_pattern_response.json';
import { isFilterable } from 'ui/index_patterns/static_utils';
@@ -77,7 +77,7 @@ describe('Kuery field suggestions', function () {
const suggestions = getSuggestions({ prefix, suffix });
expect(suggestions.length).to.be.greaterThan(0);
suggestions.forEach(suggestion => {
- expect(suggestion.description.length).to.be.greaterThan(0);
+ expect(suggestion).to.have.property('description');
});
});
});
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
index a9bc8e988aac5..57d38ddab5c3d 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/operator.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getSuggestionsProvider } from '../operator';
import indexPatternResponse from '../__fixtures__/index_pattern_response.json';
@@ -53,7 +53,7 @@ describe('Kuery operator suggestions', function () {
const suggestions = getSuggestions({ fieldName });
expect(suggestions.length).to.be.greaterThan(0);
suggestions.forEach(suggestion => {
- expect(suggestion.description.length).to.be.greaterThan(0);
+ expect(suggestion).to.have.property('description');
});
});
});
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js
index e7120ca428acb..d2cce4fe59282 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/__tests__/value.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import fetchMock from 'fetch-mock';
import { getSuggestionsProvider } from '../value';
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js
index eab4ba014ff6a..8ea90ae89d25e 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/conjunction.js
@@ -3,37 +3,48 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
-import { i18n } from '@kbn/i18n';
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
const type = 'conjunction';
-const bothArgumentsText = i18n.translate('xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText', {
- defaultMessage: 'both arguments',
- description: 'Part of xpack.kueryAutocomplete.andOperatorDescription. Full text: "Requires both arguments to be true"'
-});
-const oneOrMoreArgumentsText = i18n.translate('xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText', {
- defaultMessage: 'one or more arguments',
- description: 'Part of xpack.kueryAutocomplete.orOperatorDescription. Full text: "Requires one or more arguments to be true"'
-});
+const bothArgumentsText =
+ ();
+
+const oneOrMoreArgumentsText =
+ ();
const conjunctions = {
- and: '
' +
- i18n.translate('xpack.kueryAutocomplete.andOperatorDescription', {
- defaultMessage: 'Requires {bothArguments} to be true',
- values: { bothArguments: `${bothArgumentsText}` },
- description: 'Full text: "Requires both arguments to be true". See ' +
- 'xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText for "both arguments" part.'
- }) +
- '
',
- or: '
' +
- i18n.translate('xpack.kueryAutocomplete.orOperatorDescription', {
- defaultMessage: 'Requires {oneOrMoreArguments} to be true',
- values: { oneOrMoreArguments: `${oneOrMoreArgumentsText}` },
- description: 'Full text: "Requires one or more arguments to be true". See ' +
- 'xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText for "one or more arguments" part.'
- }) +
- '
'
+ and: (
+
+ {bothArgumentsText} }}
+ description="Full text: ' Requires both arguments to be true'. See
+ 'xpack.kueryAutocomplete.andOperatorDescription.bothArgumentsText' for 'both arguments' part."
+ />
+
+ ),
+ or: (
+
+ {oneOrMoreArgumentsText} }}
+ description="Full text: 'Requires one or more arguments to be true'. See
+ 'xpack.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText' for 'one or more arguments' part."
+ />
+
+ )
};
function getDescription(conjunction) {
diff --git a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
index a9266d44bf7d2..60c4e5ffc4121 100644
--- a/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
+++ b/x-pack/plugins/kuery_autocomplete/public/autocomplete_providers/field.js
@@ -3,23 +3,26 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
-import { escape, flatten } from 'lodash';
+import React from 'react';
+import { flatten } from 'lodash';
import { escapeKuery } from './escape_kuery';
import { sortPrefixFirst } from 'ui/utils/sort_prefix_first';
import { isFilterable } from 'ui/index_patterns/static_utils';
-import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
const type = 'field';
function getDescription(fieldName) {
- return '
+
+
+ {this._renderQuery()}
+
+ {this._renderQueryPopover()}
+
+ );
+ }
+}
diff --git a/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js
new file mode 100644
index 0000000000000..ceedf7661f69a
--- /dev/null
+++ b/x-pack/plugins/maps/public/components/layer_panel/filter_editor/index.js
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+import { connect } from 'react-redux';
+import { FilterEditor } from './filter_editor';
+import { getSelectedLayer } from '../../../selectors/map_selectors';
+import { setLayerQuery } from '../../../actions/store_actions';
+
+function mapStateToProps(state = {}) {
+ return {
+ layer: getSelectedLayer(state),
+ };
+}
+
+function mapDispatchToProps(dispatch) {
+ return {
+ setLayerQuery: (layerId, query) => {
+ dispatch(setLayerQuery(layerId, query));
+ }
+ };
+}
+
+const connectedFilterEditor = connect(mapStateToProps, mapDispatchToProps)(FilterEditor);
+export { connectedFilterEditor as FilterEditor };
diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/__snapshots__/layer_errors.test.js.snap b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/__snapshots__/layer_errors.test.js.snap
new file mode 100644
index 0000000000000..d8288ddb57bc7
--- /dev/null
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/__snapshots__/layer_errors.test.js.snap
@@ -0,0 +1,22 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Should render errors when layer has errors 1`] = `
+
+
+
+ simulated layer error
+
+
+
+
+`;
+
+exports[`should render nothing when layer has no errors 1`] = `""`;
diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js
new file mode 100644
index 0000000000000..21ff81e32f607
--- /dev/null
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/index.js
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+import { connect } from 'react-redux';
+import { LayerErrors } from './layer_errors';
+import { getSelectedLayer } from '../../../selectors/map_selectors';
+
+function mapStateToProps(state = {}) {
+ return {
+ layer: getSelectedLayer(state)
+ };
+}
+
+const connectedLayerErrors = connect(mapStateToProps, null)(LayerErrors);
+export { connectedLayerErrors as LayerErrors };
diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js
new file mode 100644
index 0000000000000..755a1ed39ff8d
--- /dev/null
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.js
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+import React, { Fragment } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiCallOut,
+ EuiSpacer,
+} from '@elastic/eui';
+
+export function LayerErrors({ layer }) {
+
+ if (!layer.hasErrors()) {
+ return null;
+ }
+
+ return (
+
+
+
+ {layer.getErrors()}
+
+
+
+
+ );
+}
diff --git a/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js
new file mode 100644
index 0000000000000..fd2b8540bee16
--- /dev/null
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_errors/layer_errors.test.js
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import { LayerErrors } from './layer_errors';
+
+test('Should render errors when layer has errors', () => {
+ const mockLayer = {
+ hasErrors: () => { return true; },
+ getErrors: () => { return 'simulated layer error'; }
+ };
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+});
+
+test('should render nothing when layer has no errors', () => {
+ const mockLayer = {
+ hasErrors: () => { return false; },
+ };
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+});
diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/_settings_panel.scss b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/_layer_settings.scss
similarity index 100%
rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/_settings_panel.scss
rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/_layer_settings.scss
diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js
similarity index 79%
rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js
rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js
index b82e2e0e62a27..e0a1275155211 100644
--- a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/index.js
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/index.js
@@ -5,14 +5,13 @@
*/
import { connect } from 'react-redux';
-import { SettingsPanel } from './settings_panel';
+import { LayerSettings } from './layer_settings';
import { getSelectedLayer } from '../../../selectors/map_selectors';
import {
updateLayerLabel,
updateLayerMaxZoom,
updateLayerMinZoom,
updateLayerAlpha,
- updateSourceProp,
} from '../../../actions/store_actions';
function mapStateToProps(state = {}) {
@@ -33,9 +32,8 @@ function mapDispatchToProps(dispatch) {
updateMinZoom: (id, minZoom) => dispatch(updateLayerMinZoom(id, minZoom)),
updateMaxZoom: (id, maxZoom) => dispatch(updateLayerMaxZoom(id, maxZoom)),
updateAlpha: (id, alpha) => dispatch(updateLayerAlpha(id, alpha)),
- updateSourceProp: (id, propName, value) => dispatch(updateSourceProp(id, propName, value)),
};
}
-const connectedSettingsPanel = connect(mapStateToProps, mapDispatchToProps)(SettingsPanel);
-export { connectedSettingsPanel as SettingsPanel };
+const connectedLayerSettings = connect(mapStateToProps, mapDispatchToProps)(LayerSettings);
+export { connectedLayerSettings as LayerSettings };
diff --git a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js
similarity index 78%
rename from x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js
rename to x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js
index 61563f4375af0..0a01498986e90 100644
--- a/x-pack/plugins/maps/public/components/layer_panel/settings_panel/settings_panel.js
+++ b/x-pack/plugins/maps/public/components/layer_panel/layer_settings/layer_settings.js
@@ -14,7 +14,6 @@ import {
EuiFormRow,
EuiFieldText,
EuiSpacer,
- EuiCallOut
} from '@elastic/eui';
import { ValidatedRange } from '../../../shared/components/validated_range';
@@ -25,7 +24,7 @@ import { ValidatedDualRange } from 'ui/validated_range';
const MIN_ZOOM = 0;
const MAX_ZOOM = 24;
-export function SettingsPanel(props) {
+export function LayerSettings(props) {
const onLabelChange = (event) => {
const label = event.target.value;
@@ -41,34 +40,6 @@ export function SettingsPanel(props) {
props.updateAlpha(props.layerId, alpha);
};
- const onSourceChange = ({ propName, value }) => {
- props.updateSourceProp(props.layerId, propName, value);
- };
-
- const renderLayerErrors = () => {
- if (!props.layer.hasErrors()) {
- return null;
- }
-
- return (
-
-
-
diff --git a/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js
index 582d9bac39d72..4e85bae4b1862 100644
--- a/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js
+++ b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { abbreviateWholeNumber } from '../abbreviate_whole_number';
describe('ML - abbreviateWholeNumber formatter', () => {
diff --git a/x-pack/plugins/ml/public/formatters/__tests__/format_value.js b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js
index 69362e76ceced..ffdbdd915d3a8 100644
--- a/x-pack/plugins/ml/public/formatters/__tests__/format_value.js
+++ b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment-timezone';
import { formatValue } from '../format_value';
diff --git a/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js
index 9c4b1516915aa..45864ce58bf83 100644
--- a/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js
+++ b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getMetricChangeDescription } from '../metric_change_description';
diff --git a/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js b/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js
index 389c53300b364..b7e63846c530f 100644
--- a/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js
+++ b/x-pack/plugins/ml/public/formatters/__tests__/round_to_decimal_place.js
@@ -5,7 +5,7 @@
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { roundToDecimalPlace } from '../round_to_decimal_place';
describe('ML - roundToDecimalPlace formatter', () => {
diff --git a/x-pack/plugins/ml/public/index.scss b/x-pack/plugins/ml/public/index.scss
index c31c1c2804c96..5d2c4628b6357 100644
--- a/x-pack/plugins/ml/public/index.scss
+++ b/x-pack/plugins/ml/public/index.scss
@@ -31,6 +31,7 @@
@import 'components/controls/index';
@import 'components/data_recognizer/index';
@import 'components/documentation_help_link/index';
+ @import 'components/entity_cell/index';
@import 'components/field_data_card/index'; // SASSTODO: This file needs to be rewritten
@import 'components/field_title_bar/index';
@import 'components/field_type_icon/index';
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js
index 704f1466b405a..2061066ca3dfd 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/__tests__/new_job_controller.js
@@ -6,7 +6,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('ML - Advanced Job Wizard - New Job Controller', () => {
beforeEach(() => {
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js
index 8e7e31ac5afda..e712cad932005 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_filter_modal/__tests__/detector_filter_modal_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
const mockModalInstance = { close: function () {}, dismiss: function () {} };
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js
index 235a8ba321d4c..002050e0413f6 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/detector_modal/__tests__/detector_modal_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
const mockModalInstance = { close: function () {}, dismiss: function () {} };
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js
index b3bc9fe1747f2..865b511857fff 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js
@@ -10,6 +10,7 @@ import _ from 'lodash';
import angular from 'angular';
import 'ace';
import 'ui/angular_ui_select';
+import 'ui/directives/input_focus';
import { parseInterval } from 'ui/utils/parse_interval';
import { timefilter } from 'ui/timefilter';
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js
index 97411067f41e1..a86202f546c63 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/save_status_modal/__tests__/save_status_modal_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
const mockModalInstance = { close: function () { }, dismiss: function () { } };
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js
index 448d1bfa600dd..12ed469ab6104 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/__tests__/create_job_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
// Import this way to be able to stub/mock functions later on in the tests using sinon.
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js
index 430be2c927376..de0d4860184e6 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/__tests__/create_job_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
// Import this way to be able to stub/mock functions later on in the tests using sinon.
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js
index 2ea1913461ca7..06c6b90323cf0 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/__tests__/create_job_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('ML - Recognize Wizard - Create Job Controller', () => {
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js
index 9522115367116..6ab0b02c6aced 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js
@@ -25,6 +25,7 @@ import { CreateRecognizerJobsServiceProvider } from './create_job_service';
import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service';
import { ml } from 'plugins/ml/services/ml_api_service';
import template from './create_job.html';
+import { toastNotifications } from 'ui/notify';
import { timefilter } from 'ui/timefilter';
uiRoutes
@@ -358,6 +359,23 @@ module
});
}
resolve();
+ })
+ .catch((err) => {
+ console.log('Error setting up module', err);
+ toastNotifications.addWarning({
+ title: i18n('xpack.ml.newJob.simple.recognize.moduleSetupFailedWarningTitle', {
+ defaultMessage: 'Error setting up module {moduleId}',
+ values: { moduleId }
+ }),
+ text: i18n('xpack.ml.newJob.simple.recognize.moduleSetupFailedWarningDescription', {
+ defaultMessage: 'An error occurred trying to create the {count, plural, one {job} other {jobs}} in the module.',
+ values: {
+ count: $scope.formConfig.jobs.length
+ }
+ })
+ });
+ $scope.overallState = SAVE_STATE.FAILED;
+ $scope.$applyAsync();
});
});
}
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js
index ea7622a08af2c..930f6756eb069 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/__tests__/create_job_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
// Import this way to be able to stub/mock functions later on in the tests using sinon.
diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js
index d06a045b61479..6e277d24908f9 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/__tests__/index_or_search_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('ML - Index Or Search Controller', () => {
beforeEach(() => {
diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
index 33cdfd0c38640..e7a8e77123526 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js
@@ -20,6 +20,8 @@ import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
import template from './index_or_search.html';
import { timefilter } from 'ui/timefilter';
+import 'ui/directives/paginated_selectable_list';
+import 'ui/directives/saved_object_finder';
uiRoutes
.when('/jobs/new_job', {
diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js
index 33500fd199512..f8fd13b2ae36e 100644
--- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js
+++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/__tests__/job_type_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
// Import this way to be able to stub/mock functions later on in the tests using sinon.
diff --git a/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js b/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js
index 57448ead2f679..a13b151c26557 100644
--- a/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js
+++ b/x-pack/plugins/ml/public/lib/angular_bootstrap_patch.js
@@ -1,4 +1,4 @@
-/* eslint-disable @kbn/license-header/require-license-header */
+/* eslint-disable @kbn/eslint/require-license-header */
/**
* @notice
diff --git a/x-pack/plugins/ml/public/license/__tests__/check_license.js b/x-pack/plugins/ml/public/license/__tests__/check_license.js
index 92dd5d27db61e..b65b5fa246d92 100644
--- a/x-pack/plugins/ml/public/license/__tests__/check_license.js
+++ b/x-pack/plugins/ml/public/license/__tests__/check_license.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
xpackFeatureProvider,
} from '../check_license';
diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js
index 19e68e6cbcca9..9ee71c676c6c6 100644
--- a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js
+++ b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseries_chart_directive.js
@@ -5,7 +5,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { TimeseriesChart } from '../components/timeseries_chart/timeseries_chart';
diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js
index 6c3bb0a9a3252..42510c5a30fd1 100644
--- a/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js
+++ b/x-pack/plugins/ml/public/timeseriesexplorer/__tests__/timeseriesexplorer_controller.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('ML - Time Series Explorer Controller', () => {
beforeEach(() => {
diff --git a/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js b/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js
index 2b0224ff112bd..3653d23464b64 100644
--- a/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js
+++ b/x-pack/plugins/ml/public/util/__tests__/app_state_utils.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import ngMock from 'ng_mock';
import { BehaviorSubject } from 'rxjs';
diff --git a/x-pack/plugins/ml/public/util/__tests__/chart_utils.js b/x-pack/plugins/ml/public/util/__tests__/chart_utils.js
index 979615f2778be..0949605e9599d 100644
--- a/x-pack/plugins/ml/public/util/__tests__/chart_utils.js
+++ b/x-pack/plugins/ml/public/util/__tests__/chart_utils.js
@@ -8,7 +8,7 @@
import $ from 'jquery';
import d3 from 'd3';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
chartLimits,
filterAxisLabels,
diff --git a/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js b/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js
index 9d7537ec23157..2081fbcb81380 100644
--- a/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js
+++ b/x-pack/plugins/ml/public/util/__tests__/custom_url_utils.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
replaceTokensInUrlValue,
getUrlForRecord,
diff --git a/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js b/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js
index 80426d1005aa2..c04545be05b35 100644
--- a/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js
+++ b/x-pack/plugins/ml/public/util/__tests__/field_types_utils.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { ML_JOB_FIELD_TYPES, KBN_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types';
import { kbnTypeToMLJobType } from 'plugins/ml/util/field_types_utils';
diff --git a/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js b/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js
index 57069994ef91c..c0ac9487a1ff0 100644
--- a/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js
+++ b/x-pack/plugins/ml/public/util/__tests__/ml_time_buckets.js
@@ -7,7 +7,7 @@
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import {
IntervalHelperProvider,
diff --git a/x-pack/plugins/ml/public/util/__tests__/string_utils.js b/x-pack/plugins/ml/public/util/__tests__/string_utils.js
index e8d4d5645d183..bdf467a9399a4 100644
--- a/x-pack/plugins/ml/public/util/__tests__/string_utils.js
+++ b/x-pack/plugins/ml/public/util/__tests__/string_utils.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
replaceStringTokens,
detectorToString,
diff --git a/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js b/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js
index dd2ade261f0bf..87ab4573c509d 100644
--- a/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js
+++ b/x-pack/plugins/ml/server/client/__tests__/elasticsearch_ml.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
elasticsearchJsPlugin
} from '../elasticsearch_ml';
diff --git a/x-pack/plugins/ml/server/lib/__tests__/query_utils.js b/x-pack/plugins/ml/server/lib/__tests__/query_utils.js
index 1a936bdf96558..671bbf1a94875 100644
--- a/x-pack/plugins/ml/server/lib/__tests__/query_utils.js
+++ b/x-pack/plugins/ml/server/lib/__tests__/query_utils.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
buildBaseFilterCriteria,
buildSamplerAggregation,
diff --git a/x-pack/plugins/ml/server/lib/__tests__/security_utils.js b/x-pack/plugins/ml/server/lib/__tests__/security_utils.js
index fbcd3ee281a4b..073b6c3c50b85 100644
--- a/x-pack/plugins/ml/server/lib/__tests__/security_utils.js
+++ b/x-pack/plugins/ml/server/lib/__tests__/security_utils.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
isSecurityDisabled
} from '../security_utils';
diff --git a/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js
index 8ed3158e9b640..f65b9c98be8e3 100644
--- a/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js
+++ b/x-pack/plugins/ml/server/lib/check_license/__tests__/check_license.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { set } from 'lodash';
import { checkLicense, isBasicLicense } from '../check_license';
diff --git a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts
index 2193e26a7e1fb..9a0c3608a893c 100644
--- a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts
+++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.test.ts
@@ -120,9 +120,7 @@ describe('ml_telemetry', () => {
}
return {
attributes: {
- telemetry: {
- enabled: telemetryEnabled,
- },
+ enabled: telemetryEnabled,
},
};
case 'ml-telemetry':
diff --git a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts
index 2ff2ae1ed8738..fef0bb2e7617c 100644
--- a/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts
+++ b/x-pack/plugins/ml/server/lib/ml_telemetry/ml_telemetry.ts
@@ -47,7 +47,7 @@ export async function incrementFileDataVisualizerIndexCreationCount(server: Serv
try {
const { attributes } = await savedObjectsClient.get('telemetry', 'telemetry');
- if (attributes.telemetry.enabled === false) {
+ if (attributes.enabled === false) {
return;
}
} catch (error) {
diff --git a/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js b/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js
index 06a937ed68acc..7b52ed9000e54 100644
--- a/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js
+++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/__tests__/bucket_span_estimator.js
@@ -7,7 +7,7 @@
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { estimateBucketSpanFactory } from '../bucket_span_estimator';
// Mock callWithRequest with the ability to simulate returning different
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js
index 817176cb78795..158bfd4a86943 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js
+++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js
@@ -63,15 +63,24 @@ export class DataRecognizer {
const configs = [];
const dirs = await this.listDirs(this.modulesDir);
await Promise.all(dirs.map(async (dir) => {
- const file = await this.readFile(`${this.modulesDir}/${dir}/manifest.json`);
+ let file;
try {
- configs.push({
- dirName: dir,
- json: JSON.parse(file)
- });
+ file = await this.readFile(`${this.modulesDir}/${dir}/manifest.json`);
} catch (error) {
- mlLog('warning', `Error parsing ${dir}/manifest.json`);
+ mlLog('warning', `Data recognizer skipping folder ${dir} as manifest.json cannot be read`);
}
+
+ if (file !== undefined) {
+ try {
+ configs.push({
+ dirName: dir,
+ json: JSON.parse(file)
+ });
+ } catch (error) {
+ mlLog('warning', `Data recognizer error parsing ${dir}/manifest.json. ${error}`);
+ }
+ }
+
}));
return configs;
@@ -90,8 +99,14 @@ export class DataRecognizer {
await Promise.all(manifestFiles.map(async (i) => {
const moduleConfig = i.json;
- const match = await this.searchForFields(moduleConfig, indexPattern);
- if (match) {
+ let match = false;
+ try {
+ match = await this.searchForFields(moduleConfig, indexPattern);
+ } catch (error) {
+ mlLog('warning', `Data recognizer error running query defined for module ${moduleConfig.id}. ${error}`);
+ }
+
+ if (match === true) {
let logo = null;
if (moduleConfig.logoFile) {
try {
@@ -131,6 +146,7 @@ export class DataRecognizer {
size,
body
});
+
return (resp.hits.total !== 0);
}
@@ -155,25 +171,33 @@ export class DataRecognizer {
const kibana = {};
// load all of the job configs
await Promise.all(manifestJSON.jobs.map(async (job) => {
- const jobConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${job.file}`);
- // use the file name for the id
- jobs.push({
- id: `${prefix}${job.id}`,
- config: JSON.parse(jobConfig)
- });
+ try {
+ const jobConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${job.file}`);
+ // use the file name for the id
+ jobs.push({
+ id: `${prefix}${job.id}`,
+ config: JSON.parse(jobConfig)
+ });
+ } catch (error) {
+ mlLog('warning', `Data recognizer error loading config for job ${job.id} for module ${id}. ${error}`);
+ }
}));
// load all of the datafeed configs
await Promise.all(manifestJSON.datafeeds.map(async (datafeed) => {
- const datafeedConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${datafeed.file}`);
- const config = JSON.parse(datafeedConfig);
- // use the job id from the manifestFile
- config.job_id = `${prefix}${datafeed.job_id}`;
-
- datafeeds.push({
- id: prefixDatafeedId(datafeed.id, prefix),
- config
- });
+ try {
+ const datafeedConfig = await this.readFile(`${this.modulesDir}/${dirName}/${ML_DIR}/${datafeed.file}`);
+ const config = JSON.parse(datafeedConfig);
+ // use the job id from the manifestFile
+ config.job_id = `${prefix}${datafeed.job_id}`;
+
+ datafeeds.push({
+ id: prefixDatafeedId(datafeed.id, prefix),
+ config
+ });
+ } catch (error) {
+ mlLog('warning', `Data recognizer error loading config for datafeed ${datafeed.id} for module ${id}. ${error}`);
+ }
}));
// load all of the kibana saved objects
@@ -182,15 +206,19 @@ export class DataRecognizer {
await Promise.all(kKeys.map(async (key) => {
kibana[key] = [];
await Promise.all(manifestJSON.kibana[key].map(async (obj) => {
- const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`);
- // use the file name for the id
- const kId = obj.file.replace('.json', '');
- const config = JSON.parse(kConfig);
- kibana[key].push({
- id: kId,
- title: config.title,
- config
- });
+ try {
+ const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`);
+ // use the file name for the id
+ const kId = obj.file.replace('.json', '');
+ const config = JSON.parse(kConfig);
+ kibana[key].push({
+ id: kId,
+ title: config.title,
+ config
+ });
+ } catch (error) {
+ mlLog('warning', `Data recognizer error loading config for ${key} ${obj.id} for module ${id}. ${error}`);
+ }
}));
}));
}
@@ -218,6 +246,7 @@ export class DataRecognizer {
end,
request
) {
+
this.savedObjectsClient = request.getSavedObjectsClient();
this.indexPatterns = await this.loadIndexPatterns();
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json
index 9ae180c42068e..f6c230a6792fb 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json
@@ -23,5 +23,8 @@
},
"model_plot_config": {
"enabled": true
+ },
+ "custom_settings": {
+ "created_by": "ml-module-apm-transaction"
}
}
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
index b0df941c416b8..d8c970e179416 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_high_count_process_events_ecs.json
@@ -25,6 +25,7 @@
"time_format": "epoch_ms"
},
"custom_settings": {
+ "created_by": "ml-module-auditbeat-process-docker",
"custom_urls": [
{
"url_name": "Process rate",
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
index f04fc11716642..76e3c8026c631 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/ml/docker_rare_process_activity_ecs.json
@@ -25,6 +25,7 @@
"time_format": "epoch_ms"
},
"custom_settings": {
+ "created_by": "ml-module-auditbeat-process-docker",
"custom_urls": [
{
"url_name": "Process explorer",
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
index 9ddfe9aa66b89..487bee5311878 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_high_count_process_events_ecs.json
@@ -24,7 +24,7 @@
"time_format": "epoch_ms"
},
"custom_settings": {
- "created_by": "ml-module-auditd-hosts",
+ "created_by": "ml-module-auditbeat-process-hosts",
"custom_urls": [
{
"url_name": "Process rate",
diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
index 4c1549cc10ab0..9ba6859bfa166 100644
--- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
+++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/ml/hosts_rare_process_activity_ecs.json
@@ -25,7 +25,7 @@
"time_format": "epoch_ms"
},
"custom_settings": {
- "created_by": "ml-module-auditd-hosts",
+ "created_by": "ml-module-auditbeat-process-hosts",
"custom_urls": [
{
"url_name": "Process explorer",
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js
index 70f338f719270..6747743676f7d 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { validateJob } from '../job_validation';
// mock callWithRequest
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js
index 7253f393b2cd9..30bced32688fb 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_bucket_span.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { validateBucketSpan } from '../validate_bucket_span';
import { SKIP_BUCKET_SPAN_ESTIMATION } from '../../../../common/constants/validation';
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js
index aa48d9f8df4ec..876b4542f688c 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_cardinality.js
@@ -7,7 +7,7 @@
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { validateCardinality } from '../validate_cardinality';
import mockFareQuoteCardinality from './mock_farequote_cardinality';
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js
index 4d4b4e0ebeed9..38a1c5731b3bb 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_influencers.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { validateInfluencers } from '../validate_influencers';
describe('ML - validateInfluencers', () => {
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js
index da65d5928d81d..2184445481eb1 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js
@@ -6,7 +6,7 @@
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { validateModelMemoryLimit } from '../validate_model_memory_limit';
describe('ML - validateModelMemoryLimit', () => {
diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js
index f8a4bb2c9da06..17297d6c863be 100644
--- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js
+++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_time_range.js
@@ -7,7 +7,7 @@
import _ from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isValidTimeField, validateTimeRange } from '../validate_time_range';
import mockTimeField from './mock_time_field';
diff --git a/x-pack/plugins/monitoring/README.md b/x-pack/plugins/monitoring/README.md
index a161fb0180a10..3659f4d2fa0f7 100644
--- a/x-pack/plugins/monitoring/README.md
+++ b/x-pack/plugins/monitoring/README.md
@@ -32,7 +32,7 @@ Drawer.
Add a `debugger` line to create a breakpoint, and then:
```
- gulp sync && mocha debug --compilers js:babel-register /pathto/kibana/plugins/monitoring/pathto/__tests__/testfile.js
+ gulp sync && mocha debug --compilers js:@babel/register /pathto/kibana/plugins/monitoring/pathto/__tests__/testfile.js
```
## Multicluster Setup for Development
diff --git a/x-pack/plugins/monitoring/__tests__/deprecations.js b/x-pack/plugins/monitoring/__tests__/deprecations.js
index 2bc46bbe99742..9e444651d4cb8 100644
--- a/x-pack/plugins/monitoring/__tests__/deprecations.js
+++ b/x-pack/plugins/monitoring/__tests__/deprecations.js
@@ -5,7 +5,7 @@
*/
import { noop } from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { deprecations as deprecationsModule } from '../deprecations';
import sinon from 'sinon';
diff --git a/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js b/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js
index 1ff2f1b7a7e72..6a44693418091 100644
--- a/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js
+++ b/x-pack/plugins/monitoring/common/__tests__/format_timestamp_to_duration.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import { formatTimestampToDuration } from '../format_timestamp_to_duration';
import { CALCULATE_DURATION_SINCE, CALCULATE_DURATION_UNTIL } from '../constants';
diff --git a/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js b/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js
index 13734f1d96f2b..c2f1ef703846c 100644
--- a/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js
+++ b/x-pack/plugins/monitoring/public/components/alerts/__tests__/map_severity.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { mapSeverity } from '../map_severity';
describe('mapSeverity', () => {
diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js
index 900c19ec8f76d..7b70f1d1fb224 100644
--- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js
+++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_color.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getColor } from '../get_color';
describe('getColors', function () {
diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js
index 7f81cc3c0e8b6..97f77882631cf 100644
--- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js
+++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_last_value.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getLastValue } from '../get_last_value';
describe('monitoringChartGetLastValue', function () {
diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js
index e981924060a79..20c1c1303d157 100644
--- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js
+++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_title.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getTitle } from '../get_title';
describe('getTitle', function () {
diff --git a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js
index 0f2e566212086..1338d40470ed4 100644
--- a/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js
+++ b/x-pack/plugins/monitoring/public/components/chart/__tests__/get_values_for_legend.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { findIndexByX, getValuesByX, getValuesForSeriesIndex } from '../get_values_for_legend';
diff --git a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js
index 911df086c4d33..1b39341a5f7cb 100644
--- a/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js
+++ b/x-pack/plugins/monitoring/public/components/cluster/listing/listing.js
@@ -292,7 +292,7 @@ const handleClickIncompatibleLicense = (scope, clusterName) => {
defaultMessage="Need to monitor multiple clusters? {getLicenseInfoLink} to enjoy multi-cluster monitoring."
values={{
getLicenseInfoLink: (
-
+ {
),
getLicenseInfoLink: (
-
+
+
+ 0
+
+
+`;
+
+exports[`Shard should show for assigned replica shards 1`] = `
+
+
+ 0
+
+
+`;
+
+exports[`Shard should show for initializing shards 1`] = `
+
+
+ 0
+
+
+`;
+
+exports[`Shard should show for relocating shards 1`] = `
+
+
+ 0
+
+
+`;
+
+exports[`Shard should show unassigned primary shards 1`] = `
+
+
+ 0
+
+
+`;
+
+exports[`Shard should show unassigned replica shards 1`] = `
+
+
+ 0
+
+
+`;
diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js
index b5033e625ba60..7e1b240d5717b 100644
--- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js
+++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js
@@ -13,25 +13,34 @@ import { i18n } from '@kbn/i18n';
import { EuiToolTip, EuiBadge } from '@elastic/eui';
function getColor(classes) {
- return classes.split(' ').reduce((color, cls) => {
- if (color) {
- return color;
- }
+ const classList = classes.split(' ');
+
+ if (classList.includes('emergency')) {
+ return 'danger';
+ }
- switch (cls) {
- case 'primary':
- return 'hollow';
- case 'replica':
- return 'secondary';
- case 'relocation':
- return 'accent';
- case 'initializing':
- return 'default';
- case 'emergency':
- case 'unassigned':
- return 'danger';
+ if (classList.includes('unassigned')) {
+ if (classList.includes('replica')) {
+ return 'warning';
}
- }, null);
+ return 'danger';
+ }
+
+ if (classList.includes('relocating')) {
+ return 'accent';
+ }
+
+ if (classList.includes('initializing')) {
+ return 'default';
+ }
+
+ if (classList.includes('primary')) {
+ return 'primary';
+ }
+
+ if (classList.includes('replica')) {
+ return 'secondary';
+ }
}
export class Shard extends React.Component {
diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js
new file mode 100644
index 0000000000000..4239b1846b8f8
--- /dev/null
+++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.test.js
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { Shard } from './shard';
+
+describe('Shard', () => {
+ it('should show unassigned primary shards', () => {
+ const props = {
+ shard: {
+ state: 'UNASSIGNED',
+ primary: true,
+ shard: 0,
+ tooltip_message: 'Unassigned',
+ type: 'shard',
+ master: true
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should show unassigned replica shards', () => {
+ const props = {
+ shard: {
+ state: 'UNASSIGNED',
+ primary: false,
+ shard: 0,
+ tooltip_message: 'Unassigned',
+ type: 'shard',
+ master: false
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should show for assigned primary shards', () => {
+ const props = {
+ shard: {
+ state: 'STARTED',
+ primary: true,
+ shard: 0,
+ tooltip_message: 'Started',
+ type: 'shard',
+ master: true
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should show for assigned replica shards', () => {
+ const props = {
+ shard: {
+ state: 'STARTED',
+ primary: false,
+ shard: 0,
+ tooltip_message: 'Started',
+ type: 'shard',
+ master: true
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should show for relocating shards', () => {
+ const props = {
+ shard: {
+ state: 'RELOCATING',
+ primary: true,
+ shard: 0,
+ tooltip_message: 'Relocating',
+ type: 'shard',
+ master: true
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should show for initializing shards', () => {
+ const props = {
+ shard: {
+ state: 'INITIALIZING',
+ primary: true,
+ shard: 0,
+ tooltip_message: 'Initializing',
+ type: 'shard',
+ master: true
+ }
+ };
+
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js
index 887e7fd678fdc..82814428a8006 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/config.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { Config } from '../config';
import { Graph } from '../graph';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js
index 1a734debc21ec..ae0c88da39cd7 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/__tests__/pipeline_state.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { PipelineState } from '../pipeline_state';
import { Config } from '../config';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js
index a1abcf6385f7e..3d1979c42ef82 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/boolean_edge.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { BooleanEdge } from '../boolean_edge';
import { Edge } from '../edge';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js
index 00105ce32703d..db8f2446a8c4a 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Edge } from '../edge';
describe('Edge', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js
index cb9b831f4e351..e206d080d358c 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/edge_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { edgeFactory } from '../edge_factory';
import { Edge } from '../edge';
import { BooleanEdge } from '../boolean_edge';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js
index 4b98217e1817d..cc4bb419f0f2b 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/if_vertex.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { IfVertex } from '../if_vertex';
import { Vertex } from '../vertex';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js
index 4844ef90d1c60..0c0a014efdc93 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/index.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Graph } from '../';
import { Vertex } from '../vertex';
import { PluginVertex } from '../plugin_vertex';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js
index 45d4789b73b39..5e158c5fa97a1 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Vertex } from '../vertex';
import {
PluginVertex,
@@ -25,30 +25,10 @@ describe('PluginVertex', () => {
vertexJson = {
config_name: 'some-name',
stats: {
- millis_per_event: {
- data: [
- [ 1516667383000, 10 ],
- [ 1516667386000, 50 ]
- ]
- },
- percent_of_total_processor_duration: {
- data: [
- [ 1516667383000, 0.25 ],
- [ 1516667386000, 0.3 ]
- ]
- },
- events_in_per_millisecond: {
- data: [
- [ 1516667383000, 0.01 ],
- [ 1516667386000, 0.02 ]
- ]
- },
- events_out_per_millisecond: {
- data: [
- [ 1516667383000, 0.01 ],
- [ 1516667386000, 0.03 ]
- ]
- }
+ millis_per_event: 50,
+ percent_of_total_processor_duration: 0.3,
+ events_in_per_millisecond: 0.01,
+ events_out_per_millisecond: 0.01
}
};
});
@@ -80,7 +60,7 @@ describe('PluginVertex', () => {
it('should have the correct events-per-second stat', () => {
const pluginVertex = new PluginVertex(graph, vertexJson);
- expect(pluginVertex.latestEventsPerSecond).to.be(20);
+ expect(pluginVertex.latestEventsPerSecond).to.be(10);
});
describe('isTimeConsuming', () => {
@@ -91,13 +71,13 @@ describe('PluginVertex', () => {
});
it('should have a false isTimeConsuming result when the plugin consumes an average amount of execution time', () => {
- vertexJson.stats.percent_of_total_processor_duration.data[1][1] = percentExecution;
+ vertexJson.stats.percent_of_total_processor_duration = percentExecution;
const pluginVertex = new PluginVertex(graph, vertexJson);
expect(pluginVertex.isTimeConsuming()).to.be(false);
});
it('should have a true isTimeConsuming result when the plugin consumes a large amount of execution time', () => {
- vertexJson.stats.percent_of_total_processor_duration.data[1][1] = 0.1 +
+ vertexJson.stats.percent_of_total_processor_duration = 0.1 +
(percentExecution * (TIME_CONSUMING_PROCESSOR_THRESHOLD_COEFFICIENT));
const pluginVertex = new PluginVertex(graph, vertexJson);
expect(pluginVertex.isTimeConsuming()).to.be(true);
@@ -111,13 +91,13 @@ describe('PluginVertex', () => {
});
it('should have a true isSlow result when the plugin\'s seconds per event is 2 standard deviations above the mean', () => {
- vertexJson.stats.millis_per_event.data[1][1] = 999999999999999999;
+ vertexJson.stats.millis_per_event = 999999999999999999;
const pluginVertex = new PluginVertex(graph, vertexJson);
expect(pluginVertex.isSlow()).to.be(true);
});
it('should have a false isSlow result when the plugin\'s seconds per event is 2 standard deviations above the mean', () => {
- vertexJson.stats.millis_per_event.data[1][1] = 1;
+ vertexJson.stats.millis_per_event = 1;
const pluginVertex = new PluginVertex(graph, vertexJson);
expect(pluginVertex.isSlow()).to.be(false);
});
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js
index eb091e6bdf683..997306f52cc59 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/queue_vertex.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { QueueVertex } from '../queue_vertex';
import { Vertex } from '../vertex';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js
index bc29533affd6a..3c2a68ad67cc8 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Graph } from '../';
describe('Vertex', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js
index 5cb914a5e4210..cbfa070fe2012 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/vertex_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { vertexFactory } from '../vertex_factory';
import { PluginVertex } from '../plugin_vertex';
import { IfVertex } from '../if_vertex';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js
index 0c74318982bd3..23f316a9351ca 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { last, get, omit } from 'lodash';
+import { get } from 'lodash';
import { Vertex } from './vertex';
export const TIME_CONSUMING_PROCESSOR_THRESHOLD_COEFFICIENT = 2;
@@ -44,28 +44,36 @@ export class PluginVertex extends Vertex {
}
get latestMillisPerEvent() {
- const latestMillisPerEventBucket = last(get(this.stats, 'millis_per_event.data', [])) || [];
- return latestMillisPerEventBucket[1];
+ return get(this.stats, 'millis_per_event');
}
get percentOfTotalProcessorTime() {
- const latestPercentOfTotalProcessorDurationBucket = last(get(this.stats, 'percent_of_total_processor_duration.data', [])) || [];
- return latestPercentOfTotalProcessorDurationBucket[1];
+ return get(this.stats, 'percent_of_total_processor_duration');
}
- get eventsPerSecond() {
- const eventsPerMillisecond = this.isInput
+ get eventsPerMillisecond() {
+ return this.isInput
? this.stats.events_out_per_millisecond
: this.stats.events_in_per_millisecond;
- return {
- ...omit(eventsPerMillisecond, 'data'),
- data: get(eventsPerMillisecond, 'data', []).map(([x, y]) => [x, y * 1000])
- };
+ }
+
+ get eventsPerSecond() {
+ if (!this.eventsPerMillisecond.hasOwnProperty('data')) {
+ return this.eventsPerMillisecond * 1000;
+ }
+
+ const eps = { ...this.eventsPerMillisecond }; // Clone the object so we don't modify the original one
+ eps.data = this.eventsPerMillisecond.data.map(([timestamp, value]) => [ timestamp, value * 1000]);
+ return eps;
}
get latestEventsPerSecond() {
- const latestBucket = last(get(this.eventsPerSecond, 'data', [])) || [];
- return latestBucket[1];
+ if (!this.eventsPerSecond.hasOwnProperty('data')) {
+ return this.eventsPerSecond;
+ }
+
+ const numTimeseriesBuckets = this.eventsPerSecond.data.length;
+ return this.eventsPerSecond.data[numTimeseriesBuckets - 1][1];
}
isTimeConsuming() {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js
index a4347f508a776..1f2d68ba5ee5f 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { IfStatement } from '../if_statement';
import { PluginVertex } from '../../graph/plugin_vertex';
import { IfElement } from '../../list/if_element';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js
index eb5754169d006..c1794852d3421 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/make_statement.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { makeStatement } from '../make_statement';
import { PluginVertex } from '../../graph/plugin_vertex';
import { IfVertex } from '../../graph/if_vertex';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js
index b8c835b9bd4be..7f96298b1530a 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Pipeline } from '../';
import { Graph } from '../../graph';
import { IfStatement } from '../if_statement';
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js
index eafde6839eda2..3bbce82b3f022 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { PluginStatement } from '../plugin_statement';
describe('PluginStatement class', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js
index 4f70604614864..7288065e282e1 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Queue } from '../queue';
describe('Queue class', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js
index f695bf36d2a15..e2c0904a0938c 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { Statement } from '../statement';
describe('Statement class', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js
index 53c7a1a3d0f24..fc50c3b9dfedb 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/utils.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isVertexPipelineStage } from '../utils';
describe('Utils', () => {
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap
index fb22a53cf25b0..aaa012c7a534e 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/pipeline_viewer.test.js.snap
@@ -14,7 +14,6 @@ exports[`PipelineViewer component passes expected props 1`] = `
verticalPosition="center"
>
@@ -90,11 +87,6 @@ exports[`PipelineViewer component renders DetailDrawer when selected vertex is n
verticalPosition="center"
>
{
let pipeline;
@@ -44,7 +43,7 @@ describe('PipelineViewer component', () => {
},
};
- component = ;
+ component = ;
});
it('passes expected props', () => {
@@ -53,33 +52,12 @@ describe('PipelineViewer component', () => {
expect(renderedComponent).toMatchSnapshot();
});
- it('changes selected vertex', () => {
- const vertex = { id: 'stdin' };
-
- const instance = shallowWithIntl(component).instance();
- instance.onShowVertexDetails(vertex);
-
- expect(get(instance, 'state.detailDrawer.vertex')).toBe(vertex);
- });
-
- it('toggles selected vertex on second pass', () => {
- const vertex = { id: 'stdin' };
-
- const instance = shallowWithIntl(component).instance();
- instance.onShowVertexDetails(vertex);
- instance.onShowVertexDetails(vertex);
-
- expect(get(instance, 'state.detailDrawer.vertex')).toBeNull();
- });
-
it('renders DetailDrawer when selected vertex is not null', () => {
const vertex = { id: 'stdin' };
+ component = ;
- const wrapper = shallowWithIntl(component);
- const instance = wrapper.instance();
- instance.onShowVertexDetails(vertex);
- wrapper.update();
+ const renderedComponent = shallowWithIntl(component);
- expect(wrapper).toMatchSnapshot();
+ expect(renderedComponent).toMatchSnapshot();
});
});
diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js
index ddebfc74fb53a..64970a846f0bf 100644
--- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js
+++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/pipeline_viewer.js
@@ -27,36 +27,15 @@ class PipelineViewerUi extends React.Component {
};
}
- onShowVertexDetails = (vertex) => {
- if (vertex === this.state.detailDrawer.vertex) {
- this.onHideVertexDetails();
- }
- else {
- this.setState({
- detailDrawer: {
- vertex
- }
- });
- }
- }
-
- onHideVertexDetails = () => {
- this.setState({
- detailDrawer: {
- vertex: null
- }
- });
- }
-
renderDetailDrawer = () => {
- if (!this.state.detailDrawer.vertex) {
+ if (!this.props.detailVertex) {
return null;
}
return (
this.props.setDetailVertexId(undefined)}
timeseriesTooltipXValueFormatter={this.props.timeseriesTooltipXValueFormatter}
/>
);
@@ -79,8 +58,7 @@ class PipelineViewerUi extends React.Component {
iconType="logstashInput"
headingText={intl.formatMessage({ id: 'xpack.monitoring.logstash.pipelineViewer.inputsTitle', defaultMessage: 'Inputs' })}
elements={inputs}
- onShowVertexDetails={this.onShowVertexDetails}
- detailVertex={this.state.detailDrawer.vertex}
+ onShowVertexDetails={this.props.setDetailVertexId}
/>
@@ -89,16 +67,14 @@ class PipelineViewerUi extends React.Component {
iconType="logstashFilter"
headingText={intl.formatMessage({ id: 'xpack.monitoring.logstash.pipelineViewer.filtersTitle', defaultMessage: 'Filters' })}
elements={filters}
- onShowVertexDetails={this.onShowVertexDetails}
- detailVertex={this.state.detailDrawer.vertex}
+ onShowVertexDetails={this.props.setDetailVertexId}
/>
{ this.renderDetailDrawer() }
diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_enabled/__tests__/__snapshots__/collection_enabled.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_enabled/__tests__/__snapshots__/collection_enabled.test.js.snap
index f34f4ab6158cb..aafbeb9970b6b 100644
--- a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_enabled/__tests__/__snapshots__/collection_enabled.test.js.snap
+++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_enabled/__tests__/__snapshots__/collection_enabled.test.js.snap
@@ -113,7 +113,7 @@ exports[`ExplainCollectionEnabled should explain about xpack.monitoring.collecti
}
property="xpack.monitoring.collection.enabled"
>
-
+
-
+
diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap
index d6db223edc136..2ab3c6b3aa7b4 100644
--- a/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap
+++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/collection_interval/__tests__/__snapshots__/collection_interval.test.js.snap
@@ -286,7 +286,7 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh
isCollectionIntervalUpdating={true}
property="xpack.monitoring.collection.interval"
>
-
+
-
+
@@ -609,7 +609,7 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect
isCollectionIntervalUpdating={false}
property="xpack.monitoring.collection.interval"
>
-
+
-
+
diff --git a/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js b/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js
index 98a107d6e25ce..927387b42e1b7 100644
--- a/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js
+++ b/x-pack/plugins/monitoring/public/directives/main/__tests__/monitoring_main_controller.js
@@ -5,7 +5,7 @@
*/
import { noop } from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { MonitoringMainController } from '../';
const getMockLicenseService = (options) => ({ mlIsSupported: () => options.mlIsSupported });
diff --git a/x-pack/plugins/monitoring/public/directives/main/index.js b/x-pack/plugins/monitoring/public/directives/main/index.js
index e68cd8c7fad4d..a0e3504cf5cb6 100644
--- a/x-pack/plugins/monitoring/public/directives/main/index.js
+++ b/x-pack/plugins/monitoring/public/directives/main/index.js
@@ -8,6 +8,7 @@ import { get } from 'lodash';
import { uiModules } from 'ui/modules';
import template from './index.html';
import { shortenPipelineHash } from '../../../common/formatting';
+import 'ui/directives/kbn_href';
/*
* Manage data and provide helper methods for the "main" directive's template
diff --git a/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js b/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js
index 209207b52db47..e26e637c7a39b 100644
--- a/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js
+++ b/x-pack/plugins/monitoring/public/lib/__tests__/format_number.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
formatNumber, formatBytesUsage
} from '../format_number';
diff --git a/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js b/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js
index 7013db3d93568..bb914379aa114 100644
--- a/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js
+++ b/x-pack/plugins/monitoring/public/lib/logstash/__tests__/pipelines.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isPipelineMonitoringSupportedInVersion } from '../pipelines';
describe('pipelines', () => {
diff --git a/x-pack/plugins/monitoring/public/monitoring.js b/x-pack/plugins/monitoring/public/monitoring.js
index 0e4528ba679c3..2452c3b58e964 100644
--- a/x-pack/plugins/monitoring/public/monitoring.js
+++ b/x-pack/plugins/monitoring/public/monitoring.js
@@ -6,6 +6,7 @@
import uiRoutes from 'ui/routes';
import chrome from 'ui/chrome';
+import 'ui/kbn_top_nav';
import 'ui/autoload/all';
import 'plugins/monitoring/filters';
import 'plugins/monitoring/services/clusters';
diff --git a/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js b/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js
index 6943d6f4e068f..547505c0d5fef 100644
--- a/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js
+++ b/x-pack/plugins/monitoring/public/services/__tests__/breadcrumbs.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { breadcrumbsProvider } from '../breadcrumbs_provider';
import { MonitoringMainController } from 'plugins/monitoring/directives/main';
diff --git a/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js b/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js
index 805fac434bd60..36ab9431058eb 100644
--- a/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js
+++ b/x-pack/plugins/monitoring/public/services/__tests__/executor_provider.js
@@ -5,7 +5,7 @@
*/
import ngMock from 'ng_mock';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { executorProvider } from '../executor_provider';
import Promise from 'bluebird';
diff --git a/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js b/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js
index b10e278728794..ed9899183463c 100644
--- a/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js
+++ b/x-pack/plugins/monitoring/public/views/__tests__/base_controller.js
@@ -5,7 +5,7 @@
*/
import { spy, stub } from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { MonitoringViewBaseController } from '../';
import { timefilter } from 'ui/timefilter';
diff --git a/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js b/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js
index 8614fa90a6af2..5c2791d781f4d 100644
--- a/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js
+++ b/x-pack/plugins/monitoring/public/views/__tests__/base_table_controller.js
@@ -5,7 +5,7 @@
*/
import { spy, stub } from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { MonitoringViewBaseTableController } from '../';
describe('MonitoringViewBaseTableController', function () {
diff --git a/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js b/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js
index 671cdd3a1b609..9ff09d731c48a 100644
--- a/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js
+++ b/x-pack/plugins/monitoring/public/views/logstash/pipeline/index.js
@@ -20,6 +20,7 @@ import { List } from 'plugins/monitoring/components/logstash/pipeline_viewer/mod
import { PipelineState } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline_state';
import { PipelineViewer } from 'plugins/monitoring/components/logstash/pipeline_viewer';
import { Pipeline } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/pipeline';
+import { vertexFactory } from 'plugins/monitoring/components/logstash/pipeline_viewer/models/graph/vertex_factory';
import { MonitoringViewBaseController } from '../../base_controller';
import { I18nContext } from 'ui/i18n';
import {
@@ -28,6 +29,9 @@ import {
EuiPageContent,
} from '@elastic/eui';
+let previousPipelineHash = undefined;
+let detailVertexId = undefined;
+
function getPageData($injector) {
const $route = $injector.get('$route');
const $http = $injector.get('$http');
@@ -38,11 +42,20 @@ function getPageData($injector) {
const { ccs, cluster_uuid: clusterUuid } = globalState;
const pipelineId = $route.current.params.id;
const pipelineHash = $route.current.params.hash || '';
+
+ // Pipeline version was changed, so clear out detailVertexId since that vertex won't
+ // exist in the updated pipeline version
+ if (pipelineHash !== previousPipelineHash) {
+ previousPipelineHash = pipelineHash;
+ detailVertexId = undefined;
+ }
+
const url = pipelineHash
? `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}/${pipelineHash}`
: `../api/monitoring/v1/clusters/${clusterUuid}/logstash/pipeline/${pipelineId}`;
return $http.post(url, {
- ccs
+ ccs,
+ detailVertexId
})
.then(response => response.data)
.then(data => {
@@ -107,11 +120,22 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', {
const timeseriesTooltipXValueFormatter = xValue =>
moment(xValue).format(dateFormat);
+ const setDetailVertexId = vertex => {
+ if (!vertex) {
+ detailVertexId = undefined;
+ } else {
+ detailVertexId = vertex.id;
+ }
+
+ return this.updateData();
+ };
+
$scope.$watch(() => this.data, data => {
if (!data || !data.pipeline) {
return;
}
this.pipelineState = new PipelineState(data.pipeline);
+ this.detailVertex = data.vertex ? vertexFactory(null, data.vertex) : null;
this.renderReact(
@@ -122,6 +146,8 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', {
Pipeline.fromPipelineGraph(this.pipelineState.config.graph)
)}
timeseriesTooltipXValueFormatter={timeseriesTooltipXValueFormatter}
+ setDetailVertexId={setDetailVertexId}
+ detailVertex={this.detailVertex}
/>
@@ -129,6 +155,11 @@ uiRoutes.when('/logstash/pipelines/:id/:hash?', {
);
});
+
+ $scope.$on('$destroy', () => {
+ previousPipelineHash = undefined;
+ detailVertexId = undefined;
+ });
}
}
});
diff --git a/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js b/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js
index 058b9127c82ab..044f0dc2434b9 100644
--- a/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js
+++ b/x-pack/plugins/monitoring/public/views/logstash/pipelines/index.js
@@ -72,6 +72,7 @@ uiRoutes
title: 'Logstash Pipelines',
storageKey: 'logstash.pipelines',
getPageData,
+ reactNodeId: 'monitoringLogstashPipelinesApp',
$scope,
$injector
});
diff --git a/x-pack/plugins/monitoring/public/views/no_data/controller.js b/x-pack/plugins/monitoring/public/views/no_data/controller.js
index d108678cb992f..c35eaf2066bda 100644
--- a/x-pack/plugins/monitoring/public/views/no_data/controller.js
+++ b/x-pack/plugins/monitoring/public/views/no_data/controller.js
@@ -16,6 +16,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { NoData } from 'plugins/monitoring/components';
import { timefilter } from 'ui/timefilter';
import { I18nContext } from 'ui/i18n';
+import 'ui/listen';
const REACT_NODE_ID_NO_DATA = 'noDataReact';
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js b/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js
index 37e0c5531ea0d..4339d0fe3df95 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/aws.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { AWS, AWSCloudService } from '../aws';
describe('AWS', () => {
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js b/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js
index 4e6efe9463b53..cb5251f7844f9 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/azure.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { AZURE } from '../azure';
describe('Azure', () => {
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js
index 19e49bec43c8d..f290f789a319b 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_detector.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { CloudDetector } from '../cloud_detector';
describe('CloudDetector', () => {
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js
index a8cb5c8949c64..e0f31615ed156 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_response.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { CloudServiceResponse } from '../cloud_response';
describe('CloudServiceResponse', () => {
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js
index 34d47d24c51e1..72c40b0a29b83 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_service.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { CloudService } from '../cloud_service';
import { CloudServiceResponse } from '../cloud_response';
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js
index 99c5a0845971d..e1139db313e92 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/cloud_services.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { CLOUD_SERVICES } from '../cloud_services';
import { AWS } from '../aws';
import { AZURE } from '../azure';
diff --git a/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js b/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js
index 467ea8b5ff0cd..88b9e9e3e1c34 100644
--- a/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js
+++ b/x-pack/plugins/monitoring/server/cloud/__tests__/gcp.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { GCP } from '../gcp';
describe('GCP', () => {
diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js
index 1b7d9a0f58bf7..b790aba05351f 100644
--- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js
+++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_cluster_search.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { createStubs } from './fixtures/create_stubs';
import { alertsClusterSearch } from '../alerts_cluster_search';
diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js
index f209a5f177895..8af04a4bdb7be 100644
--- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js
+++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/alerts_clusters_aggregation.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { merge } from 'lodash';
import { createStubs } from './fixtures/create_stubs';
diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js
index df3876367b181..ec18d85752a61 100644
--- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js
+++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/check_license.js
@@ -5,7 +5,7 @@
*/
import { checkLicense, checkLicenseGenerator } from '../check_license';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
describe('Monitoring Check License', () => {
diff --git a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js
index 86902c6400adc..c70c298bf359a 100644
--- a/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js
+++ b/x-pack/plugins/monitoring/server/cluster_alerts/__tests__/verify_monitoring_license.js
@@ -5,7 +5,7 @@
*/
import { verifyMonitoringLicense } from '../verify_monitoring_license';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
describe('Monitoring Verify License', () => {
diff --git a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js
index bb11902f1ff6d..bc2afc7c25e19 100644
--- a/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js
+++ b/x-pack/plugins/monitoring/server/es_client/__tests__/instantiate_client.js
@@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { get, noop } from 'lodash';
-import { exposeClient } from '../instantiate_client';
+import { exposeClient, hasMonitoringCluster } from '../instantiate_client';
function getMockServerFromConnectionUrl(monitoringClusterUrl) {
const server = {
@@ -136,4 +136,16 @@ describe('Instantiate Client', () => {
expect(createClientOptions.password).to.eql('monitoring-p@ssw0rd!-internal-test');
});
});
+
+ describe('hasMonitoringCluster', () => {
+ it('returns true if monitoring is configured', () => {
+ const server = getMockServerFromConnectionUrl('http://monitoring-cluster.test:9200'); // pass null for URL to create the client using prod config
+ expect(hasMonitoringCluster(server)).to.be(true);
+ });
+
+ it('returns false if monitoring is not configured', () => {
+ const server = getMockServerFromConnectionUrl(null);
+ expect(hasMonitoringCluster(server)).to.be(false);
+ });
+ });
});
diff --git a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js
index c52c1b3aa8290..a4930d9d1dc21 100644
--- a/x-pack/plugins/monitoring/server/es_client/instantiate_client.js
+++ b/x-pack/plugins/monitoring/server/es_client/instantiate_client.js
@@ -15,28 +15,22 @@ import { LOGGING_TAG } from '../../common/constants';
*/
export function exposeClient(server) {
- const monitoringEsConfig = server.config().get('xpack.monitoring.elasticsearch');
-
- let config;
- let configSource;
- if (!Boolean(monitoringEsConfig.hosts && monitoringEsConfig.hosts.length)) {
- config = {};
- configSource = 'production';
- } else {
- config = { ...monitoringEsConfig };
- configSource = 'monitoring';
- }
-
+ const config = hasMonitoringCluster(server) ? server.config().get('xpack.monitoring.elasticsearch') : {};
const cluster = server.plugins.elasticsearch.createCluster('monitoring', {
...config,
plugins: [monitoringBulk],
- logQueries: Boolean(monitoringEsConfig.logQueries),
+ logQueries: Boolean(config.logQueries),
});
server.events.on('stop', bindKey(cluster, 'close'));
-
+ const configSource = hasMonitoringCluster(server) ? 'monitoring' : 'production';
server.log([LOGGING_TAG, 'es-client'], `config sourced from: ${configSource} cluster`);
}
+export function hasMonitoringCluster(server) {
+ const hosts = server.config().get('xpack.monitoring.elasticsearch.hosts');
+ return Boolean(hosts && hosts.length);
+}
+
export const instantiateClient = once(exposeClient);
diff --git a/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js b/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js
index 152515fa3194d..39d078c800925 100644
--- a/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js
+++ b/x-pack/plugins/monitoring/server/init_monitoring_xpack_info.js
@@ -5,6 +5,7 @@
*/
import { checkLicenseGenerator } from './cluster_alerts/check_license';
+import { hasMonitoringCluster } from './es_client/instantiate_client';
import { LOGGING_TAG } from '../common/constants';
/*
@@ -12,11 +13,10 @@ import { LOGGING_TAG } from '../common/constants';
*/
export const initMonitoringXpackInfo = async server => {
const config = server.config();
- const xpackInfoOptions = {
+ const xpackInfo = hasMonitoringCluster(server) ? server.plugins.xpack_main.createXPackInfo({
clusterSource: 'monitoring',
pollFrequencyInMillis: config.get('xpack.monitoring.xpack_api_polling_frequency_millis')
- };
- const xpackInfo = server.plugins.xpack_main.createXPackInfo(xpackInfoOptions);
+ }) : server.plugins.xpack_main.info;
xpackInfo.feature('monitoring').registerLicenseCheckResultsGenerator(checkLicenseGenerator);
server.expose('info', xpackInfo);
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js b/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js
index 6f7b6b3383538..6c034ddac6261 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/__tests__/bulk_uploader.js
@@ -6,7 +6,7 @@
import { noop } from 'lodash';
import sinon from 'sinon';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { BulkUploader } from '../bulk_uploader';
const FETCH_INTERVAL = 300;
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js
index 4189903684a9b..9823fd603221b 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/check_for_email_value.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { checkForEmailValue } from '../get_settings_collector';
describe('getSettingsCollector / checkForEmailValue', () => {
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js
index 0d32c1d479853..083e6de3599ac 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_default_admin_email.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { set } from 'lodash';
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js
index 61b1e6a673d93..a97a3e28564f1 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/event_roller.js
@@ -5,7 +5,7 @@
*/
import { EventRoller } from '../event_roller';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
const events = [
{
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js
index 6fb1392830383..a5baeb452928c 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_requests.js
@@ -6,7 +6,7 @@
import _ from 'lodash';
import { mapRequests } from '../map_requests';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Map requests', () => {
it('flatten ports', () => {
diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js
index 224b948732f07..15c987ec33264 100644
--- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js
+++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/ops_buffer/__tests__/map_response_times.js
@@ -6,7 +6,7 @@
import { isEqual } from 'lodash';
import { mapResponseTimes } from '../map_response_times';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Map response times', () => {
it('flatten ports', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js
index 50bcac815045c..879f42f787970 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_auto.js
@@ -5,7 +5,7 @@
*/
import { calculateAuto } from '../calculate_auto.js';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import _ from 'lodash';
import moment from 'moment';
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js
index fb8193e6afcd2..3f70db5124fcb 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_availabiilty.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import { calculateAvailability } from '../calculate_availability';
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js
index 8019c3f30977c..88c84a08541b0 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_overall_status.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { calculateOverallStatus } from '../calculate_overall_status';
describe('Calculate Kibana Cluster Helath', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js
index c9fac06fac7d5..3dc8808d16995 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_rate.js
@@ -5,7 +5,7 @@
*/
import { calculateRate } from '../calculate_rate';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Calculate Rate', () => {
it('returns null when all fields are undefined', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js
index 8c2cf3c97aa10..3c4061490ebc2 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/calculate_timeseries_interval.js
@@ -5,7 +5,7 @@
*/
import moment from 'moment';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { calculateTimeseriesInterval } from '../calculate_timeseries_interval';
describe('calculateTimeseriesInterval', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js b/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js
index e2aa07ad78ee1..d17177102dbf6 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/ccs_utils.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { parseCrossClusterPrefix, prefixIndexPattern } from '../ccs_utils';
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js b/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js
index 8ad0e4e5a953e..cc064c4688f85 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/create_query.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { MissingRequiredError } from '../error_missing_required';
import { ElasticsearchMetric } from '../metrics';
diff --git a/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js b/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js
index 14f6870331db1..729e43d2f0c76 100644
--- a/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js
+++ b/x-pack/plugins/monitoring/server/lib/__tests__/process_version_string.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { normalizeVersionString } from '../normalize_version_string';
describe('Normalizing Version String', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js
index 0e6c8ba53aa23..d4b47070c80a7 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/create_beats_query.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { createBeatsQuery } from '../create_beats_query';
describe('createBeatsQuery', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js
index 8cf25533178b9..fc5124b7d304a 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beat_summary.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_beat_summary';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('get_beat_summary', () => {
it('Handles empty aggregation', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js
index bbe9de2da5eb1..73b1bf77b3e0b 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_beats';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('beats/get_beats', () => {
it('Handles empty response', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js
index 2a77e2825a11e..9fa13b71637a4 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_beats_for_clusters.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_beats_for_clusters';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('get_beats_for_clusters', () => {
it('Handles empty aggregation', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js
index ec21e1865224e..39b85baf7311c 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_latest_stats.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_latest_stats';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('beats/get_latest_stats', () => {
it('Handle empty response', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js
index 857259dd4b232..bf47aa1a2a562 100644
--- a/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js
+++ b/x-pack/plugins/monitoring/server/lib/beats/__tests__/get_stats.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_stats';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('beats/get_stats', () => {
it('Handle empty response', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/ccs_utils.js b/x-pack/plugins/monitoring/server/lib/ccs_utils.js
index 30409960edd9e..5b3980d9619a8 100644
--- a/x-pack/plugins/monitoring/server/lib/ccs_utils.js
+++ b/x-pack/plugins/monitoring/server/lib/ccs_utils.js
@@ -7,7 +7,7 @@
/**
* Prefix all comma separated index patterns within the original {@code indexPattern}.
*
- * Cross Cluster Search (CCS) prefixing is ignored if the user has disabled CCS via kibana.yml,
+ * Cross-cluster search (CCS) prefixing is ignored if the user has disabled CCS via kibana.yml,
* which means that the index pattern will be returned without using {@code ccs}.
*
* @param {Object} config The Kibana configuration object.
diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js
index b5358a1f54787..78c98ba05b8af 100644
--- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js
+++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/flag_supported_clusters.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { flagSupportedClusters } from '../flag_supported_clusters';
diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js
index e6df2396ea34b..87f61a0ba87c7 100644
--- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js
+++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_cluster_status.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getClusterStatus } from '../get_cluster_status';
let clusterStats = {};
diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js
index 3c5f8d2822df8..0b7dabeba72d8 100644
--- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js
+++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_state.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_clusters_state';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import { set } from 'lodash';
diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js
index cd9098a290208..e4755e704bf90 100644
--- a/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js
+++ b/x-pack/plugins/monitoring/server/lib/cluster/__tests__/get_clusters_stats.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { handleClusterStats } from '../get_clusters_stats';
describe('handleClusterStats', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js
index 7bec0eacd964e..bd867a7475f16 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_last_recovery.js
@@ -5,7 +5,7 @@
*/
import { handleLastRecoveries, filterOldShardActivity } from '../get_last_recovery';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('get_last_recovery', () => {
// Note: times are from the epoch!
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js
index b661f11a27207..f97b56d538a8a 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/__tests__/get_ml_jobs.js
@@ -5,7 +5,7 @@
*/
import { set } from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { handleResponse } from '../get_ml_jobs';
describe('Get ML Jobs', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js
index 1f395a746420c..114984c3f6d71 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_index_summary.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { handleResponse } from '../get_index_summary';
describe('get_index_summary handleResponse', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js
index fbe84b9e3d09a..5c1e4c84898f5 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js
@@ -5,7 +5,7 @@
*/
import { handleResponse } from '../get_indices';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
describe('Get Elasticsearch Indices', () => {
it('handle an empty response', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js
index 5d3de396d935a..b9adcb725f0b8 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/calculate_node_type.js
@@ -5,7 +5,7 @@
*/
import { set } from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { calculateNodeType } from '../calculate_node_type.js';
const masterNodeId = 'def456';
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js
index 22e41a02eef86..40904aac2cde0 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { handleResponse } from '../get_node_summary';
describe('Elasticsearch Node Summary get_node_summary handleResponse', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js
index c149c6e3100e9..4c21391a9ae62 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_type_class_label.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { getNodeTypeClassLabel } from '../get_node_type_class_label';
describe('Node Type and Label', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js
index b16f857acdb9a..a8c0f483ec1fa 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/lookups.js
@@ -5,7 +5,7 @@
*/
import { nodeTypeClass, nodeTypeLabel } from '../lookups';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import _ from 'lodash';
describe('Node Types Lookups', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js
index 043c87877e34f..299dc0f61a41b 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/get_shard_stats.js
@@ -5,7 +5,7 @@
*/
import { cloneDeep } from 'lodash';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { handleResponse } from '../get_shard_stats';
import { shardStatsFixture, clusterFixture } from './fixtures';
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js
index 6ec0114742af8..a615a2859a7b3 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__tests__/normalize_shard_objects.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { normalizeIndexShards, normalizeNodeShards } from '../normalize_shard_objects';
function getIndexShardBucket(indexName) {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js
index e464ea323ca75..2f52f83002553 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/cluster.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { checkClusterSettings } from '../';
describe('Elasticsearch Cluster Settings', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js
index e5e93d5f475f1..b3515c4c0c0a0 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/find_reason.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { findReason } from '../find_reason';
describe('Elasticsearch Settings Find Reason for No Data', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js
index 4d41a9b541a23..b0914bbc9861a 100644
--- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js
+++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/__tests__/nodes.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { checkNodesSettings } from '../';
describe('Elasticsearch Nodes Settings', () => {
diff --git a/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js b/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js
index 12d3b3f99013a..3b25aa752b483 100644
--- a/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js
+++ b/x-pack/plugins/monitoring/server/lib/errors/__tests__/auth_errors.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { errors } from 'elasticsearch';
import { forbidden, unauthorized } from 'boom';
import { isAuthError, handleAuthError } from '../auth_errors';
diff --git a/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js b/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js
index 73a0e0f007745..c2b21f354abf1 100644
--- a/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js
+++ b/x-pack/plugins/monitoring/server/lib/errors/__tests__/known_errors.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { errors } from 'elasticsearch';
import { isKnownError, handleKnownError } from '../known_errors';
diff --git a/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js b/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js
index d84d163c5c11e..4d8a63308d26a 100644
--- a/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js
+++ b/x-pack/plugins/monitoring/server/lib/kibana/__tests__/get_kibana_info.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import { handleResponse } from '../get_kibana_info';
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js
index 5ecfb0a902f8b..2cf407bfea7bd 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_node_info.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import moment from 'moment';
import { handleResponse } from '../get_node_info';
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js
index 97a4610a8831f..71732b6a2d7fa 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
_vertexStats,
_enrichStateWithStatsAggregation
@@ -37,13 +37,8 @@ describe('get_pipeline', () => {
it('returns correct stats', () => {
const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
expect(result).to.eql({
- events_in: 10000,
- events_out: 9000,
- duration_in_millis: 18000,
events_out_per_millisecond: 0.01,
millis_per_event: 2,
- queue_push_duration_in_millis: 100000,
- queue_push_duration_in_millis_per_event: 11.11111111111111
});
});
@@ -57,9 +52,6 @@ describe('get_pipeline', () => {
it('returns correct stats', () => {
const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
expect(result).to.eql({
- events_in: 10000,
- events_out: 9000,
- duration_in_millis: 18000,
events_in_per_millisecond: 0.011111111111111112,
events_out_per_millisecond: 0.01,
millis_per_event: 1.8,
@@ -78,9 +70,6 @@ describe('get_pipeline', () => {
it('returns correct stats', () => {
const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
expect(result).to.eql({
- events_in: 10000,
- events_out: 9000,
- duration_in_millis: 18000,
events_in_per_millisecond: 0.011111111111111112,
events_out_per_millisecond: 0.01,
millis_per_event: 1.8,
@@ -93,7 +82,6 @@ describe('get_pipeline', () => {
describe('_enrichStateWithStatsAggregation function', () => {
let stateDocument;
let statsAggregation;
- let version;
let timeseriesInterval;
beforeEach(() => {
@@ -160,278 +148,96 @@ describe('get_pipeline', () => {
};
statsAggregation = {
- timeseriesStats: [
- {
- key: { time_bucket: 1516131120000 },
- pipelines: {
- scoped: {
- vertices: {
- vertex_id: {
- buckets: [
- {
- key: 'mystdout',
- events_in_total: { value: 1000 },
- events_out_total: { value: 1000 },
- duration_in_millis_total: { value: 15 },
- queue_push_duration_in_millis_total: { value: 0 }
- },
- {
- key: 'mystdin',
- events_in_total: { value: 0 },
- events_out_total: { value: 1000 },
- duration_in_millis_total: { value: 0 },
- queue_push_duration_in_millis_total: { value: 13547 }
- }
- ]
- }
- },
- total_processor_duration_stats: {
- count: 276,
- min: 0,
- max: 15904756,
- avg: 6591773.384057971,
- sum: 1819329454
- }
- }
- }
- },
- {
- key: { time_bucket: 1516131180000 },
- pipelines: {
- scoped: {
- vertices: {
- vertex_id: {
- buckets: [
- {
- key: 'mystdout',
- events_in_total: { value: 2000 },
- events_out_total: { value: 2000 },
- duration_in_millis_total: { value: 20 },
- queue_push_duration_in_millis_total: { value: 0 }
- },
- {
- key: 'mystdin',
- events_in_total: { value: 0 },
- events_out_total: { value: 2000 },
- duration_in_millis_total: { value: 0 },
- queue_push_duration_in_millis_total: { value: 25073 }
- }
- ]
- }
- },
- total_processor_duration_stats: {
- count: 276,
- min: 0,
- max: 15953756,
- avg: 6591773.384057971,
- sum: 1819329454
+ aggregations: {
+ pipelines: {
+ scoped: {
+ vertices: {
+ vertex_id: {
+ buckets: [
+ {
+ key: 'mystdout',
+ events_in_total: { value: 1000 },
+ events_out_total: { value: 1000 },
+ duration_in_millis_total: { value: 15 },
+ },
+ {
+ key: 'mystdin',
+ events_in_total: { value: 0 },
+ events_out_total: { value: 1000 },
+ duration_in_millis_total: { value: 0 },
+ }
+ ]
}
+ },
+ total_processor_duration_stats: {
+ count: 276,
+ min: 0,
+ max: 15904756,
+ avg: 6591773.384057971,
+ sum: 1819329454
}
}
}
- ]
- };
-
- version = {
- hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081',
- firstSeen: 1516131138639,
- lastSeen: 1516135440463
+ }
};
-
timeseriesInterval = 30;
});
it('enriches the state document correctly with stats', () => {
- const enrichedStateDocument = _enrichStateWithStatsAggregation(stateDocument, statsAggregation, version, timeseriesInterval);
+ const enrichedStateDocument = _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesInterval);
expect(enrichedStateDocument).to.eql({
- pipeline: {
- batch_size: 125,
- ephemeral_id: '2c53e689-62e8-4ef3-bc57-ea968531a848',
+ batch_size: 125,
+ ephemeral_id: '2c53e689-62e8-4ef3-bc57-ea968531a848',
+ hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081',
+ id: 'main',
+ representation: {
+ type: 'lir',
+ version: '0.0.0',
hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081',
- id: 'main',
- representation: {
- type: 'lir',
- version: '0.0.0',
- hash: 'eada8baceee81726f6be9d0a071beefad3d9a2fd1b5f5d916011dca9fa66d081',
- graph: {
- vertices: [
- {
- config_name: 'stdin',
- id: 'mystdin',
- type: 'plugin',
- plugin_type: 'input',
- stats: {
- duration_in_millis: {
- data: [
- [ 1516131120000, 0 ],
- [ 1516131180000, 0 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_in: {
- data: [
- [ 1516131120000, 0 ],
- [ 1516131180000, 0 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_out: {
- data: [
- [ 1516131120000, 1000 ],
- [ 1516131180000, 2000 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_out_per_millisecond: {
- data: [
- [ 1516131120000, 0.03333333333333333 ],
- [ 1516131180000, 0.06666666666666667 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- millis_per_event: {
- data: [
- [ 1516131120000, 0 ],
- [ 1516131180000, 0 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- queue_push_duration_in_millis: {
- data: [
- [ 1516131120000, 13547 ],
- [ 1516131180000, 25073 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- queue_push_duration_in_millis_per_event: {
- data: [
- [ 1516131120000, 13.547 ],
- [ 1516131180000, 12.5365 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- }
- }
- },
- {
- config_name: 'stdout',
- id: 'mystdout',
- type: 'plugin',
- plugin_type: 'output',
- stats: {
- duration_in_millis: {
- data: [
- [ 1516131120000, 15 ],
- [ 1516131180000, 20 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_in: {
- data: [
- [ 1516131120000, 1000 ],
- [ 1516131180000, 2000 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_out: {
- data: [
- [ 1516131120000, 1000 ],
- [ 1516131180000, 2000 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_in_per_millisecond: {
- data: [
- [1516131120000, 0.03333333333333333],
- [1516131180000, 0.06666666666666667]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- events_out_per_millisecond: {
- data: [
- [ 1516131120000, 0.03333333333333333 ],
- [ 1516131180000, 0.06666666666666667 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- millis_per_event: {
- data: [
- [ 1516131120000, 0.015 ],
- [ 1516131180000, 0.01 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- },
- percent_of_total_processor_duration: {
- data: [
- [ 1516131120000, 0.0000009431141225932671 ],
- [ 1516131180000, 0.0000012536232846986 ]
- ],
- timeRange: {
- min: 1516131138639,
- max: 1516135440463
- }
- }
- }
+ graph: {
+ vertices: [
+ {
+ config_name: 'stdin',
+ id: 'mystdin',
+ type: 'plugin',
+ plugin_type: 'input',
+ stats: {
+ events_out_per_millisecond: 0.03333333333333333,
+ millis_per_event: 0
}
- ],
- edges: [
- {
- id: 'c56369ba2e160c8add43e8f105ca17c374b27f4b4627ea4566f066b0ead0bcc7',
- from: 'mystdin',
- to: '__QUEUE__',
- type: 'plain'
- },
- {
- id: '8a5222282b023399a14195011f2a14aa54a4d97810cd9e0a63c5cd98856bb70f',
- from: '__QUEUE__',
- to: 'mystdout',
- type: 'plain'
+ },
+ {
+ config_name: 'stdout',
+ id: 'mystdout',
+ type: 'plugin',
+ plugin_type: 'output',
+ stats: {
+ events_in_per_millisecond: 0.03333333333333333,
+ events_out_per_millisecond: 0.03333333333333333,
+ millis_per_event: 0.015,
+ percent_of_total_processor_duration: 0.0000009431141225932671
}
- ]
- },
- plugins: []
+ }
+ ],
+ edges: [
+ {
+ id: 'c56369ba2e160c8add43e8f105ca17c374b27f4b4627ea4566f066b0ead0bcc7',
+ from: 'mystdin',
+ to: '__QUEUE__',
+ type: 'plain'
+ },
+ {
+ id: '8a5222282b023399a14195011f2a14aa54a4d97810cd9e0a63c5cd98856bb70f',
+ from: '__QUEUE__',
+ to: 'mystdout',
+ type: 'plain'
+ }
+ ]
},
- workers: 1
- }
+ plugins: []
+ },
+ workers: 1
});
});
});
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js
index 6aefd1c0b88be..47735e08c470a 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipelines.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import {
_handleResponse,
processPipelinesAPIResponse } from '../get_pipelines';
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js
index 63f0f2389033a..8461f880e37f5 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js
@@ -9,7 +9,6 @@ import { get } from 'lodash';
import { checkParam } from '../error_missing_required';
import { getPipelineStateDocument } from './get_pipeline_state_document';
import { getPipelineStatsAggregation } from './get_pipeline_stats_aggregation';
-import { getPipelineVersions } from './get_pipeline_versions';
import { calculateTimeseriesInterval } from '../calculate_timeseries_interval';
export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds) {
@@ -24,7 +23,6 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI
const durationInMillis = vertexStatsBucket.duration_in_millis_total.value;
- const inputStats = {};
const processorStats = {};
const eventsProcessedStats = {
events_out_per_millisecond: eventsOutTotal / timeseriesIntervalInMillis
@@ -34,8 +32,6 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI
if (isInput) {
eventsTotal = eventsOutTotal;
- inputStats.queue_push_duration_in_millis = vertexStatsBucket.queue_push_duration_in_millis_total.value;
- inputStats.queue_push_duration_in_millis_per_event = inputStats.queue_push_duration_in_millis / eventsTotal;
}
if (isProcessor) {
@@ -45,11 +41,7 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI
}
return {
- events_in: eventsInTotal,
- events_out: eventsOutTotal,
- duration_in_millis: durationInMillis,
millis_per_event: durationInMillis / eventsTotal,
- ...inputStats,
...processorStats,
...eventsProcessedStats
};
@@ -57,15 +49,15 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI
/**
* The UI needs a list of all vertices for the requested pipeline version, with each vertex in the list having its timeseries metrics associated with it. The
- * stateDocument object provides the list of vertices while the statsAggregation object provides timeseries metrics. This function stitches the two together
- * and returns the modified stateDocument object.
+ * stateDocument object provides the list of vertices while the statsAggregation object provides the latest metrics for each of these vertices.
+ * This function stitches the two together and returns the modified stateDocument object.
*
* @param {Object} stateDocument
* @param {Object} statsAggregation
* @param {Object} First and last seen timestamps for pipeline version we're getting data for
* @param {Integer} timeseriesIntervalInSeconds The size of each timeseries bucket, in seconds
*/
-export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation, { firstSeen, lastSeen }, timeseriesIntervalInSeconds) {
+export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesIntervalInSeconds) {
const logstashState = stateDocument.logstash_state;
const vertices = logstashState.pipeline.representation.graph.vertices;
@@ -75,67 +67,27 @@ export function _enrichStateWithStatsAggregation(stateDocument, statsAggregation
vertex.stats = {};
});
- // The statsAggregation object buckets by time first, then by vertex ID. However, the logstashState object (which is part of the
- // stateDocument object) buckets by vertex ID first. The UI desires the latter structure so it can look up stats by vertex. So we
- // transpose statsAggregation to bucket by vertex ID first, then by time. This then allows us to stitch the per-vertex timeseries stats
- // from the transposed statsAggregation object onto the logstashState object.
- const timeseriesBuckets = statsAggregation.timeseriesStats;
- timeseriesBuckets.forEach(timeseriesBucket => {
- // each bucket calculates stats for total pipeline CPU time for the associated timeseries
- const totalDurationStats = timeseriesBucket.pipelines.scoped.total_processor_duration_stats;
- const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min;
-
- // Each timeseriesBucket contains a list of vertices and their stats for a single timeseries interval
- const timestamp = timeseriesBucket.key.time_bucket;
- const vertexStatsByIdBuckets = get(timeseriesBucket, 'pipelines.scoped.vertices.vertex_id.buckets', []);
-
- vertexStatsByIdBuckets.forEach(vertexStatsBucket => {
- // Each vertexStats bucket contains a list of stats for a single vertex within a single timeseries interval
- const vertexId = vertexStatsBucket.key;
- const vertex = verticesById[vertexId];
-
- if (vertex !== undefined) {
- // We extract this vertex's stats from vertexStatsBucket
- const vertexStats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
-
- // For each stat (metric), we add it to the stats property of the vertex object in logstashState
- const metrics = Object.keys(vertexStats);
- metrics.forEach(metric => {
- // Create metric object if it doesn't already exist
- if (!vertex.stats.hasOwnProperty(metric)) {
- vertex.stats[metric] = {
- timeRange: {
- min: firstSeen,
- max: lastSeen
- },
- data: []
- };
- }
-
- vertex.stats[metric].data.push([ timestamp, vertexStats[metric]]);
- });
- }
- });
+ const totalDurationStats = statsAggregation.aggregations.pipelines.scoped.total_processor_duration_stats;
+ const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min;
+
+ const verticesWithStatsBuckets = statsAggregation.aggregations.pipelines.scoped.vertices.vertex_id.buckets;
+ verticesWithStatsBuckets.forEach(vertexStatsBucket => {
+ // Each vertexStats bucket contains a list of stats for a single vertex within a single timeseries interval
+ const vertexId = vertexStatsBucket.key;
+ const vertex = verticesById[vertexId];
+
+ if (vertex !== undefined) {
+ // We extract this vertex's stats from vertexStatsBucket
+ vertex.stats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
+ }
});
- return stateDocument.logstash_state;
+ return stateDocument.logstash_state.pipeline;
}
-export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, pipelineHash) {
+export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, version) {
checkParam(lsIndexPattern, 'lsIndexPattern in getPipeline');
- const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
- const versions = await getPipelineVersions(callWithRequest, req, config, lsIndexPattern, clusterUuid, pipelineId);
-
- let version;
- if (pipelineHash) {
- // Find version corresponding to given hash
- version = versions.find(({ hash }) => hash === pipelineHash);
- } else {
- // Go with latest version
- version = versions[0];
- }
-
const options = {
clusterUuid,
pipelineId,
@@ -147,17 +99,13 @@ export async function getPipeline(req, config, lsIndexPattern, clusterUuid, pipe
const timeseriesInterval = calculateTimeseriesInterval(version.firstSeen, version.lastSeen, minIntervalSeconds);
const [ stateDocument, statsAggregation ] = await Promise.all([
- getPipelineStateDocument(callWithRequest, req, lsIndexPattern, options),
- getPipelineStatsAggregation(callWithRequest, req, lsIndexPattern, timeseriesInterval, options)
+ getPipelineStateDocument(req, lsIndexPattern, options),
+ getPipelineStatsAggregation(req, lsIndexPattern, timeseriesInterval, options),
]);
if (stateDocument === null) {
return boom.notFound(`Pipeline [${pipelineId} @ ${version.hash}] not found in the selected time range for cluster [${clusterUuid}].`);
}
- const result = {
- ..._enrichStateWithStatsAggregation(stateDocument, statsAggregation, version, timeseriesInterval),
- versions
- };
- return result;
+ return _enrichStateWithStatsAggregation(stateDocument, statsAggregation, timeseriesInterval);
}
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js
index ccccb84ceb9a1..eb88342eee06f 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js
@@ -8,8 +8,10 @@ import { createQuery } from '../create_query';
import { LogstashMetric } from '../metrics';
import { get } from 'lodash';
-export async function getPipelineStateDocument(callWithRequest, req, logstashIndexPattern,
+export async function getPipelineStateDocument(req, logstashIndexPattern,
{ clusterUuid, pipelineId, version }) {
+
+ const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
const filters = [
{ term: { 'logstash_state.pipeline.id': pipelineId } },
{ term: { 'logstash_state.pipeline.hash': version.hash } }
@@ -32,6 +34,7 @@ export async function getPipelineStateDocument(callWithRequest, req, logstashInd
size: 1,
ignoreUnavailable: true,
body: {
+ _source: { excludes: 'logstash_state.pipeline.representation.plugins' },
sort: { timestamp: { order: 'desc' } },
query,
terminate_after: 1 // Safe to do because all these documents are functionally identical
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js
index 49ca02e204ae2..e59299f0bd673 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { get, last } from 'lodash';
import { createQuery } from '../create_query';
import { LogstashMetric } from '../metrics';
@@ -62,7 +61,6 @@ function nestedVertices(maxBucketSize) {
...scalarCounterAggregation('events_in', fieldPath, ephemeralIdField, maxBucketSize),
...scalarCounterAggregation('events_out', fieldPath, ephemeralIdField, maxBucketSize),
...scalarCounterAggregation('duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize),
- ...scalarCounterAggregation('queue_push_duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize)
}
}
}
@@ -90,62 +88,37 @@ function createScopedAgg(pipelineId, pipelineHash, agg) {
};
}
-function createTimeseriesAggs(pipelineId, pipelineHash, maxBucketSize, timeseriesInterval, lastTimeBucket) {
- return {
- by_time: {
- composite: {
- sources: [
- {
- time_bucket: {
- date_histogram: {
- field: 'logstash_stats.timestamp',
- interval: timeseriesInterval + 's'
- }
- }
- }
- ],
- after: {
- time_bucket: lastTimeBucket
- }
- },
- aggs: createScopedAgg(pipelineId, pipelineHash, {
- vertices: nestedVertices(maxBucketSize),
- total_processor_duration_stats: {
- stats: {
- field: 'logstash_stats.pipelines.events.duration_in_millis'
- }
- }
- })
- }
- };
-}
-
-function fetchPipelineTimeseriesStats(query, logstashIndexPattern, pipelineId, version,
- maxBucketSize, timeseriesInterval, callWithRequest, req, lastTimeBucket = 0) {
+function fetchPipelineLatestStats(query, logstashIndexPattern, pipelineId, version, maxBucketSize, callWithRequest, req) {
const params = {
index: logstashIndexPattern,
size: 0,
ignoreUnavailable: true,
filterPath: [
- 'aggregations.by_time.buckets.key.time_bucket',
- 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.key',
- 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.events_in_total',
- 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.events_out_total',
- 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.duration_in_millis_total',
- 'aggregations.by_time.buckets.pipelines.scoped.vertices.vertex_id.buckets.queue_push_duration_in_millis_total',
- 'aggregations.by_time.buckets.pipelines.scoped.total_processor_duration_stats'
+ 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.key',
+ 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.events_in_total',
+ 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.events_out_total',
+ 'aggregations.pipelines.scoped.vertices.vertex_id.buckets.duration_in_millis_total',
+ 'aggregations.pipelines.scoped.total_processor_duration_stats'
],
body: {
query: query,
- aggs: createTimeseriesAggs(pipelineId, version.hash, maxBucketSize, timeseriesInterval, lastTimeBucket)
+ aggs: createScopedAgg(pipelineId, version.hash, {
+ vertices: nestedVertices(maxBucketSize),
+ total_processor_duration_stats: {
+ stats: {
+ field: 'logstash_stats.pipelines.events.duration_in_millis'
+ }
+ }
+ })
}
};
return callWithRequest(req, 'search', params);
}
-export async function getPipelineStatsAggregation(callWithRequest, req, logstashIndexPattern, timeseriesInterval,
+export function getPipelineStatsAggregation(req, logstashIndexPattern, timeseriesInterval,
{ clusterUuid, start, end, pipelineId, version }) {
+ const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
const filters = [
{
nested: {
@@ -162,6 +135,9 @@ export async function getPipelineStatsAggregation(callWithRequest, req, logstash
}
];
+ start = version.lastSeen - (timeseriesInterval * 1000);
+ end = version.lastSeen;
+
const query = createQuery({
type: 'logstash_stats',
start,
@@ -173,24 +149,6 @@ export async function getPipelineStatsAggregation(callWithRequest, req, logstash
const config = req.server.config();
- const timeBuckets = [];
- let paginatedTimeBuckets;
- do {
- const lastTimeBucket = get(last(paginatedTimeBuckets), 'key.time_bucket', 0);
- const paginatedResponse = await fetchPipelineTimeseriesStats(query, logstashIndexPattern, pipelineId, version,
- config.get('xpack.monitoring.max_bucket_size'), timeseriesInterval, callWithRequest, req, lastTimeBucket);
-
- paginatedTimeBuckets = get(paginatedResponse, 'aggregations.by_time.buckets', []);
- timeBuckets.push(...paginatedTimeBuckets);
- } while (paginatedTimeBuckets.length > 0);
-
- // Drop the last bucket if it is partial (spoiler alert: this will be the case most of the time)
- const lastTimeBucket = last(timeBuckets);
- if (version.lastSeen - lastTimeBucket.key.time_bucket < timeseriesInterval * 1000) {
- timeBuckets.pop();
- }
-
- return {
- timeseriesStats: timeBuckets
- };
+ return fetchPipelineLatestStats(query, logstashIndexPattern, pipelineId, version,
+ config.get('xpack.monitoring.max_bucket_size'), callWithRequest, req);
}
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js
index b66aad3dcfcfe..39b3df6220f0f 100644
--- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js
@@ -10,8 +10,9 @@ import { get } from 'lodash';
import { checkParam } from '../error_missing_required';
function fetchPipelineVersions(...args) {
- const [ callWithRequest, req, config, logstashIndexPattern, clusterUuid, pipelineId ] = args;
+ const [ req, config, logstashIndexPattern, clusterUuid, pipelineId ] = args;
checkParam(logstashIndexPattern, 'logstashIndexPattern in getPipelineVersions');
+ const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
const filters = [
{
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js
new file mode 100644
index 0000000000000..f0d3fc4008b3f
--- /dev/null
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex.js
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+import boom from 'boom';
+import { get } from 'lodash';
+import { checkParam } from '../error_missing_required';
+import { getPipelineStateDocument } from './get_pipeline_state_document';
+import { getPipelineVertexStatsAggregation } from './get_pipeline_vertex_stats_aggregation';
+import { calculateTimeseriesInterval } from '../calculate_timeseries_interval';
+
+export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds) {
+
+ const isInput = vertex.plugin_type === 'input';
+ const isProcessor = vertex.plugin_type === 'filter' || vertex.plugin_type === 'output';
+
+ const timeseriesIntervalInMillis = timeseriesIntervalInSeconds * 1000;
+
+ const eventsInTotal = vertexStatsBucket.events_in_total.value;
+ const eventsOutTotal = get(vertexStatsBucket, 'events_out_total.value', null);
+
+ const durationInMillis = vertexStatsBucket.duration_in_millis_total.value;
+
+ const inputStats = {};
+ const processorStats = {};
+ const eventsProcessedStats = {
+ events_out_per_millisecond: eventsOutTotal / timeseriesIntervalInMillis
+ };
+
+ let eventsTotal;
+
+ if (isInput) {
+ eventsTotal = eventsOutTotal;
+ inputStats.queue_push_duration_in_millis = vertexStatsBucket.queue_push_duration_in_millis_total.value;
+ inputStats.queue_push_duration_in_millis_per_event = inputStats.queue_push_duration_in_millis / eventsTotal;
+ }
+
+ if (isProcessor) {
+ eventsTotal = eventsInTotal;
+ processorStats.percent_of_total_processor_duration = durationInMillis / totalProcessorsDurationInMillis;
+ eventsProcessedStats.events_in_per_millisecond = eventsInTotal / timeseriesIntervalInMillis;
+ }
+
+ return {
+ events_in: eventsInTotal,
+ events_out: eventsOutTotal,
+ duration_in_millis: durationInMillis,
+ millis_per_event: durationInMillis / eventsTotal,
+ ...inputStats,
+ ...processorStats,
+ ...eventsProcessedStats
+ };
+}
+
+/**
+ * The UI needs a list of all vertices for the requested pipeline version, with each vertex in the list having its timeseries metrics associated with it. The
+ * stateDocument object provides the list of vertices while the statsAggregation object provides the timeseries metrics for each of these vertices.
+ * This function stitches the two together and returns the modified stateDocument object.
+ *
+ * @param {Object} stateDocument
+ * @param {Object} vertexStatsAggregation
+ * @param {Object} First and last seen timestamps for pipeline version we're getting data for
+ * @param {Integer} timeseriesIntervalInSeconds The size of each timeseries bucket, in seconds
+ */
+export function _enrichVertexStateWithStatsAggregation(stateDocument, vertexStatsAggregation, vertexId, timeseriesIntervalInSeconds) {
+ const logstashState = stateDocument.logstash_state;
+ const vertices = logstashState.pipeline.representation.graph.vertices;
+
+ // First, filter out the vertex we care about
+ const vertex = vertices.find(v => v.id === vertexId);
+ vertex.stats = {};
+
+ // Next, iterate over timeseries metrics and attach them to vertex
+ const timeSeriesBuckets = vertexStatsAggregation.aggregations.timeseries.buckets;
+ timeSeriesBuckets.forEach(timeSeriesBucket => {
+ // each bucket calculates stats for total pipeline CPU time for the associated timeseries
+ const totalDurationStats = timeSeriesBucket.pipelines.scoped.total_processor_duration_stats;
+ const totalProcessorsDurationInMillis = totalDurationStats.max - totalDurationStats.min;
+
+ const timestamp = timeSeriesBucket.key;
+
+ const vertexStatsBucket = timeSeriesBucket.pipelines.scoped.vertices.vertex_id;
+ const vertexStats = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds);
+ Object.keys(vertexStats).forEach(stat => {
+ if (!vertex.stats.hasOwnProperty(stat)) {
+ vertex.stats[stat] = { data: [] };
+ }
+ vertex.stats[stat].data.push([ timestamp, vertexStats[stat] ]);
+ });
+ });
+
+ return vertex;
+}
+
+export async function getPipelineVertex(req, config, lsIndexPattern, clusterUuid, pipelineId, version, vertexId) {
+ checkParam(lsIndexPattern, 'lsIndexPattern in getPipeline');
+
+ const options = {
+ clusterUuid,
+ pipelineId,
+ version,
+ vertexId
+ };
+
+ // Determine metrics' timeseries interval based on version's timespan
+ const minIntervalSeconds = config.get('xpack.monitoring.min_interval_seconds');
+ const timeseriesInterval = calculateTimeseriesInterval(version.firstSeen, version.lastSeen, minIntervalSeconds);
+
+ const [ stateDocument, statsAggregation ] = await Promise.all([
+ getPipelineStateDocument(req, lsIndexPattern, options),
+ getPipelineVertexStatsAggregation(req, lsIndexPattern, timeseriesInterval, options),
+ ]);
+
+ if (stateDocument === null) {
+ return boom.notFound(`Pipeline [${pipelineId} @ ${version.hash}] not found in the selected time range for cluster [${clusterUuid}].`);
+ }
+
+ return _enrichVertexStateWithStatsAggregation(stateDocument, statsAggregation, vertexId, timeseriesInterval);
+}
diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js
new file mode 100644
index 0000000000000..5c80165e74bf4
--- /dev/null
+++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_vertex_stats_aggregation.js
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+import { createQuery } from '../create_query';
+import { LogstashMetric } from '../metrics';
+
+function scalarCounterAggregation(field, fieldPath, ephemeralIdField, maxBucketSize) {
+ const fullPath = `${fieldPath}.${field}`;
+
+ const byEphemeralIdName = `${field}_temp_by_ephemeral_id`;
+ const sumName = `${field}_total`;
+
+ const aggs = {};
+
+ aggs[byEphemeralIdName] = {
+ terms: {
+ field: ephemeralIdField,
+ size: maxBucketSize,
+ },
+ aggs: {
+ stats: {
+ stats: { field: fullPath }
+ },
+ difference: {
+ bucket_script: {
+ script: 'params.max - params.min',
+ buckets_path: {
+ min: 'stats.min',
+ max: 'stats.max'
+ }
+ }
+ }
+ }
+ };
+
+ aggs[sumName] = {
+ sum_bucket: {
+ buckets_path: `${byEphemeralIdName}>difference`
+ }
+ };
+
+ return aggs;
+}
+
+
+function createAggsObjectFromAggsList(aggsList) {
+ return aggsList.reduce((aggsSoFar, agg) => ({ ...aggsSoFar, ...agg }), {});
+}
+
+function createNestedVertexAgg(vertexId, maxBucketSize) {
+ const fieldPath = 'logstash_stats.pipelines.vertices';
+ const ephemeralIdField = 'logstash_stats.pipelines.vertices.pipeline_ephemeral_id';
+
+ return {
+ vertices: {
+ nested: { path: 'logstash_stats.pipelines.vertices' },
+ aggs: {
+ vertex_id: {
+ filter: {
+ term: {
+ 'logstash_stats.pipelines.vertices.id': vertexId
+ }
+ },
+ aggs: {
+ ...scalarCounterAggregation('events_in', fieldPath, ephemeralIdField, maxBucketSize),
+ ...scalarCounterAggregation('events_out', fieldPath, ephemeralIdField, maxBucketSize),
+ ...scalarCounterAggregation('duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize),
+ ...scalarCounterAggregation('queue_push_duration_in_millis', fieldPath, ephemeralIdField, maxBucketSize)
+ }
+ }
+ }
+ }
+ };
+}
+
+function createTotalProcessorDurationStatsAgg() {
+ return {
+ total_processor_duration_stats: {
+ stats: {
+ field: 'logstash_stats.pipelines.events.duration_in_millis'
+ }
+ }
+ };
+}
+
+function createScopedAgg(pipelineId, pipelineHash, ...aggsList) {
+ return {
+ pipelines: {
+ nested: { path: 'logstash_stats.pipelines' },
+ aggs: {
+ scoped: {
+ filter: {
+ bool: {
+ filter: [
+ { term: { 'logstash_stats.pipelines.id': pipelineId } },
+ { term: { 'logstash_stats.pipelines.hash': pipelineHash } }
+ ]
+ }
+ },
+ aggs: createAggsObjectFromAggsList(aggsList)
+ }
+ }
+ }
+ };
+}
+
+function createTimeSeriesAgg(timeSeriesIntervalInSeconds, ...aggsList) {
+ return {
+ timeseries: {
+ date_histogram: {
+ field: 'timestamp',
+ interval: timeSeriesIntervalInSeconds + 's'
+ },
+ aggs: createAggsObjectFromAggsList(aggsList)
+ }
+ };
+}
+
+function fetchPipelineVertexTimeSeriesStats(query, logstashIndexPattern, pipelineId, version, vertexId,
+ timeSeriesIntervalInSeconds, maxBucketSize, callWithRequest, req) {
+ const aggs = {
+ ...createTimeSeriesAgg(timeSeriesIntervalInSeconds,
+ createScopedAgg(pipelineId, version.hash,
+ createNestedVertexAgg(vertexId, maxBucketSize),
+ createTotalProcessorDurationStatsAgg()
+ )
+ )
+ };
+
+ const params = {
+ index: logstashIndexPattern,
+ size: 0,
+ ignoreUnavailable: true,
+ filterPath: [
+ 'aggregations.timeseries.buckets.key',
+ 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.events_in_total',
+ 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.events_out_total',
+ 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.duration_in_millis_total',
+ 'aggregations.timeseries.buckets.pipelines.scoped.vertices.vertex_id.queue_push_duration_in_millis_total',
+ 'aggregations.timeseries.buckets.pipelines.scoped.total_processor_duration_stats'
+ ],
+ body: {
+ query: query,
+ aggs
+ }
+ };
+
+ return callWithRequest(req, 'search', params);
+}
+
+export function getPipelineVertexStatsAggregation(req, logstashIndexPattern, timeSeriesIntervalInSeconds,
+ { clusterUuid, start, end, pipelineId, version, vertexId }) {
+ const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring');
+ const filters = [
+ {
+ nested: {
+ path: 'logstash_stats.pipelines',
+ query: {
+ bool: {
+ must: [
+ { term: { 'logstash_stats.pipelines.hash': version.hash } },
+ { term: { 'logstash_stats.pipelines.id': pipelineId } },
+ ]
+ }
+ }
+ }
+ }
+ ];
+
+ start = version.firstSeen;
+ end = version.lastSeen;
+
+ const query = createQuery({
+ type: 'logstash_stats',
+ start,
+ end,
+ metric: LogstashMetric.getMetricFields(),
+ clusterUuid,
+ filters
+ });
+
+ const config = req.server.config();
+
+ return fetchPipelineVertexTimeSeriesStats(query, logstashIndexPattern, pipelineId, version, vertexId,
+ timeSeriesIntervalInSeconds, config.get('xpack.monitoring.max_bucket_size'), callWithRequest, req);
+}
diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js
index 433c48f02b3ea..fdd9342cf9eae 100644
--- a/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js
+++ b/x-pack/plugins/monitoring/server/routes/api/v1/logstash/pipeline.js
@@ -6,10 +6,18 @@
import Joi from 'joi';
import { handleError } from '../../../../lib/errors';
+import { getPipelineVersions } from '../../../../lib/logstash/get_pipeline_versions';
import { getPipeline } from '../../../../lib/logstash/get_pipeline';
+import { getPipelineVertex } from '../../../../lib/logstash/get_pipeline_vertex';
import { prefixIndexPattern } from '../../../../lib/ccs_utils';
import { INDEX_PATTERN_LOGSTASH } from '../../../../../common/constants';
+function getPipelineVersion(versions, pipelineHash) {
+ return pipelineHash
+ ? versions.find(({ hash }) => hash === pipelineHash)
+ : versions[0];
+}
+
/*
* Logstash Pipeline route.
*/
@@ -34,22 +42,46 @@ export function logstashPipelineRoute(server) {
pipelineHash: Joi.string().optional()
}),
payload: Joi.object({
- ccs: Joi.string().optional()
+ ccs: Joi.string().optional(),
+ detailVertexId: Joi.string().optional()
})
}
},
- handler: (req) => {
+ handler: async (req) => {
const config = server.config();
const ccs = req.payload.ccs;
const clusterUuid = req.params.clusterUuid;
+ const detailVertexId = req.payload.detailVertexId;
const lsIndexPattern = prefixIndexPattern(config, INDEX_PATTERN_LOGSTASH, ccs);
const pipelineId = req.params.pipelineId;
// Optional params default to empty string, set to null to be more explicit.
const pipelineHash = req.params.pipelineHash || null;
- return getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, pipelineHash)
- .catch(err => handleError(err, req));
+ // Figure out which version of the pipeline we want to show
+ let versions;
+ try {
+ versions = await getPipelineVersions(req, config, lsIndexPattern, clusterUuid, pipelineId);
+ } catch (err) {
+ return handleError(err, req);
+ }
+ const version = getPipelineVersion(versions, pipelineHash);
+
+ const promises = [ getPipeline(req, config, lsIndexPattern, clusterUuid, pipelineId, version) ];
+ if (detailVertexId) {
+ promises.push(getPipelineVertex(req, config, lsIndexPattern, clusterUuid, pipelineId, version, detailVertexId));
+ }
+
+ try {
+ const [ pipeline, vertex ] = await Promise.all(promises);
+ return {
+ versions,
+ pipeline,
+ vertex
+ };
+ } catch (err) {
+ return handleError(err, req);
+ }
}
});
}
diff --git a/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js
index 19a7b56759269..394c2c4735c0c 100644
--- a/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js
+++ b/x-pack/plugins/remote_clusters/server/lib/check_license/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js
index 443744ccb0cc8..f9c102be7a1ff 100644
--- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js
+++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_custom_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapCustomError } from '../wrap_custom_error';
describe('wrap_custom_error', () => {
diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js
index b8d59590ebf33..f3237563edb45 100644
--- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js
+++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_es_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapEsError } from '../wrap_es_error';
describe('wrap_es_error', () => {
diff --git a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
index 6d6a336417bef..85e0b2b3033ad 100644
--- a/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
+++ b/x-pack/plugins/remote_clusters/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapUnknownError } from '../wrap_unknown_error';
describe('wrap_unknown_error', () => {
diff --git a/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
index d50ff9480d3e4..76fdf7b36c3d0 100644
--- a/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
+++ b/x-pack/plugins/remote_clusters/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isEsErrorFactory } from '../is_es_error_factory';
import { set } from 'lodash';
diff --git a/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index ffbbd1395a418..dc641bef91085 100644
--- a/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
describe('license_pre_routing_factory', () => {
diff --git a/x-pack/plugins/reporting/common/__tests__/export_types_registry.js b/x-pack/plugins/reporting/common/__tests__/export_types_registry.js
index 9df8b8b47f50f..02aff84fb7d0d 100644
--- a/x-pack/plugins/reporting/common/__tests__/export_types_registry.js
+++ b/x-pack/plugins/reporting/common/__tests__/export_types_registry.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { ExportTypesRegistry } from '../export_types_registry';
describe('ExportTypesRegistry', function () {
diff --git a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js
index ee851694f03d0..b8799f7a516d9 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import Puid from 'puid';
import sinon from 'sinon';
import nodeCrypto from '@elastic/node-crypto';
diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js
index e8dd84637589c..7e2b38f380e8d 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/escape_value.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { createEscapeValue } from '../escape_value';
describe('escapeValue', function () {
diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js
index d11552daf9e89..15d2bbbc60a44 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { FieldFormat } from '../../../../../../../../src/legacy/ui/field_formats/field_format.js';
import { FieldFormatsService } from '../../../../../../../../src/legacy/ui/field_formats/field_formats_service.js';
diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js
index 005862a61fee1..4abf31bb3e5e3 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/flatten_hit.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { createFlattenHit } from '../flatten_hit';
describe('flattenHit', function () {
diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js
index 9faa32fee9b0b..e3d588b5f48f1 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/format_csv_values.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { createFormatCsvValues } from '../format_csv_values';
describe('formatCsvValues', function () {
diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js
index 15a10934b5db5..32b68e6c7ba09 100644
--- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js
+++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/max_size_string_builder.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { MaxSizeStringBuilder } from '../max_size_string_builder';
describe('MaxSizeStringBuilder', function () {
diff --git a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js
index 999144a5ce1c5..a9329a7b42da8 100644
--- a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js
+++ b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/encode_uri_query.js
@@ -1,4 +1,4 @@
-/* eslint-disable @kbn/license-header/require-license-header */
+/* eslint-disable @kbn/eslint/require-license-header */
// This function was extracted from angular v1.3
diff --git a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js
index 9b78d73b39449..ee0e7c81e4849 100644
--- a/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js
+++ b/x-pack/plugins/reporting/export_types/printable_pdf/server/lib/pdf/assets/fonts/noto/index.js
@@ -1,4 +1,4 @@
-/* eslint-disable @kbn/license-header/require-license-header */
+/* eslint-disable @kbn/eslint/require-license-header */
/**
* @notice
*
diff --git a/x-pack/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap b/x-pack/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
index 39ea6409cf7ae..d4d7165a8454e 100644
--- a/x-pack/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
+++ b/x-pack/plugins/reporting/public/components/__snapshots__/report_info_button.test.tsx.snap
@@ -83,11 +83,15 @@ Array [
>
({ jobQueueClient: mockJobQueueClient }));
diff --git a/x-pack/plugins/reporting/public/components/report_info_button.test.tsx b/x-pack/plugins/reporting/public/components/report_info_button.test.tsx
index 93ceed0f64a0e..3b9c2a8485423 100644
--- a/x-pack/plugins/reporting/public/components/report_info_button.test.tsx
+++ b/x-pack/plugins/reporting/public/components/report_info_button.test.tsx
@@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-const mockJobQueueClient = { getInfo: jest.fn() };
-jest.mock('../lib/job_queue_client', () => ({ jobQueueClient: mockJobQueueClient }));
+import { mockJobQueueClient } from './report_info_button.test.mocks';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
diff --git a/x-pack/plugins/reporting/public/components/report_listing.tsx b/x-pack/plugins/reporting/public/components/report_listing.tsx
index 262362a1e5a51..56f0e382d23a6 100644
--- a/x-pack/plugins/reporting/public/components/report_listing.tsx
+++ b/x-pack/plugins/reporting/public/components/report_listing.tsx
@@ -23,7 +23,7 @@ import { ReportErrorButton } from './report_error_button';
import { ReportInfoButton } from './report_info_button';
import {
- EuiBasicTable,
+ EuiBasicTable as EuiBasicTableTyped,
EuiButtonIcon,
EuiPageContent,
EuiSpacer,
@@ -296,7 +296,7 @@ class ReportListingUi extends Component {
};
return (
- ;
}
-import { EuiButton, EuiCopy, EuiForm, EuiFormRow, EuiSpacer, EuiText } from '@elastic/eui';
+import {
+ EuiButton,
+ EuiCopy as EuiCopyTyped,
+ EuiForm,
+ EuiFormRow,
+ EuiSpacer,
+ EuiText,
+} from '@elastic/eui';
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
import React, { Component, ReactElement } from 'react';
import { KFetchError } from 'ui/kfetch/kfetch_error';
@@ -131,7 +138,7 @@ class ReportingPanelContentUi extends Component {
-
@@ -143,7 +150,7 @@ class ReportingPanelContentUi extends Component {
/>
)}
-
+
);
}
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js
deleted file mode 100644
index 33a83f01f53ea..0000000000000
--- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/* eslint-disable @kbn/license-header/require-license-header */
-export const search = {
- _index: '.kibana',
- _type: 'search',
- _id: 'mock-search',
- _version: 1,
- found: true,
- _source: {
- title: 'to IN',
- description: '',
- hits: 0,
- columns: [
- '_source'
- ],
- sort: [
- '@timestamp',
- 'desc'
- ],
- version: 1,
- kibanaSavedObjectMeta: {
- searchSourceJSON: '{\'index\':\'logstash-*\',\'query\':{\'query_string\':{\'query\':\'geo.dest: IN\','
- + '\'analyze_wildcard\':true}},\'filter\':[],\'highlight\':{\'pre_tags\':[\'@kibana-highlighted-field@\'],'
- + '\'post_tags\':[\'@/kibana-highlighted-field@\'],\'fields\':{\'*\':{}},\'require_field_match\':false,'
- + '\'fragment_size\':2147483647}}'
- }
- }
-};
-
-export const visualization = {
- _index: '.kibana',
- _type: 'visualization',
- _id: 'mock-visualization',
- _version: 1,
- found: true,
- _source: {
- title: 'dem line',
- visState: '{\'title\':\'New Visualization\',\'type\':\'line\',\'params\':{\'shareYAxis\':true,\'addTooltip\':true,'
- + '\'addLegend\':true,\'showCircles\':true,\'smoothLines\':false,\'interpolate\':\'linear\',\'scale\':\'linear\','
- + '\'drawLinesBetweenPoints\':true,\'radiusRatio\':9,\'times\':[],\'addTimeMarker\':false,\'defaultYExtents\':false,'
- + '\'setYExtents\':false,\'yAxis\':{}},\'aggs\':[{\'id\':\'1\',\'type\':\'count\',\'schema\':\'metric\',\'params\':{}},'
- + '{\'id\':\'2\',\'type\':\'date_histogram\',\'schema\':\'segment\',\'params\':{\'field\':\'@timestamp\',\'interval\':\'auto\','
- + '\'customInterval\':\'2h\',\'min_doc_count\':1,\'extended_bounds\':{}}}],\'listeners\':{}}',
- uiStateJSON: '{}',
- description: '',
- version: 1,
- kibanaSavedObjectMeta: {
- searchSourceJSON: '{\'index\':\'logstash-*\',\'query\':{\'query_string\':{\'query\':\'*\',\'analyze_wildcard\':true}},\'filter\':[]}'
- }
- }
-};
-
-export const dashboard = {
- _index: '.kibana',
- _type: 'dashboard',
- _id: 'mock-dashboard',
- _version: 1,
- found: true,
- _source: {
- title: 'example dashboard',
- hits: 0,
- description: '',
- panelsJSON: '[{\'id\':\'mock-visualization\',\'type\':\'visualization\',\'panelIndex\':1,\'size_x\':3,\'size_y\':5,'
- + '\'col\':1,\'row\':1},{\'id\':\'mock-search\',\'type\':\'search\',\'panelIndex\':2,\'size_x\':7,\'size_y\':4,\'col\':4,'
- + '\'row\':1,\'columns\':[\'_source\'],\'sort\':[\'@timestamp\',\'desc\']}]',
- optionsJSON: '{\'darkTheme\':false}',
- uiStateJSON: '{}',
- version: 1,
- timeRestore: false,
- kibanaSavedObjectMeta: {
- searchSourceJSON: '{\'filter\':[{\'query\':{\'query_string\':{\'query\':\'*\',\'analyze_wildcard\':true}}}]}'
- }
- }
-};
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2
deleted file mode 100644
index d4f349ee7dba9..0000000000000
Binary files a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.bz2 and /dev/null differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.tar.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.tar.bz2
deleted file mode 100644
index d10b896e1d55b..0000000000000
Binary files a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.tar.bz2 and /dev/null differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.zip b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.zip
deleted file mode 100644
index bbd9e07bdb095..0000000000000
Binary files a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js.zip and /dev/null differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md
new file mode 100644
index 0000000000000..ab5ba94b31d97
--- /dev/null
+++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md
@@ -0,0 +1,9 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam accumsan eleifend dolor, lacinia ullamcorper metus. Nam sollicitudin, elit ut vehicula sagittis, risus ligula tristique arcu, non hendrerit dolor elit ac urna. Fusce congue accumsan massa vitae congue. Phasellus tristique leo sed sapien ultricies faucibus. Vivamus ultrices sem at tellus fringilla, eget lacinia tellus ullamcorper. Donec pulvinar pretium ante, ut cursus sem varius sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque justo risus, aliquam tempus bibendum vel, dignissim vitae est. Suspendisse hendrerit dictum tincidunt. Vestibulum sed odio convallis, pretium ligula luctus, dictum metus. Nullam scelerisque risus id nisl venenatis, non volutpat erat ornare. Suspendisse quam nunc, sollicitudin eget sodales vehicula, lacinia ac ligula. Fusce viverra, metus posuere laoreet molestie, tellus dui pharetra est, at porta nulla est at nisi. Aliquam ut elit orci. Etiam ac venenatis ex. Praesent est lacus, dictum sit amet ornare id, vulputate sit amet odio.
+
+Curabitur pretium viverra nibh, interdum dapibus turpis tincidunt at. Duis ac libero ultricies, maximus metus sit amet, rutrum sapien. Suspendisse potenti. Praesent a massa non nisl ullamcorper congue nec et turpis. Phasellus mattis, quam in tempor dictum, quam dui commodo velit, vel rutrum urna libero rhoncus felis. Nunc ullamcorper ligula fringilla ultricies bibendum. Nulla facilisi. Vestibulum pulvinar justo nisl, vel interdum urna venenatis ornare. Nunc luctus malesuada metus, ac luctus lorem fringilla faucibus. Cras ullamcorper neque ac sem facilisis feugiat. Maecenas tempor nisl arcu, eget dignissim ex faucibus sed.
+
+Ut vel ex ipsum. Aenean interdum a tortor non convallis. Curabitur viverra aliquam laoreet. Aliquam commodo ex ut dui venenatis, non pretium est feugiat. Integer nunc nisl, sodales nec tristique nec, finibus sed felis. In metus purus, interdum at congue nec, vehicula ac odio. Mauris in ultrices tellus. Pellentesque eget laoreet dui. Proin sollicitudin orci non odio ullamcorper bibendum. Nam neque tortor, laoreet at egestas in, viverra sit amet orci. Mauris facilisis non ipsum in accumsan.
+
+Proin luctus, felis at ultricies vulputate, neque lectus convallis odio, in laoreet lorem nulla eget enim. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed at justo elementum, laoreet est pretium, consequat quam. Mauris accumsan consectetur tellus a semper. Nam dictum justo vitae sapien congue, quis porta orci condimentum. Sed dapibus, ex sed luctus dapibus, magna sapien euismod nisl, id tincidunt erat lorem vel purus. Vivamus consectetur eros nec facilisis pellentesque.
+
+Duis et rutrum eros. Cras id bibendum nisl. Aenean pulvinar non tortor a varius. Pellentesque at auctor lacus. Phasellus aliquet massa elit, vitae bibendum nunc interdum sed. Aenean a consequat tellus, nec pretium odio. Aenean et nisl facilisis, eleifend urna vel, tempor enim. Curabitur sapien sem, rutrum eu velit id, ullamcorper cursus justo. Donec eget magna nec enim iaculis placerat.
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2
new file mode 100644
index 0000000000000..c49e1b504ef12
Binary files /dev/null and b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.bz2 differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.tar.bz2 b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.tar.bz2
new file mode 100644
index 0000000000000..3399f39b1ad70
Binary files /dev/null and b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.tar.bz2 differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip
new file mode 100644
index 0000000000000..a0836ba67abe4
Binary files /dev/null and b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/file.md.zip differ
diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js
index 2eb85e18f07bd..e3af8b2c0029a 100644
--- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js
+++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/extract.js
@@ -6,19 +6,20 @@
import fs from 'fs';
import crypto from 'crypto';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
+import { resolve } from 'path';
import { extract } from '../extract';
import { ExtractError } from '../extract_error';
import { promisify } from 'util';
-const FIXTURES_FOLDER = `${__dirname}/__fixtures__`;
-const SRC_FILE_UNCOMPRESSED = `${FIXTURES_FOLDER}/extract_test_file.js`;
+const FIXTURES_FOLDER = resolve(__dirname, '__fixtures__');
+const SRC_FILE_UNCOMPRESSED = resolve(FIXTURES_FOLDER, 'file.md');
const SRC_FILE_COMPRESSED_ZIP = `${SRC_FILE_UNCOMPRESSED}.zip`;
const SRC_FILE_COMPRESSED_BZ2 = `${SRC_FILE_UNCOMPRESSED}.bz2`;
const SRC_FILE_COMPRESSED_TAR_BZ2 = `${SRC_FILE_UNCOMPRESSED}.tar.bz2`;
-const EXTRACT_TARGET_FOLDER = `${FIXTURES_FOLDER}/extract_target`;
-const EXTRACT_TARGET_FILE = `${EXTRACT_TARGET_FOLDER}/extract_test_file.js`;
+const EXTRACT_TARGET_FOLDER = resolve(FIXTURES_FOLDER, 'extract_target');
+const EXTRACT_TARGET_FILE = resolve(EXTRACT_TARGET_FOLDER, 'file.md');
const fsp = {
mkdir: promisify(fs.mkdir),
diff --git a/x-pack/plugins/reporting/server/lib/__tests__/check_license.js b/x-pack/plugins/reporting/server/lib/__tests__/check_license.js
index dc42258a7897a..480cf4d3e14e2 100644
--- a/x-pack/plugins/reporting/server/lib/__tests__/check_license.js
+++ b/x-pack/plugins/reporting/server/lib/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicenseFactory } from '../check_license';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js
index 5a394c1ac29f5..b40765810fb63 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/cancellation_token.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { CancellationToken } from '../../helpers/cancellation_token';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js
index 533ba93735c4f..7b0b5e3e468c2 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { createIndex } from '../../helpers/create_index';
import { ClientMock } from '../fixtures/elasticsearch';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js
index f0264ce3985e2..d41b29106bb9d 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/errors.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { WorkerTimeoutError, UnspecifiedWorkerError } from '../../helpers/errors';
describe('custom errors', function () {
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js
index cfd25e73640d9..e57e62c229ff1 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/index_timestamp.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import moment from 'moment';
import { constants } from '../../constants';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js
index ad2da19579387..3d25b45298535 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/index.js
@@ -5,7 +5,7 @@
*/
import events from 'events';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import proxyquire from 'proxyquire';
import { noop, times } from 'lodash';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js
index 15ef68c1cb834..233ecb07ca44c 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js
@@ -5,7 +5,7 @@
*/
import events from 'events';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import proxyquire from 'proxyquire';
import { QueueMock } from './fixtures/queue';
diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js
index 7607049479f6b..bb3f9495e88f7 100644
--- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js
+++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import moment from 'moment';
import { noop, random, get, find, identity } from 'lodash';
diff --git a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js
index 78c449b7f6c2d..9a74ba63b8e31 100644
--- a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js
+++ b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_config.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { validateConfig } from '../validate_config';
diff --git a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js
index 604bd75525298..fc825952e34b4 100644
--- a/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js
+++ b/x-pack/plugins/reporting/server/lib/validate/__tests__/validate_max_content_length.js
@@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { validateMaxContentLength } from '../validate_max_content_length';
diff --git a/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js b/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js
index 3c5d044212d1f..42b2019507fe9 100644
--- a/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js
+++ b/x-pack/plugins/reporting/server/routes/lib/__tests__/authorized_user_pre_routing.test.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { authorizedUserPreRoutingFactory } from '../authorized_user_pre_routing';
diff --git a/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js b/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js
index 5cabb57f1568d..01b0464aa0e00 100644
--- a/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js
+++ b/x-pack/plugins/rollup/__jest__/client_integration/job_create.test_helpers.js
@@ -103,7 +103,7 @@ export const initTestBed = () => {
};
};
-export const nextTick = async () => new Promise((resolve) => setTimeout(resolve));
+export { nextTick } from '../../../../test_utils';
export const mockServerResponses = server => {
const mockIndexPatternValidityResponse = (response) => {
diff --git a/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js b/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js
new file mode 100644
index 0000000000000..951e63147e435
--- /dev/null
+++ b/x-pack/plugins/rollup/__jest__/client_integration/job_list.test.js
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+import sinon from 'sinon';
+import axios from 'axios';
+
+import { registerTestBed, nextTick } from '../../../../test_utils';
+import { createRollupJobsStore } from '../../public/crud_app/store';
+import { setHttp, registerRouter, getRouter } from '../../public/crud_app/services';
+import { JobList } from '../../public/crud_app/sections/job_list';
+
+// axios has a $http like interface so using it to simulate $http
+setHttp(axios.create());
+
+jest.mock('ui/chrome', () => ({
+ addBasePath: (path) => path ? path : 'api/rollup',
+ breadcrumbs: { set: () => {} },
+}));
+
+jest.mock('../../public/crud_app/services', () => {
+ const services = require.requireActual('../../public/crud_app/services');
+ return {
+ ...services,
+ getRouterLinkProps: (link) => ({ href: link }),
+ };
+});
+
+const loadJobsMock = {
+ jobs: [{
+ config: {
+ id: 'my-rollup-job',
+ index_pattern: 'kibana_sample*',
+ rollup_index: 'rollup-index',
+ cron: '0 0 0 ? * 7',
+ groups: {
+ date_histogram: {
+ interval: '24h',
+ field: 'timestamp',
+ delay: '1d',
+ time_zone: 'UTC'
+ }
+ },
+ metrics: [],
+ timeout: '20s',
+ page_size: 1000
+ },
+ status: {
+ job_state: 'stopped',
+ upgraded_doc_id: true
+ },
+ stats: {
+ pages_processed: 0,
+ documents_processed: 0,
+ rollups_indexed: 0,
+ trigger_count: 0,
+ index_time_in_ms: 0,
+ index_total: 0,
+ index_failures: 0,
+ search_time_in_ms: 0,
+ search_total: 0,
+ search_failures: 0
+ }
+ }]
+};
+
+describe('', () => {
+ describe('detail panel', () => {
+ let server;
+ let component;
+ let getMetadataFromEuiTable;
+ let exists;
+
+ const testBedOptions = {
+ memoryRouter: {
+ onRouter: (router) => {
+ // register our react memory router
+ registerRouter(router);
+ }
+ }
+ };
+
+ beforeEach(async () => {
+ server = sinon.fakeServer.create();
+ server.respondImmediately = true;
+
+ // Mock load job list
+ server.respondWith('GET', '/api/rollup/jobs', [
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify(loadJobsMock),
+ ]);
+
+ // Mock all user actions tracking
+ server.respondWith('POST', /\/api\/user_action/, [200, { 'Content-Type': 'application/json' }, '']);
+
+ const initTestBed = registerTestBed(JobList, {}, createRollupJobsStore());
+ ({ component, exists, getMetadataFromEuiTable } = initTestBed(undefined, testBedOptions));
+
+ await nextTick(); // We need to wait next tick for the mock server response to comes in
+ component.update();
+ });
+
+ test('should open the detail panel when clicking on a job in the table', () => {
+ const { rows } = getMetadataFromEuiTable('rollupJobsListTable');
+ const button = rows[0].columns[1].reactWrapper.find('button');
+
+ expect(exists('rollupJobDetailFlyout')).toBe(false); // make sure it is not shown
+
+ button.simulate('click');
+
+ expect(exists('rollupJobDetailFlyout')).toBe(true);
+ });
+
+ test('should add the Job id to the route query params when opening the detail panel', () => {
+ const { rows } = getMetadataFromEuiTable('rollupJobsListTable');
+ const button = rows[0].columns[1].reactWrapper.find('button');
+
+ expect(getRouter().history.location.search).toEqual('');
+
+ button.simulate('click');
+
+ const {
+ jobs: [{
+ config: { id: jobId },
+ }],
+ } = loadJobsMock;
+ expect(getRouter().history.location.search).toEqual(`?job=${jobId}`);
+ });
+
+ test('should open the detail panel whenever a job id is added to the query params', () => {
+ expect(exists('rollupJobDetailFlyout')).toBe(false); // make sure it is not shown
+
+ getRouter().history.replace({ search: `?job=bar` });
+
+ component.update();
+
+ expect(exists('rollupJobDetailFlyout')).toBe(true);
+ });
+ });
+});
diff --git a/x-pack/plugins/rollup/public/crud_app/app.js b/x-pack/plugins/rollup/public/crud_app/app.js
index 11ac412104db8..2e6994a01d3e7 100644
--- a/x-pack/plugins/rollup/public/crud_app/app.js
+++ b/x-pack/plugins/rollup/public/crud_app/app.js
@@ -6,14 +6,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { Switch, Route, Redirect } from 'react-router-dom';
+import { HashRouter, Switch, Route, Redirect } from 'react-router-dom';
import { UA_APP_LOAD } from '../../common';
import { CRUD_APP_BASE_PATH } from './constants';
import { registerRouter, setUserHasLeftApp, trackUserAction } from './services';
import { JobList, JobCreate } from './sections';
-export class App extends Component {
+class ShareRouter extends Component {
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
@@ -34,7 +34,13 @@ export class App extends Component {
registerRouter(router);
}
- componentWillMount() {
+ render() {
+ return this.props.children;
+ }
+}
+
+export class App extends Component { // eslint-disable-line react/no-multi-comp
+ componentDidMount() {
trackUserAction(UA_APP_LOAD);
}
@@ -45,11 +51,15 @@ export class App extends Component {
render() {
return (
-
-
-
-
-
+
+
+
+
+
+
+
+
+
);
}
}
diff --git a/x-pack/plugins/rollup/public/crud_app/index.js b/x-pack/plugins/rollup/public/crud_app/index.js
index b43592c8e2284..28e9973d2151b 100644
--- a/x-pack/plugins/rollup/public/crud_app/index.js
+++ b/x-pack/plugins/rollup/public/crud_app/index.js
@@ -8,7 +8,6 @@ import React from 'react';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
-import { HashRouter } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { I18nContext } from 'ui/i18n';
import { management } from 'ui/management';
@@ -33,9 +32,7 @@ const renderReact = async (elem) => {
render(
-
-
-
+ ,
elem
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
index 5aa47b47998bc..8b220027a75fb 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.test.js
@@ -53,24 +53,6 @@ describe('', () => {
expect(component.find('JobTableUi').length).toBeTruthy();
});
- describe('route query params change', () => {
- it('should call the "openDetailPanel()" prop each time the "job" query params changes', () => {
- const openDetailPanel = jest.fn();
- const jobId = 'foo';
- const { setProps } = initTestBed({ openDetailPanel });
-
- expect(openDetailPanel.mock.calls.length).toBe(0);
-
- setProps({
- history: { location: { search: `?job=${jobId}` } },
- openDetailPanel,
- });
-
- expect(openDetailPanel.mock.calls.length).toBe(1);
- expect(openDetailPanel.mock.calls[0][0]).toEqual(jobId);
- });
- });
-
describe('when there is an API error', () => {
const { exists, find } = initTestBed({
jobLoadError: {
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
index 222ee6822ed8e..192a0413355b8 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_table/job_table.js
@@ -378,7 +378,7 @@ export class JobTableUi extends Component {
{jobs.length > 0 ? (
-
+ trackUserAction(actionType));
- return request;
+ return request.then(response => {
+ trackUserAction(actionType);
+ // We return the response immediately without waiting for the tracking request to resolve,
+ // to avoid adding additional latency.
+ return response;
+ });
}
diff --git a/x-pack/plugins/rollup/public/crud_app/store/index.js b/x-pack/plugins/rollup/public/crud_app/store/index.js
index bd072ee94d022..f0be8e5e400fb 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/index.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { rollupJobsStore } from './store';
+export { rollupJobsStore, createRollupJobsStore } from './store';
diff --git a/x-pack/plugins/rollup/public/crud_app/store/store.js b/x-pack/plugins/rollup/public/crud_app/store/store.js
index b5644d7c3bb27..418b781ef6e4d 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/store.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/store.js
@@ -13,7 +13,7 @@ import {
detailPanel,
} from './middleware';
-function createRollupJobsStore(initialState = {}) {
+export function createRollupJobsStore(initialState = {}) {
const enhancers = [ applyMiddleware(thunk, detailPanel) ];
window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__());
diff --git a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js b/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js
index 2e62e6cff82a3..b6387502abe2f 100644
--- a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js
+++ b/x-pack/plugins/rollup/server/client/elasticsearch_rollup.js
@@ -91,6 +91,12 @@ export const elasticsearchJsPlugin = (Client, config, components) => {
});
rollup.stopJob = ca({
+ params: {
+ waitForCompletion: {
+ type: 'boolean',
+ name: 'wait_for_completion'
+ }
+ },
urls: [
{
fmt: '/_rollup/job/<%=id%>/_stop',
diff --git a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js b/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js
index 45953b04143b0..90ec30fd05b5c 100644
--- a/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js
+++ b/x-pack/plugins/rollup/server/lib/__tests__/jobs_compatibility.js
@@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { areJobsCompatible, mergeJobConfigurations } from '../jobs_compatibility';
import { jobs } from './fixtures';
diff --git a/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js
index 19a7b56759269..394c2c4735c0c 100644
--- a/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js
+++ b/x-pack/plugins/rollup/server/lib/check_license/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js
index 443744ccb0cc8..f9c102be7a1ff 100644
--- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js
+++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_custom_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapCustomError } from '../wrap_custom_error';
describe('wrap_custom_error', () => {
diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js
index b8d59590ebf33..f3237563edb45 100644
--- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js
+++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_es_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapEsError } from '../wrap_es_error';
describe('wrap_es_error', () => {
diff --git a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
index 6d6a336417bef..85e0b2b3033ad 100644
--- a/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
+++ b/x-pack/plugins/rollup/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { wrapUnknownError } from '../wrap_unknown_error';
describe('wrap_unknown_error', () => {
diff --git a/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
index d50ff9480d3e4..76fdf7b36c3d0 100644
--- a/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
+++ b/x-pack/plugins/rollup/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { isEsErrorFactory } from '../is_es_error_factory';
import { set } from 'lodash';
diff --git a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index ffbbd1395a418..dc641bef91085 100644
--- a/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/rollup/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
describe('license_pre_routing_factory', () => {
diff --git a/x-pack/plugins/rollup/server/routes/api/jobs.js b/x-pack/plugins/rollup/server/routes/api/jobs.js
index ac4ef3731dbfe..24418dae8e43d 100644
--- a/x-pack/plugins/rollup/server/routes/api/jobs.js
+++ b/x-pack/plugins/rollup/server/routes/api/jobs.js
@@ -75,6 +75,7 @@ export function registerJobsRoute(server) {
handler: async (request) => {
try {
const { jobIds } = request.payload;
+
const callWithRequest = callWithRequestFactory(server, request);
return await Promise.all(jobIds.map(id => callWithRequest('rollup.startJob', { id })))
.then(() => ({ success: true }));
@@ -107,9 +108,17 @@ export function registerJobsRoute(server) {
handler: async (request) => {
try {
const { jobIds } = request.payload;
+ // For our API integration tests we need to wait for the jobs to be stopped
+ // in order to be able to delete them sequencially.
+ const { waitForCompletion } = request.query;
const callWithRequest = callWithRequestFactory(server, request);
- return await Promise.all(jobIds.map(id => callWithRequest('rollup.stopJob', { id })))
+
+ const stopRollupJob = id => callWithRequest('rollup.stopJob', { id, waitForCompletion: waitForCompletion === 'true' });
+
+ return await Promise
+ .all(jobIds.map(stopRollupJob))
.then(() => ({ success: true }));
+
} catch(err) {
if (isEsError(err)) {
return wrapEsError(err);
@@ -129,6 +138,7 @@ export function registerJobsRoute(server) {
handler: async (request) => {
try {
const { jobIds } = request.payload;
+
const callWithRequest = callWithRequestFactory(server, request);
return await Promise.all(jobIds.map(id => callWithRequest('rollup.deleteJob', { id })))
.then(() => ({ success: true }));
diff --git a/x-pack/plugins/searchprofiler/README.md b/x-pack/plugins/searchprofiler/README.md
index 54bbd1203235d..1dec1bb4e5450 100644
--- a/x-pack/plugins/searchprofiler/README.md
+++ b/x-pack/plugins/searchprofiler/README.md
@@ -19,7 +19,7 @@ If you have installed this somewhere other than via x-plugins, and next to the k
To run the server tests, change into `x-plugins/kibana` and run:
```bash
-mocha --debug --compilers js:babel/register plugins/profiler/**/__tests__/**/*.js
+mocha --debug --compilers js:@babel/register plugins/profiler/**/__tests__/**/*.js
```
diff --git a/x-pack/plugins/searchprofiler/public/__tests__/app_util.js b/x-pack/plugins/searchprofiler/public/__tests__/app_util.js
index 2c085296d0dbb..164e7394dead7 100644
--- a/x-pack/plugins/searchprofiler/public/__tests__/app_util.js
+++ b/x-pack/plugins/searchprofiler/public/__tests__/app_util.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { checkForParseErrors } from '../app_util.js';
describe('checkForParseErrors', function () {
diff --git a/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js b/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js
index 745cfb94ac811..6da9a452e5e3c 100644
--- a/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js
+++ b/x-pack/plugins/searchprofiler/public/directives/profile_tree/__tests__/profile_tree.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import * as util from '../util.js';
import { normalized, breakdown } from './fixtures/breakdown.js';
import { inputTimes, normalizedTimes } from './fixtures/normalize_times.js';
diff --git a/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js b/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js
index 3519c411951f0..85208495fc18e 100644
--- a/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js
+++ b/x-pack/plugins/searchprofiler/public/filters/__tests__/ns_to_pretty.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { nsToPretty } from '../ns_to_pretty.js';
describe('nsToPretty', function () {
diff --git a/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js b/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js
index 17dacc31680be..f1e19b61cbe2b 100644
--- a/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js
+++ b/x-pack/plugins/searchprofiler/server/lib/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { set } from 'lodash';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/security/public/lib/__tests__/parse_next.js b/x-pack/plugins/security/public/lib/__tests__/parse_next.js
index 615c348c33b1c..7516433c77f83 100644
--- a/x-pack/plugins/security/public/lib/__tests__/parse_next.js
+++ b/x-pack/plugins/security/public/lib/__tests__/parse_next.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { parseNext } from '../parse_next';
describe('parseNext', () => {
diff --git a/x-pack/plugins/security/public/lib/__tests__/util.js b/x-pack/plugins/security/public/lib/__tests__/util.js
index 766c384456aa6..3f7d8aea53a85 100644
--- a/x-pack/plugins/security/public/lib/__tests__/util.js
+++ b/x-pack/plugins/security/public/lib/__tests__/util.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { toggle, toggleSort } from '../../../public/lib/util';
describe('util', () => {
diff --git a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap
index 5c38e3f28c4d0..19dacf984f5dc 100644
--- a/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap
+++ b/x-pack/plugins/security/public/views/management/edit_role/components/privileges/kibana/__snapshots__/privilege_callout_warning.test.tsx.snap
@@ -179,9 +179,7 @@ exports[`PrivilegeCalloutWarning renders without crashing 1`] = `
>
- grants full access to all
- spaces. To customize privileges for individual spaces, the minimum privilege must be
- either
+ grants full access to all spaces. To customize privileges for individual spaces, the minimum privilege must be either
renders without crashing 1`] = `
>
with user profile disabling "manageSpaces" re
LoginAttempt; getBasePath: () => string };
}
diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js
index c511eca58ac4d..32bc341ce58fa 100644
--- a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js
+++ b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js
@@ -5,7 +5,7 @@
*/
import Boom from 'boom';
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { hFixture } from './__fixtures__/h';
diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js b/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js
index 8f3c3acede0be..d54d53d12142b 100644
--- a/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js
+++ b/x-pack/plugins/security/server/lib/__tests__/auth_scope_service.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { AuthScopeService } from '../auth_scope_service';
diff --git a/x-pack/plugins/security/server/lib/__tests__/check_license.js b/x-pack/plugins/security/server/lib/__tests__/check_license.js
index 365cf399519d9..a2bf1faf031e3 100644
--- a/x-pack/plugins/security/server/lib/__tests__/check_license.js
+++ b/x-pack/plugins/security/server/lib/__tests__/check_license.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { checkLicense } from '../check_license';
diff --git a/x-pack/plugins/security/server/lib/__tests__/errors.js b/x-pack/plugins/security/server/lib/__tests__/errors.js
deleted file mode 100644
index 5ec42f7d30f0c..0000000000000
--- a/x-pack/plugins/security/server/lib/__tests__/errors.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-import expect from 'expect.js';
-
-import * as errors from '../errors';
-
-describe('lib/errors', function () {
- describe('#wrapError', () => {
- it('returns given object', () => {
- const err = new Error();
- const returned = errors.wrapError(err);
- expect(returned).to.equal(err);
- });
- it('error becomes boom error', () => {
- const err = new Error();
- errors.wrapError(err);
- expect(err.isBoom).to.equal(true);
- });
- it('defaults output.statusCode to 500', () => {
- const err = new Error();
- errors.wrapError(err);
- expect(err.output.statusCode).to.equal(500);
- });
- it('sets output.statusCode to .status if given', () => {
- const err = new Error();
- err.status = 400;
- errors.wrapError(err);
- expect(err.output.statusCode).to.equal(400);
- });
- it('defaults message to "Internal Server Error"', () => {
- const err = new Error();
- errors.wrapError(err);
- expect(err.message).to.equal('Internal Server Error');
- });
- it('sets custom message if a 400 level error', () => {
- const err = new Error('wat');
- err.status = 499;
- errors.wrapError(err);
- expect(err.output.payload.message).to.equal('wat');
- });
- });
-});
diff --git a/x-pack/plugins/security/server/lib/__tests__/parse_next.js b/x-pack/plugins/security/server/lib/__tests__/parse_next.js
index 615c348c33b1c..7516433c77f83 100644
--- a/x-pack/plugins/security/server/lib/__tests__/parse_next.js
+++ b/x-pack/plugins/security/server/lib/__tests__/parse_next.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import { parseNext } from '../parse_next';
describe('parseNext', () => {
diff --git a/x-pack/plugins/security/server/lib/__tests__/validate_config.js b/x-pack/plugins/security/server/lib/__tests__/validate_config.js
index 26d84f6f5559b..c5a96bc8253f1 100644
--- a/x-pack/plugins/security/server/lib/__tests__/validate_config.js
+++ b/x-pack/plugins/security/server/lib/__tests__/validate_config.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { validateConfig } from '../validate_config';
diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js
index de5061fc65ba2..58cffca347e35 100644
--- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js
+++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import Boom from 'boom';
@@ -28,11 +28,10 @@ describe('Authenticator', () => {
session = sinon.createStubInstance(Session);
config = { get: sinon.stub() };
- cluster = { callWithRequest: sinon.stub() };
// Cluster is returned by `getClient` function that is wrapped into `once` making cluster
// a static singleton, so we should use sandbox to set/reset its behavior between tests.
- cluster = sinon.stub({ callWithRequest() {} });
+ cluster = sinon.stub({ callWithRequest() {}, callWithInternalUser() {} });
sandbox.stub(ClientShield, 'getClient').returns(cluster);
server.config.returns(config);
@@ -357,6 +356,35 @@ describe('Authenticator', () => {
sinon.assert.calledWithExactly(session.clear, notSystemAPIRequest);
});
+ it('clears session if provider requested it via setting state to `null`.', async () => {
+ // Use `token` provider for this test as it's the only one that does what we want.
+ config.get.withArgs('xpack.security.authProviders').returns(['token']);
+ await initAuthenticator(server);
+ authenticate = server.expose.withArgs('authenticate').lastCall.args[1];
+
+ const request = requestFixture({ headers: { xCustomHeader: 'xxx' } });
+
+ session.get.withArgs(request).resolves({
+ state: { accessToken: 'access-xxx', refreshToken: 'refresh-xxx' },
+ provider: 'token'
+ });
+
+ session.clear.resolves();
+
+ cluster.callWithRequest
+ .withArgs(request).rejects({ statusCode: 401 });
+
+ cluster.callWithInternalUser.withArgs('shield.getAccessToken').rejects(
+ Boom.badRequest('refresh token expired')
+ );
+
+ const authenticationResult = await authenticate(request);
+ expect(authenticationResult.redirected()).to.be(true);
+
+ sinon.assert.calledOnce(session.clear);
+ sinon.assert.calledWithExactly(session.clear, request);
+ });
+
it('does not clear session if provider failed to authenticate request with non-401 reason with active session.',
async () => {
const systemAPIRequest = requestFixture({ headers: { xCustomHeader: 'xxx' } });
diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js
index 832adef2439ee..4a47fe12c68bf 100644
--- a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js
+++ b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
import { serverFixture } from '../../__tests__/__fixtures__/server';
diff --git a/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts b/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts
index d67136e21a5c5..870e843a829b0 100644
--- a/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts
+++ b/x-pack/plugins/security/server/lib/authentication/authentication_result.test.ts
@@ -123,4 +123,96 @@ describe('AuthenticationResult', () => {
expect(authenticationResult.error).toBeUndefined();
});
});
+
+ describe('shouldUpdateState', () => {
+ it('always `false` for `failed`', () => {
+ expect(AuthenticationResult.failed(new Error('error')).shouldUpdateState()).toBe(false);
+ });
+
+ it('always `false` for `notHandled`', () => {
+ expect(AuthenticationResult.notHandled().shouldUpdateState()).toBe(false);
+ });
+
+ it('depends on `state` for `redirected`.', () => {
+ const mockURL = 'some-url';
+ expect(AuthenticationResult.redirectTo(mockURL, 'string').shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.redirectTo(mockURL, 0).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.redirectTo(mockURL, true).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.redirectTo(mockURL, false).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldUpdateState()).toBe(
+ true
+ );
+ expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldUpdateState()).toBe(
+ true
+ );
+
+ expect(AuthenticationResult.redirectTo(mockURL).shouldUpdateState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, undefined).shouldUpdateState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, null).shouldUpdateState()).toBe(false);
+ });
+
+ it('depends on `state` for `succeeded`.', () => {
+ const mockUser = { username: 'u' };
+ expect(AuthenticationResult.succeeded(mockUser, 'string').shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.succeeded(mockUser, 0).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.succeeded(mockUser, true).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.succeeded(mockUser, false).shouldUpdateState()).toBe(true);
+ expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldUpdateState()).toBe(
+ true
+ );
+ expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldUpdateState()).toBe(
+ true
+ );
+
+ expect(AuthenticationResult.succeeded(mockUser).shouldUpdateState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, undefined).shouldUpdateState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, null).shouldUpdateState()).toBe(false);
+ });
+ });
+
+ describe('shouldClearState', () => {
+ it('always `false` for `failed`', () => {
+ expect(AuthenticationResult.failed(new Error('error')).shouldClearState()).toBe(false);
+ });
+
+ it('always `false` for `notHandled`', () => {
+ expect(AuthenticationResult.notHandled().shouldClearState()).toBe(false);
+ });
+
+ it('depends on `state` for `redirected`.', () => {
+ const mockURL = 'some-url';
+ expect(AuthenticationResult.redirectTo(mockURL, null).shouldClearState()).toBe(true);
+
+ expect(AuthenticationResult.redirectTo(mockURL).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, undefined).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, 'string').shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, 0).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, true).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, false).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldClearState()).toBe(
+ false
+ );
+ expect(AuthenticationResult.redirectTo(mockURL, { prop: 'object' }).shouldClearState()).toBe(
+ false
+ );
+ });
+
+ it('depends on `state` for `succeeded`.', () => {
+ const mockUser = { username: 'u' };
+ expect(AuthenticationResult.succeeded(mockUser, null).shouldClearState()).toBe(true);
+
+ expect(AuthenticationResult.succeeded(mockUser).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, undefined).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, 'string').shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, 0).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, true).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, false).shouldClearState()).toBe(false);
+ expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldClearState()).toBe(
+ false
+ );
+ expect(AuthenticationResult.succeeded(mockUser, { prop: 'object' }).shouldClearState()).toBe(
+ false
+ );
+ });
+ });
});
diff --git a/x-pack/plugins/security/server/lib/authentication/authentication_result.ts b/x-pack/plugins/security/server/lib/authentication/authentication_result.ts
index 19df30ef84ae9..b6a0d3ba1c21a 100644
--- a/x-pack/plugins/security/server/lib/authentication/authentication_result.ts
+++ b/x-pack/plugins/security/server/lib/authentication/authentication_result.ts
@@ -160,4 +160,19 @@ export class AuthenticationResult {
public redirected() {
return this.status === AuthenticationResultStatus.Redirected;
}
+
+ /**
+ * Checks whether authentication result implies state update.
+ */
+ public shouldUpdateState() {
+ // State shouldn't be updated in case it wasn't set or was specifically set to `null`.
+ return this.options.state != null;
+ }
+
+ /**
+ * Checks whether authentication result implies state clearing.
+ */
+ public shouldClearState() {
+ return this.options.state === null;
+ }
}
diff --git a/x-pack/plugins/security/server/lib/authentication/authenticator.js b/x-pack/plugins/security/server/lib/authentication/authenticator.js
index 2cf2d0e1e0f8b..f6dacb308e62d 100644
--- a/x-pack/plugins/security/server/lib/authentication/authenticator.js
+++ b/x-pack/plugins/security/server/lib/authentication/authenticator.js
@@ -6,6 +6,7 @@
import { getClient } from '../../../../../server/lib/get_client_shield';
import { AuthScopeService } from '../auth_scope_service';
+import { getErrorStatusCode } from '../errors';
import { BasicAuthenticationProvider } from './providers/basic';
import { SAMLAuthenticationProvider } from './providers/saml';
import { TokenAuthenticationProvider } from './providers/token';
@@ -49,15 +50,6 @@ function getProviderOptions(server) {
};
}
-/**
- * Extracts error code from Boom and Elasticsearch "native" errors.
- * @param {Error} error Error instance to extract status code from.
- * @returns {number}
- */
-function getErrorStatusCode(error) {
- return error.isBoom ? error.output.statusCode : error.statusCode;
-}
-
/**
* Authenticator is responsible for authentication of the request using chain of
* authentication providers. The chain is essentially a prioritized list of configured
@@ -149,21 +141,24 @@ class Authenticator {
ownsSession ? existingSession.state : null
);
- if (ownsSession || authenticationResult.state) {
+ if (ownsSession || authenticationResult.shouldUpdateState()) {
// If authentication succeeds or requires redirect we should automatically extend existing user session,
// unless authentication has been triggered by a system API request. In case provider explicitly returns new
// state we should store it in the session regardless of whether it's a system API request or not.
const sessionCanBeUpdated = (authenticationResult.succeeded() || authenticationResult.redirected())
- && (authenticationResult.state || !isSystemApiRequest);
-
- // If provider owned the session, but failed to authenticate anyway, that likely means
- // that session is not valid and we should clear it.
- if (authenticationResult.failed() && getErrorStatusCode(authenticationResult.error) === 401) {
+ && (authenticationResult.shouldUpdateState() || !isSystemApiRequest);
+
+ // If provider owned the session, but failed to authenticate anyway, that likely means that
+ // session is not valid and we should clear it. Also provider can specifically ask to clear
+ // session by setting it to `null` even if authentication attempt didn't fail.
+ if (authenticationResult.shouldClearState() || (
+ authenticationResult.failed() && getErrorStatusCode(authenticationResult.error) === 401)
+ ) {
await this._session.clear(request);
} else if (sessionCanBeUpdated) {
await this._session.set(
request,
- authenticationResult.state
+ authenticationResult.shouldUpdateState()
? { state: authenticationResult.state, provider: providerType }
: existingSession
);
diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js
index 902db0fc1a2dc..6c99a78847b6d 100644
--- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js
+++ b/x-pack/plugins/security/server/lib/authentication/providers/__tests__/token.js
@@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
+import expect from '@kbn/expect';
import sinon from 'sinon';
+import { errors } from 'elasticsearch';
import { requestFixture } from '../../../__tests__/__fixtures__/request';
import { LoginAttempt } from '../../login_attempt';
import { TokenAuthenticationProvider } from '../token';
@@ -136,7 +137,7 @@ describe('TokenAuthenticationProvider', () => {
callWithRequest
.withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
- .returns(Promise.reject({ body: { error: { reason: 'token expired' } } }));
+ .rejects({ statusCode: 401 });
callWithInternalUser
.withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
@@ -175,26 +176,6 @@ describe('TokenAuthenticationProvider', () => {
expect(authenticationResult.notHandled()).to.be(true);
});
- it('fails if state contains invalid credentials.', async () => {
- const request = requestFixture();
- const accessToken = 'foo';
- const authorization = `Bearer ${accessToken}`;
-
- const authenticationError = new Error('Forbidden');
- callWithRequest
- .withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate')
- .returns(Promise.reject(authenticationError));
-
- const authenticationResult = await provider.authenticate(request, { accessToken });
-
- expect(request.headers).to.not.have.property('authorization');
- expect(authenticationResult.failed()).to.be(true);
- expect(authenticationResult.user).to.be.eql(undefined);
- expect(authenticationResult.state).to.be.eql(undefined);
- expect(authenticationResult.error).to.be.eql(authenticationError);
- sinon.assert.calledOnce(callWithRequest);
- });
-
it('authenticates only via `authorization` header even if state is available.', async () => {
const accessToken = 'foo';
const authorization = `Bearer ${accessToken}`;
@@ -262,14 +243,14 @@ describe('TokenAuthenticationProvider', () => {
expect(authenticationResult.error).to.be.eql(authenticationError);
});
- it('fails when header contains a rejected token', async () => {
+ it('fails if authentication with token from header fails with unknown error', async () => {
const authorization = `Bearer foo`;
const request = requestFixture({ headers: { authorization } });
- const authenticationError = new Error('Forbidden');
+ const authenticationError = new errors.InternalServerError('something went wrong');
callWithRequest
.withArgs(request, 'shield.authenticate')
- .returns(Promise.reject(authenticationError));
+ .rejects(authenticationError);
const authenticationResult = await provider.authenticate(request);
@@ -281,14 +262,14 @@ describe('TokenAuthenticationProvider', () => {
expect(authenticationResult.error).to.be.eql(authenticationError);
});
- it('fails when session contains a rejected token', async () => {
+ it('fails if authentication with token from state fails with unknown error.', async () => {
const accessToken = 'foo';
const request = requestFixture();
- const authenticationError = new Error('Forbidden');
+ const authenticationError = new errors.InternalServerError('something went wrong');
callWithRequest
- .withArgs(request, 'shield.authenticate')
- .returns(Promise.reject(authenticationError));
+ .withArgs(sinon.match({ headers: { authorization: `Bearer ${accessToken}` } }), 'shield.authenticate')
+ .rejects(authenticationError);
const authenticationResult = await provider.authenticate(request, { accessToken });
@@ -301,17 +282,17 @@ describe('TokenAuthenticationProvider', () => {
expect(authenticationResult.error).to.be.eql(authenticationError);
});
- it('fails if token refresh is rejected', async () => {
+ it('fails if token refresh is rejected with unknown error', async () => {
const request = requestFixture();
callWithRequest
.withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
- .returns(Promise.reject({ body: { error: { reason: 'token expired' } } }));
+ .rejects({ statusCode: 401 });
- const authenticationError = new Error('failed to refresh token');
+ const refreshError = new errors.InternalServerError('failed to refresh token');
callWithInternalUser
.withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
- .returns(Promise.reject(authenticationError));
+ .rejects(refreshError);
const accessToken = 'foo';
const refreshToken = 'bar';
@@ -324,7 +305,88 @@ describe('TokenAuthenticationProvider', () => {
expect(authenticationResult.failed()).to.be(true);
expect(authenticationResult.user).to.be.eql(undefined);
expect(authenticationResult.state).to.be.eql(undefined);
- expect(authenticationResult.error).to.be.eql(authenticationError);
+ expect(authenticationResult.error).to.be.eql(refreshError);
+ });
+
+ it('redirects non-AJAX requests to /login and clears session if token document is missing', async () => {
+ const request = requestFixture({ path: '/some-path' });
+
+ callWithRequest
+ .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
+ .rejects({
+ statusCode: 500,
+ body: { error: { reason: 'token document is missing and must be present' } },
+ });
+
+ callWithInternalUser
+ .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
+ .rejects(new errors.BadRequest('failed to refresh token'));
+
+ const accessToken = 'foo';
+ const refreshToken = 'bar';
+ const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken });
+
+ sinon.assert.calledOnce(callWithRequest);
+ sinon.assert.calledOnce(callWithInternalUser);
+
+ expect(request.headers).to.not.have.property('authorization');
+ expect(authenticationResult.redirected()).to.be(true);
+ expect(authenticationResult.redirectURL).to.be('/base-path/login?next=%2Fsome-path');
+ expect(authenticationResult.user).to.be.eql(undefined);
+ expect(authenticationResult.state).to.be.eql(null);
+ expect(authenticationResult.error).to.be.eql(undefined);
+ });
+
+ it('redirects non-AJAX requests to /login and clears session if token refresh fails with 400 error', async () => {
+ const request = requestFixture({ path: '/some-path' });
+
+ callWithRequest
+ .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
+ .rejects({ statusCode: 401 });
+
+ callWithInternalUser
+ .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
+ .rejects(new errors.BadRequest('failed to refresh token'));
+
+ const accessToken = 'foo';
+ const refreshToken = 'bar';
+ const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken });
+
+ sinon.assert.calledOnce(callWithRequest);
+ sinon.assert.calledOnce(callWithInternalUser);
+
+ expect(request.headers).to.not.have.property('authorization');
+ expect(authenticationResult.redirected()).to.be(true);
+ expect(authenticationResult.redirectURL).to.be('/base-path/login?next=%2Fsome-path');
+ expect(authenticationResult.user).to.be.eql(undefined);
+ expect(authenticationResult.state).to.be.eql(null);
+ expect(authenticationResult.error).to.be.eql(undefined);
+ });
+
+ it('does not redirect AJAX requests if token refresh fails with 400 error', async () => {
+ const request = requestFixture({ headers: { 'kbn-xsrf': 'xsrf' }, path: '/some-path' });
+
+ callWithRequest
+ .withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
+ .rejects({ statusCode: 401 });
+
+ const authenticationError = new errors.BadRequest('failed to refresh token');
+ callWithInternalUser
+ .withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
+ .rejects(authenticationError);
+
+ const accessToken = 'foo';
+ const refreshToken = 'bar';
+ const authenticationResult = await provider.authenticate(request, { accessToken, refreshToken });
+
+ sinon.assert.calledOnce(callWithRequest);
+ sinon.assert.calledOnce(callWithInternalUser);
+
+ expect(request.headers).to.not.have.property('authorization');
+ expect(authenticationResult.failed()).to.be(true);
+ expect(authenticationResult.error).to.be(authenticationError);
+ expect(authenticationResult.user).to.be.eql(undefined);
+ expect(authenticationResult.state).to.be.eql(undefined);
});
it('fails if new access token is rejected after successful refresh', async () => {
@@ -332,16 +394,16 @@ describe('TokenAuthenticationProvider', () => {
callWithRequest
.withArgs(sinon.match({ headers: { authorization: 'Bearer foo' } }), 'shield.authenticate')
- .returns(Promise.reject({ body: { error: { reason: 'token expired' } } }));
+ .rejects({ statusCode: 401 });
callWithInternalUser
.withArgs('shield.getAccessToken', { body: { grant_type: 'refresh_token', refresh_token: 'bar' } })
.returns(Promise.resolve({ access_token: 'newfoo', refresh_token: 'newbar' }));
- const authenticationError = new Error('Some error');
+ const authenticationError = new errors.AuthenticationException('Some error');
callWithRequest
.withArgs(sinon.match({ headers: { authorization: 'Bearer newfoo' } }), 'shield.authenticate')
- .returns(Promise.reject(authenticationError));
+ .rejects(authenticationError);
const accessToken = 'foo';
const refreshToken = 'bar';
diff --git a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js b/x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts
similarity index 56%
rename from x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js
rename to x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts
index 0226c9b36b5c9..ebe984e41a2c5 100644
--- a/x-pack/plugins/security/server/lib/authentication/providers/__tests__/basic.js
+++ b/x-pack/plugins/security/server/lib/authentication/providers/basic.test.ts
@@ -4,30 +4,31 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import expect from 'expect.js';
import sinon from 'sinon';
-import { requestFixture } from '../../../__tests__/__fixtures__/request';
-import { LoginAttempt } from '../../login_attempt';
-import { BasicAuthenticationProvider, BasicCredentials } from '../basic';
+import { requestFixture } from '../../__tests__/__fixtures__/request';
+import { LoginAttempt } from '../login_attempt';
+import { BasicAuthenticationProvider, BasicCredentials } from './basic';
-function generateAuthorizationHeader(username, password) {
- const { headers: { authorization } } = BasicCredentials.decorateRequest(
- requestFixture(), username, password
- );
+function generateAuthorizationHeader(username: string, password: string) {
+ const {
+ headers: { authorization },
+ } = BasicCredentials.decorateRequest(requestFixture(), username, password);
return authorization;
}
describe('BasicAuthenticationProvider', () => {
describe('`authenticate` method', () => {
- let provider;
- let callWithRequest;
+ let provider: BasicAuthenticationProvider;
+ let callWithRequest: sinon.SinonStub;
beforeEach(() => {
callWithRequest = sinon.stub();
provider = new BasicAuthenticationProvider({
- client: { callWithRequest },
- log() {},
- basePath: '/base-path'
+ client: { callWithRequest } as any,
+ log() {
+ // no-op
+ },
+ basePath: '/base-path',
});
});
@@ -39,30 +40,28 @@ describe('BasicAuthenticationProvider', () => {
null
);
- expect(authenticationResult.notHandled()).to.be(true);
+ expect(authenticationResult.notHandled()).toBe(true);
});
it('redirects non-AJAX requests that can not be authenticated to the login page.', async () => {
const authenticationResult = await provider.authenticate(
- requestFixture({ path: '/some-path # that needs to be encoded', basePath: '/s/foo' }),
+ requestFixture({
+ path: '/some-path # that needs to be encoded',
+ basePath: '/s/foo',
+ }),
null
);
- expect(authenticationResult.redirected()).to.be(true);
- expect(authenticationResult.redirectURL).to.be(
+ expect(authenticationResult.redirected()).toBe(true);
+ expect(authenticationResult.redirectURL).toBe(
'/base-path/login?next=%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded'
);
});
- it('does not handle authentication if state exists, but authorization property is missing.',
- async () => {
- const authenticationResult = await provider.authenticate(
- requestFixture(),
- {}
- );
-
- expect(authenticationResult.notHandled()).to.be(true);
- });
+ it('does not handle authentication if state exists, but authorization property is missing.', async () => {
+ const authenticationResult = await provider.authenticate(requestFixture(), {});
+ expect(authenticationResult.notHandled()).toBe(true);
+ });
it('succeeds with valid login attempt and stores in session', async () => {
const user = { username: 'user' };
@@ -70,17 +69,15 @@ describe('BasicAuthenticationProvider', () => {
const request = requestFixture();
const loginAttempt = new LoginAttempt();
loginAttempt.setCredentials('user', 'password');
- request.loginAttempt.returns(loginAttempt);
+ (request.loginAttempt as sinon.SinonStub).returns(loginAttempt);
- callWithRequest
- .withArgs(request, 'shield.authenticate')
- .returns(Promise.resolve(user));
+ callWithRequest.withArgs(request, 'shield.authenticate').resolves(user);
const authenticationResult = await provider.authenticate(request);
- expect(authenticationResult.succeeded()).to.be(true);
- expect(authenticationResult.user).to.be.eql(user);
- expect(authenticationResult.state).to.be.eql({ authorization });
+ expect(authenticationResult.succeeded()).toBe(true);
+ expect(authenticationResult.user).toEqual(user);
+ expect(authenticationResult.state).toEqual({ authorization });
sinon.assert.calledOnce(callWithRequest);
});
@@ -88,14 +85,12 @@ describe('BasicAuthenticationProvider', () => {
const request = BasicCredentials.decorateRequest(requestFixture(), 'user', 'password');
const user = { username: 'user' };
- callWithRequest
- .withArgs(request, 'shield.authenticate')
- .returns(Promise.resolve(user));
+ callWithRequest.withArgs(request, 'shield.authenticate').resolves(user);
const authenticationResult = await provider.authenticate(request);
- expect(authenticationResult.succeeded()).to.be(true);
- expect(authenticationResult.user).to.be.eql(user);
+ expect(authenticationResult.succeeded()).toBe(true);
+ expect(authenticationResult.user).toEqual(user);
sinon.assert.calledOnce(callWithRequest);
});
@@ -103,13 +98,13 @@ describe('BasicAuthenticationProvider', () => {
const request = BasicCredentials.decorateRequest(requestFixture(), 'user', 'password');
const user = { username: 'user' };
- callWithRequest
- .withArgs(request, 'shield.authenticate')
- .returns(Promise.resolve(user));
+ callWithRequest.withArgs(request, 'shield.authenticate').resolves(user);
const authenticationResult = await provider.authenticate(request);
- expect(authenticationResult.state).not.to.eql({ authorization: request.headers.authorization });
+ expect(authenticationResult.state).not.toEqual({
+ authorization: request.headers.authorization,
+ });
});
it('succeeds if only state is available.', async () => {
@@ -119,13 +114,13 @@ describe('BasicAuthenticationProvider', () => {
callWithRequest
.withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate')
- .returns(Promise.resolve(user));
+ .resolves(user);
const authenticationResult = await provider.authenticate(request, { authorization });
- expect(authenticationResult.succeeded()).to.be(true);
- expect(authenticationResult.user).to.be.eql(user);
- expect(authenticationResult.state).to.be.eql(undefined);
+ expect(authenticationResult.succeeded()).toBe(true);
+ expect(authenticationResult.user).toEqual(user);
+ expect(authenticationResult.state).toBeUndefined();
sinon.assert.calledOnce(callWithRequest);
});
@@ -136,8 +131,8 @@ describe('BasicAuthenticationProvider', () => {
const authenticationResult = await provider.authenticate(request, { authorization });
sinon.assert.notCalled(callWithRequest);
- expect(request.headers.authorization).to.be('Bearer ***');
- expect(authenticationResult.notHandled()).to.be(true);
+ expect(request.headers.authorization).toBe('Bearer ***');
+ expect(authenticationResult.notHandled()).toBe(true);
});
it('fails if state contains invalid credentials.', async () => {
@@ -147,15 +142,15 @@ describe('BasicAuthenticationProvider', () => {
const authenticationError = new Error('Forbidden');
callWithRequest
.withArgs(sinon.match({ headers: { authorization } }), 'shield.authenticate')
- .returns(Promise.reject(authenticationError));
+ .rejects(authenticationError);
const authenticationResult = await provider.authenticate(request, { authorization });
- expect(request.headers).to.not.have.property('authorization');
- expect(authenticationResult.failed()).to.be(true);
- expect(authenticationResult.user).to.be.eql(undefined);
- expect(authenticationResult.state).to.be.eql(undefined);
- expect(authenticationResult.error).to.be.eql(authenticationError);
+ expect(request.headers).not.toHaveProperty('authorization');
+ expect(authenticationResult.failed()).toBe(true);
+ expect(authenticationResult.user).toBeUndefined();
+ expect(authenticationResult.state).toBeUndefined();
+ expect(authenticationResult.error).toBe(authenticationError);
sinon.assert.calledOnce(callWithRequest);
});
@@ -165,55 +160,68 @@ describe('BasicAuthenticationProvider', () => {
const authorization = generateAuthorizationHeader('user1', 'password2');
// GetUser will be called with request's `authorization` header.
- callWithRequest.withArgs(request, 'shield.authenticate').returns(Promise.resolve(user));
+ callWithRequest.withArgs(request, 'shield.authenticate').resolves(user);
const authenticationResult = await provider.authenticate(request, { authorization });
- expect(authenticationResult.succeeded()).to.be(true);
- expect(authenticationResult.user).to.be.eql(user);
- expect(authenticationResult.state).not.to.eql({ authorization: request.headers.authorization });
+ expect(authenticationResult.succeeded()).toBe(true);
+ expect(authenticationResult.user).toEqual(user);
+ expect(authenticationResult.state).not.toEqual({
+ authorization: request.headers.authorization,
+ });
sinon.assert.calledOnce(callWithRequest);
});
});
describe('`deauthenticate` method', () => {
- let provider;
+ let provider: BasicAuthenticationProvider;
beforeEach(() => {
provider = new BasicAuthenticationProvider({
- client: { callWithRequest: sinon.stub() },
- basePath: '/base-path'
+ client: { callWithRequest: sinon.stub() } as any,
+ log() {
+ // no-op
+ },
+ basePath: '/base-path',
});
});
it('always redirects to the login page.', async () => {
const request = requestFixture();
const deauthenticateResult = await provider.deauthenticate(request);
- expect(deauthenticateResult.redirected()).to.be(true);
- expect(deauthenticateResult.redirectURL).to.be('/base-path/login');
+ expect(deauthenticateResult.redirected()).toBe(true);
+ expect(deauthenticateResult.redirectURL).toBe('/base-path/login');
});
it('passes query string parameters to the login page.', async () => {
const request = requestFixture({ search: '?next=%2Fapp%2Fml&msg=SESSION_EXPIRED' });
const deauthenticateResult = await provider.deauthenticate(request);
- expect(deauthenticateResult.redirected()).to.be(true);
- expect(deauthenticateResult.redirectURL).to.be('/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED');
+ expect(deauthenticateResult.redirected()).toBe(true);
+ expect(deauthenticateResult.redirectURL).toBe(
+ '/base-path/login?next=%2Fapp%2Fml&msg=SESSION_EXPIRED'
+ );
});
});
describe('BasicCredentials', () => {
it('`decorateRequest` fails if username or password is not provided.', () => {
- expect(() => BasicCredentials.decorateRequest()).to
- .throwError(/Request should be a valid object/);
- expect(() => BasicCredentials.decorateRequest({})).to
- .throwError(/Username should be a valid non-empty string/);
- expect(() => BasicCredentials.decorateRequest({}, '')).to
- .throwError(/Username should be a valid non-empty string/);
- expect(() => BasicCredentials.decorateRequest({}, '', '')).to
- .throwError(/Username should be a valid non-empty string/);
- expect(() => BasicCredentials.decorateRequest({}, 'username', '')).to
- .throwError(/Password should be a valid non-empty string/);
- expect(() => BasicCredentials.decorateRequest({}, '', 'password')).to
- .throwError(/Username should be a valid non-empty string/);
+ expect(() =>
+ BasicCredentials.decorateRequest(undefined as any, undefined as any, undefined as any)
+ ).toThrowError('Request should be a valid object');
+ expect(() =>
+ BasicCredentials.decorateRequest({} as any, undefined as any, undefined as any)
+ ).toThrowError('Username should be a valid non-empty string');
+ expect(() => BasicCredentials.decorateRequest({} as any, '', undefined as any)).toThrowError(
+ 'Username should be a valid non-empty string'
+ );
+ expect(() => BasicCredentials.decorateRequest({} as any, '', '')).toThrowError(
+ 'Username should be a valid non-empty string'
+ );
+ expect(() => BasicCredentials.decorateRequest({} as any, 'username', '')).toThrowError(
+ 'Password should be a valid non-empty string'
+ );
+ expect(() => BasicCredentials.decorateRequest({} as any, '', 'password')).toThrowError(
+ 'Username should be a valid non-empty string'
+ );
});
it('`decorateRequest` correctly sets authorization header.', () => {
@@ -223,8 +231,10 @@ describe('BasicAuthenticationProvider', () => {
BasicCredentials.decorateRequest(oneRequest, 'one-user', 'one-password');
BasicCredentials.decorateRequest(anotherRequest, 'another-user', 'another-password');
- expect(oneRequest.headers.authorization).to.be('Basic b25lLXVzZXI6b25lLXBhc3N3b3Jk');
- expect(anotherRequest.headers.authorization).to.be('Basic YW5vdGhlci11c2VyOmFub3RoZXItcGFzc3dvcmQ=');
+ expect(oneRequest.headers.authorization).toBe('Basic b25lLXVzZXI6b25lLXBhc3N3b3Jk');
+ expect(anotherRequest.headers.authorization).toBe(
+ 'Basic YW5vdGhlci11c2VyOmFub3RoZXItcGFzc3dvcmQ='
+ );
});
});
});
diff --git a/x-pack/plugins/security/server/lib/authentication/providers/basic.js b/x-pack/plugins/security/server/lib/authentication/providers/basic.ts
similarity index 53%
rename from x-pack/plugins/security/server/lib/authentication/providers/basic.js
rename to x-pack/plugins/security/server/lib/authentication/providers/basic.ts
index bd8eb7a3820d8..d3756aafd0e1a 100644
--- a/x-pack/plugins/security/server/lib/authentication/providers/basic.js
+++ b/x-pack/plugins/security/server/lib/authentication/providers/basic.ts
@@ -4,9 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { Request } from 'hapi';
+import { Cluster } from 'src/legacy/core_plugins/elasticsearch';
import { canRedirectRequest } from '../../can_redirect_request';
import { AuthenticationResult } from '../authentication_result';
import { DeauthenticationResult } from '../deauthentication_result';
+import { LoginAttempt } from '../login_attempt';
/**
* Utility class that knows how to decorate request with proper Basic authentication headers.
@@ -15,13 +18,13 @@ export class BasicCredentials {
/**
* Takes provided `username` and `password`, transforms them into proper `Basic ***` authorization
* header and decorates passed request with it.
- * @param {Hapi.Request} request HapiJS request instance.
- * @param {string} username User name.
- * @param {string} password User password.
- * @returns {Hapi.Request} HapiJS request instance decorated with the proper header.
+ * @param request HapiJS request instance.
+ * @param username User name.
+ * @param password User password.
*/
- static decorateRequest(request, username, password) {
- if (!request || typeof request !== 'object') {
+ public static decorateRequest(request: T, username: string, password: string) {
+ const typeOfRequest = typeof request;
+ if (!request || typeOfRequest !== 'object') {
throw new Error('Request should be a valid object.');
}
@@ -39,63 +42,59 @@ export class BasicCredentials {
}
}
+type RequestWithLoginAttempt = Request & {
+ loginAttempt: () => LoginAttempt;
+};
+
/**
- * Object that represents available provider options.
- * @typedef {{
- * protocol: string,
- * hostname: string,
- * port: string,
- * basePath: string,
- * client: Client,
- * log: Function
- * }} ProviderOptions
+ * Represents available provider options.
*/
+interface ProviderOptions {
+ basePath: string;
+ client: Cluster;
+ log: (tags: string[], message: string) => void;
+}
/**
- * Object that represents return value of internal header auth
- * @typedef {{
- * authenticationResult: AuthenticationResult,
- * headerNotRecognized?: boolean
- * }} HeaderAuthAttempt
+ * The state supported by the provider.
*/
+interface ProviderState {
+ /**
+ * Content of the HTTP authorization header (`Basic base-64-of-username:password`) that is based
+ * on user credentials used at login time and that should be provided with every request to the
+ * Elasticsearch on behalf of the authenticated user.
+ */
+ authorization?: string;
+}
/**
* Provider that supports request authentication via Basic HTTP Authentication.
*/
+// tslint:disable-next-line: max-classes-per-file
export class BasicAuthenticationProvider {
- /**
- * Server options that may be needed by authentication provider.
- * @type {?ProviderOptions}
- * @protected
- */
- _options = null;
-
/**
* Instantiates BasicAuthenticationProvider.
- * @param {ProviderOptions} options Provider options object.
+ * @param options Provider options object.
*/
- constructor(options) {
- this._options = options;
- }
+ constructor(private readonly options: ProviderOptions) {}
/**
* Performs request authentication using Basic HTTP Authentication.
- * @param {Hapi.Request} request HapiJS request instance.
- * @param {Object} [state] Optional state object associated with the provider.
- * @returns {Promise.}
+ * @param request HapiJS request instance.
+ * @param [state] Optional state object associated with the provider.
*/
- async authenticate(request, state) {
- this._options.log(['debug', 'security', 'basic'], `Trying to authenticate user request to ${request.url.path}.`);
+ public async authenticate(request: RequestWithLoginAttempt, state?: ProviderState | null) {
+ this.debug(`Trying to authenticate user request to ${request.url.path}.`);
// first try from login payload
- let authenticationResult = await this._authenticateViaLoginAttempt(request);
+ let authenticationResult = await this.authenticateViaLoginAttempt(request);
// if there isn't a payload, try header-based auth
if (authenticationResult.notHandled()) {
const {
authenticationResult: headerAuthResult,
headerNotRecognized,
- } = await this._authenticateViaHeader(request);
+ } = await this.authenticateViaHeader(request);
if (headerNotRecognized) {
return headerAuthResult;
}
@@ -103,12 +102,12 @@ export class BasicAuthenticationProvider {
}
if (authenticationResult.notHandled() && state) {
- authenticationResult = await this._authenticateViaState(request, state);
+ authenticationResult = await this.authenticateViaState(request, state);
} else if (authenticationResult.notHandled() && canRedirectRequest(request)) {
// If we couldn't handle authentication let's redirect user to the login page.
const nextURL = encodeURIComponent(`${request.getBasePath()}${request.url.path}`);
authenticationResult = AuthenticationResult.redirectTo(
- `${this._options.basePath}/login?next=${nextURL}`
+ `${this.options.basePath}/login?next=${nextURL}`
);
}
@@ -117,39 +116,38 @@ export class BasicAuthenticationProvider {
/**
* Redirects user to the login page preserving query string parameters.
- * @param {Hapi.Request} request HapiJS request instance.
- * @returns {Promise.