diff --git a/x-pack/plugins/ml/common/types/kibana.ts b/x-pack/plugins/ml/common/types/kibana.ts index 7783a02c2dd379..cc7b68b40149f8 100644 --- a/x-pack/plugins/ml/common/types/kibana.ts +++ b/x-pack/plugins/ml/common/types/kibana.ts @@ -8,7 +8,6 @@ // custom edits or fixes for default kibana types which are incomplete import type { SimpleSavedObject } from 'kibana/public'; -import type { IndexPatternAttributes } from 'src/plugins/data/common'; import type { FieldFormatsRegistry } from '../../../../../src/plugins/field_formats/common'; export type IndexPatternTitle = string; @@ -18,7 +17,6 @@ export interface Route { k7Breadcrumbs: () => any; } -export type IndexPatternSavedObject = SimpleSavedObject; // TODO define saved object type export type SavedSearchSavedObject = SimpleSavedObject; diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index 310ac5d65c9866..9ed05bbdc2edf3 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -8,6 +8,7 @@ ], "requiredPlugins": [ "data", + "dataViews", "cloud", "features", "dataVisualizer", diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index c7e457c0b5e001..6259cecae78b59 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -135,6 +135,7 @@ export const renderApp = ( urlGenerators: deps.share.urlGenerators, maps: deps.maps, dataVisualizer: deps.dataVisualizer, + dataViews: deps.data.dataViews, }); appMountParams.onAppLeave((actions) => actions.default()); diff --git a/x-pack/plugins/ml/public/application/components/data_grid/common.ts b/x-pack/plugins/ml/public/application/components/data_grid/common.ts index a64594e86a7574..6fc6f298e73d8d 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/common.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/common.ts @@ -19,12 +19,9 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup } from 'src/core/public'; -import { - IndexPattern, - IFieldType, - ES_FIELD_TYPES, - KBN_FIELD_TYPES, -} from '../../../../../../../src/plugins/data/public'; +import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; + +import type { DataView, DataViewField } from '../../../../../../../src/plugins/data_views/common'; import { DEFAULT_RESULTS_FIELD } from '../../../../common/constants/data_frame_analytics'; import { extractErrorMessage } from '../../../../common/util/errors'; @@ -72,7 +69,7 @@ export const euiDataGridToolbarSettings = { showFullScreenSelector: false, }; -export const getFieldsFromKibanaIndexPattern = (indexPattern: IndexPattern): string[] => { +export const getFieldsFromKibanaIndexPattern = (indexPattern: DataView): string[] => { const allFields = indexPattern.fields.map((f) => f.name); const indexPatternFields: string[] = allFields.filter((f) => { if (indexPattern.metaFields.includes(f)) { @@ -98,7 +95,7 @@ export const getFieldsFromKibanaIndexPattern = (indexPattern: IndexPattern): str * @param RuntimeMappings */ export function getCombinedRuntimeMappings( - indexPattern: IndexPattern | undefined, + indexPattern: DataView | undefined, runtimeMappings?: RuntimeMappings ): RuntimeMappings | undefined { let combinedRuntimeMappings = {}; @@ -219,7 +216,7 @@ export const getDataGridSchemaFromESFieldType = ( }; export const getDataGridSchemaFromKibanaFieldType = ( - field: IFieldType | undefined + field: DataViewField | undefined ): string | undefined => { // Built-in values are ['boolean', 'currency', 'datetime', 'numeric', 'json'] // To fall back to the default string schema it needs to be undefined. @@ -312,7 +309,7 @@ export const getTopClasses = (row: Record, mlResultsField: string): }; export const useRenderCellValue = ( - indexPattern: IndexPattern | undefined, + indexPattern: DataView | undefined, pagination: IndexPagination, tableItems: DataGridItem[], resultsField?: string, diff --git a/x-pack/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts b/x-pack/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts index ff6363ea2cc6ed..fb9648f5ef4af2 100644 --- a/x-pack/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts +++ b/x-pack/plugins/ml/public/application/components/data_recognizer/data_recognizer.d.ts @@ -7,10 +7,10 @@ import { FC } from 'react'; import { SavedSearchSavedObject } from '../../../../common/types/kibana'; -import type { IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; declare const DataRecognizer: FC<{ - indexPattern: IIndexPattern; + indexPattern: DataView; savedSearch: SavedSearchSavedObject | null; results: { count: number; diff --git a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx index f9f8d9a370bab6..72641499fe6afb 100644 --- a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx +++ b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx @@ -8,15 +8,15 @@ import React from 'react'; import { shallowWithIntl } from '@kbn/test/jest'; import { FullTimeRangeSelector } from './index'; -import { Query } from 'src/plugins/data/public'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { Query } from 'src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; // Create a mock for the setFullTimeRange function in the service. // The mock is hoisted to the top, so need to prefix the mock function // with 'mock' so it can be used lazily. -const mockSetFullTimeRange = jest.fn((indexPattern: IndexPattern, query: Query) => true); +const mockSetFullTimeRange = jest.fn((indexPattern: DataView, query: Query) => true); jest.mock('./full_time_range_selector_service', () => ({ - setFullTimeRange: (indexPattern: IndexPattern, query: Query) => + setFullTimeRange: (indexPattern: DataView, query: Query) => mockSetFullTimeRange(indexPattern, query), })); @@ -26,7 +26,7 @@ describe('FullTimeRangeSelector', () => { fields: [], title: 'test-index-pattern', timeFieldName: '@timestamp', - } as unknown as IndexPattern; + } as unknown as DataView; const query: Query = { language: 'kuery', diff --git a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx index f087754bd275b0..3c9689c8c108bb 100644 --- a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx +++ b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx @@ -8,12 +8,13 @@ import React, { FC } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Query, IndexPattern } from 'src/plugins/data/public'; +import type { Query } from 'src/plugins/data/public'; import { EuiButton } from '@elastic/eui'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; import { setFullTimeRange } from './full_time_range_selector_service'; interface Props { - indexPattern: IndexPattern; + indexPattern: DataView; query: Query; disabled: boolean; callback?: (a: any) => void; @@ -23,7 +24,7 @@ interface Props { // to the time range of data in the index(es) mapped to the supplied Kibana index pattern or query. export const FullTimeRangeSelector: FC = ({ indexPattern, query, disabled, callback }) => { // wrapper around setFullTimeRange to allow for the calling of the optional callBack prop - async function setRange(i: IndexPattern, q: Query) { + async function setRange(i: DataView, q: Query) { const fullTimeRange = await setFullTimeRange(i, q); if (typeof callback === 'function') { callback(fullTimeRange); diff --git a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts index 1e9c1e2c1b74da..8f0d344a36f36e 100644 --- a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts +++ b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts @@ -8,11 +8,11 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; -import { Query } from 'src/plugins/data/public'; +import type { Query } from 'src/plugins/data/public'; import dateMath from '@elastic/datemath'; import { getTimefilter, getToastNotifications } from '../../util/dependency_cache'; import { ml, GetTimeFieldRangeResponse } from '../../services/ml_api_service'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; import { isPopulatedObject } from '../../../../common/util/object_utils'; import { RuntimeMappings } from '../../../../common/types/fields'; @@ -22,7 +22,7 @@ export interface TimeRange { } export async function setFullTimeRange( - indexPattern: IndexPattern, + indexPattern: DataView, query: Query ): Promise { try { diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx index b83965b52befc3..d64a180bfa8b6e 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx @@ -24,7 +24,7 @@ import { import { i18n } from '@kbn/i18n'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import { DataView } from '../../../../../../../src/plugins/data_views/public'; import { extractErrorMessage } from '../../../../common'; import { isRuntimeMappings } from '../../../../common/util/runtime_field_utils'; import { stringHash } from '../../../../common/util/string_utils'; @@ -89,7 +89,7 @@ export interface ScatterplotMatrixProps { legendType?: LegendType; searchQuery?: ResultsSearchQuery; runtimeMappings?: RuntimeMappings; - indexPattern?: IndexPattern; + indexPattern?: DataView; } export const ScatterplotMatrix: FC = ({ diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/use_scatterplot_field_options.ts b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/use_scatterplot_field_options.ts index d8b5b23f688474..543ab0a0c0982f 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/use_scatterplot_field_options.ts +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/use_scatterplot_field_options.ts @@ -7,12 +7,12 @@ import { useMemo } from 'react'; -import type { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; import { ML__INCREMENTAL_ID } from '../../data_frame_analytics/common/fields'; export const useScatterplotFieldOptions = ( - indexPattern?: IndexPattern, + indexPattern?: DataView, includes?: string[], excludes?: string[], resultsField = '' diff --git a/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_pattern.ts b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_pattern.ts index 9d53efad86d381..93f92002c4bfdc 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_pattern.ts +++ b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_pattern.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../src/plugins/data_views/public'; export const indexPatternMock = { id: 'the-index-pattern-id', title: 'the-index-pattern-title', fields: [], -} as unknown as IndexPattern; +} as unknown as DataView; diff --git a/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_patterns.ts b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_patterns.ts index 7dfbcf1675692c..571ce8ac3f4232 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_patterns.ts +++ b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/index_patterns.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IndexPatternsContract } from '../../../../../../../../src/plugins/data/public'; +import type { DataViewsContract } from '../../../../../../../../src/plugins/data_views/public'; export const indexPatternsMock = new (class { fieldFormats = []; @@ -19,4 +19,4 @@ export const indexPatternsMock = new (class { getIds = jest.fn(); getTitles = jest.fn(); make = jest.fn(); -})() as unknown as IndexPatternsContract; +})() as unknown as DataViewsContract; diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_context.ts b/x-pack/plugins/ml/public/application/contexts/ml/ml_context.ts index 02c0945cf998f4..cd7059b5302f23 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_context.ts @@ -6,15 +6,15 @@ */ import React from 'react'; -import { IndexPattern, IndexPatternsContract } from '../../../../../../../src/plugins/data/public'; +import { DataView, DataViewsContract } from '../../../../../../../src/plugins/data_views/public'; import { SavedSearchSavedObject } from '../../../../common/types/kibana'; import { MlServicesContext } from '../../app'; export interface MlContextValue { combinedQuery: any; - currentIndexPattern: IndexPattern; // TODO this should be IndexPattern or null + currentIndexPattern: DataView; // TODO this should be IndexPattern or null currentSavedSearch: SavedSearchSavedObject | null; - indexPatterns: IndexPatternsContract; + indexPatterns: DataViewsContract; kibanaConfig: any; // IUiSettingsClient; kibanaVersion: string; } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts index e1f0db4e9291c0..a235885a9a5b7e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/use_results_view_config.ts @@ -9,7 +9,7 @@ import { useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; import { extractErrorMessage } from '../../../../common/util/errors'; @@ -34,7 +34,7 @@ export const useResultsViewConfig = (jobId: string) => { const mlContext = useMlContext(); const trainedModelsApiService = useTrainedModelsApiService(); - const [indexPattern, setIndexPattern] = useState(undefined); + const [indexPattern, setIndexPattern] = useState(undefined); const [indexPatternErrorMessage, setIndexPatternErrorMessage] = useState( undefined ); @@ -99,7 +99,7 @@ export const useResultsViewConfig = (jobId: string) => { ? jobConfigUpdate.dest.index[0] : jobConfigUpdate.dest.index; const destIndexPatternId = getIndexPatternIdFromName(destIndex) || destIndex; - let indexP: IndexPattern | undefined; + let indexP: DataView | undefined; try { indexP = await mlContext.indexPatterns.get(destIndexPatternId); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts index 60a5a548c8621b..f3779e1968985d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts @@ -11,7 +11,7 @@ import { estypes } from '@elastic/elasticsearch'; import { EuiDataGridColumn } from '@elastic/eui'; import { CoreSetup } from 'src/core/public'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { isRuntimeMappings } from '../../../../../../common/util/runtime_field_utils'; import { RuntimeMappings } from '../../../../../../common/types/fields'; import { DEFAULT_SAMPLER_SHARD_SIZE } from '../../../../../../common/constants/field_histograms'; @@ -52,13 +52,14 @@ function getRuntimeFieldColumns(runtimeMappings: RuntimeMappings) { }); } -function getIndexPatternColumns(indexPattern: IndexPattern, fieldsFilter: string[]) { +function getIndexPatternColumns(indexPattern: DataView, fieldsFilter: string[]) { const { fields } = newJobCapsServiceAnalytics; return fields .filter((field) => fieldsFilter.includes(field.name)) .map((field) => { const schema = + // @ts-expect-error field is not DataViewField getDataGridSchemaFromESFieldType(field.type) || getDataGridSchemaFromKibanaFieldType(field); return { @@ -71,7 +72,7 @@ function getIndexPatternColumns(indexPattern: IndexPattern, fieldsFilter: string } export const useIndexData = ( - indexPattern: IndexPattern, + indexPattern: DataView, query: Record | undefined, toastNotifications: CoreSetup['notifications']['toasts'], runtimeMappings?: RuntimeMappings diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx index d67473d9d3220b..2c2df0cd3d9052 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/expandable_section/expandable_section_results.tsx @@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiDataGridColumn, EuiSpacer, EuiText } from '@elastic/eui'; -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../../src/plugins/data_views/public'; import { isClassificationAnalysis, @@ -104,7 +104,7 @@ const getResultsSectionHeaderItems = ( interface ExpandableSectionResultsProps { colorRange?: ReturnType; indexData: UseIndexDataReturnType; - indexPattern?: IndexPattern; + indexPattern?: DataView; jobConfig?: DataFrameAnalyticsConfig; needsDestIndexPattern: boolean; searchQuery: SavedSearchQuery; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx index 1a5f1bad997e2c..3639836c6be01e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx @@ -13,7 +13,7 @@ import { debounce } from 'lodash'; import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; import { estypes } from '@elastic/elasticsearch'; import { Dictionary } from '../../../../../../../common/types/common'; -import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../../../src/plugins/data_views/common'; import { Query, QueryStringInput } from '../../../../../../../../../../src/plugins/data/public'; import { @@ -29,7 +29,7 @@ interface ErrorMessage { } export interface ExplorationQueryBarProps { - indexPattern: IIndexPattern; + indexPattern: DataView; setSearchQuery: (update: { queryString: string; query?: SavedSearchQuery; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx index 416d2f8b29d3b6..41c434c7160cfe 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx @@ -7,7 +7,7 @@ import React, { FC } from 'react'; -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../../src/plugins/data_views/public'; import { getToastNotifications } from '../../../../../util/dependency_cache'; import { useMlKibana } from '../../../../../contexts/kibana'; @@ -22,7 +22,7 @@ import { ExpandableSectionResults } from '../expandable_section'; import { useExplorationResults } from './use_exploration_results'; interface Props { - indexPattern: IndexPattern; + indexPattern: DataView; jobConfig: DataFrameAnalyticsConfig; jobStatus?: DataFrameTaskStateType; needsDestIndexPattern: boolean; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts index 02e3f0abac4be1..6e0d513a35b9a7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts @@ -13,7 +13,7 @@ import { CoreSetup } from 'src/core/public'; import { i18n } from '@kbn/i18n'; import { MlApiServices } from '../../../../../services/ml_api_service'; -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../../src/plugins/data_views/public'; import { DataLoader } from '../../../../../datavisualizer/index_based/data_loader'; @@ -41,7 +41,7 @@ import { FeatureImportanceBaseline } from '../../../../../../../common/types/fea import { useExplorationDataGrid } from './use_exploration_data_grid'; export const useExplorationResults = ( - indexPattern: IndexPattern | undefined, + indexPattern: DataView | undefined, jobConfig: DataFrameAnalyticsConfig | undefined, searchQuery: SavedSearchQuery, toastNotifications: CoreSetup['notifications']['toasts'], diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts index d630fedc72d3f7..d0f048ac02606a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts @@ -9,7 +9,7 @@ import { useEffect, useMemo } from 'react'; import { EuiDataGridColumn } from '@elastic/eui'; -import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../../src/plugins/data_views/public'; import { DataLoader } from '../../../../../datavisualizer/index_based/data_loader'; @@ -41,7 +41,7 @@ import { getFeatureCount, getOutlierScoreFieldName } from './common'; import { useExplorationDataGrid } from '../exploration_results_table/use_exploration_data_grid'; export const useOutlierData = ( - indexPattern: IndexPattern | undefined, + indexPattern: DataView | undefined, jobConfig: DataFrameAnalyticsConfig | undefined, searchQuery: SavedSearchQuery ): UseIndexDataReturnType => { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx index a3f18801b88f9e..8ef743d2eea9fd 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx @@ -9,7 +9,6 @@ import { EuiToolTip } from '@elastic/eui'; import React, { FC } from 'react'; import { cloneDeep, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { IIndexPattern } from 'src/plugins/data/common'; import { DeepReadonly } from '../../../../../../../common/types/common'; import { DataFrameAnalyticsConfig, isOutlierAnalysis } from '../../../../common'; import { isClassificationAnalysis, isRegressionAnalysis } from '../../../../common/analytics'; @@ -401,13 +400,11 @@ export const useNavigateToWizardWithClonedJob = () => { const { services: { notifications: { toasts }, - savedObjects, + data: { dataViews }, }, } = useMlKibana(); const navigateToPath = useNavigateToPath(); - const savedObjectsClient = savedObjects.client; - return async (item: Pick) => { const sourceIndex = Array.isArray(item.config.source.index) ? item.config.source.index.join(',') @@ -415,19 +412,9 @@ export const useNavigateToWizardWithClonedJob = () => { let sourceIndexId; try { - const response = await savedObjectsClient.find({ - type: 'index-pattern', - perPage: 10, - search: `"${sourceIndex}"`, - searchFields: ['title'], - fields: ['title'], - }); - - const ip = response.savedObjects.find( - (obj) => obj.attributes.title.toLowerCase() === sourceIndex.toLowerCase() - ); - if (ip !== undefined) { - sourceIndexId = ip.id; + const dv = (await dataViews.find(sourceIndex)).find(({ title }) => title === sourceIndex); + if (dv !== undefined) { + sourceIndexId = dv.id; } else { toasts.addDanger( i18n.translate('xpack.ml.dataframe.analyticsList.noSourceIndexPatternForClone', { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_action_name.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_action_name.test.tsx index 6b26e3823d2efa..ad6a59bf01c0e6 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_action_name.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_action_name.test.tsx @@ -30,7 +30,7 @@ jest.mock('../../../../../../application/util/dependency_cache', () => ({ jest.mock('../../../../../contexts/kibana', () => ({ useMlKibana: () => ({ - services: mockCoreServices.createStart(), + services: { ...mockCoreServices.createStart(), data: { data_view: { find: jest.fn() } } }, }), useNotifications: () => { return { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.tsx index 91871015d2adde..0d2025c0d049a0 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.tsx @@ -8,9 +8,6 @@ import React, { useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; - -import { IIndexPattern } from 'src/plugins/data/common'; - import { extractErrorMessage } from '../../../../../../../common/util/errors'; import { useMlKibana } from '../../../../../contexts/kibana'; @@ -48,8 +45,9 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => { const [indexPatternExists, setIndexPatternExists] = useState(false); const [isLoading, setIsLoading] = useState(false); - const { savedObjects } = useMlKibana().services; - const savedObjectsClient = savedObjects.client; + const { + data: { dataViews }, + } = useMlKibana().services; const indexName = item?.config.dest.index ?? ''; @@ -57,17 +55,8 @@ export const useDeleteAction = (canDeleteDataFrameAnalytics: boolean) => { const checkIndexPatternExists = async () => { try { - const response = await savedObjectsClient.find({ - type: 'index-pattern', - perPage: 10, - search: `"${indexName}"`, - searchFields: ['title'], - fields: ['title'], - }); - const ip = response.savedObjects.find( - (obj) => obj.attributes.title.toLowerCase() === indexName.toLowerCase() - ); - if (ip !== undefined) { + const dv = (await dataViews.find(indexName)).find(({ title }) => title === indexName); + if (dv !== undefined) { setIndexPatternExists(true); } else { setIndexPatternExists(false); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx index 7e90a4e3ed44ac..6e663318d2dc64 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx @@ -87,6 +87,7 @@ jest.mock('../../../../../util/index_utils', () => { async (id: string): Promise => { return { indexPattern: { + // @ts-expect-error fields should not be empty fields: [], title: id === 'the-remote-saved-search-id' diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts b/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts index a5fabc12c83df5..1dccd54f68a386 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts @@ -7,7 +7,7 @@ import { CoreSetup } from 'src/core/public'; -import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../src/plugins/data_views/public'; import { SavedSearchQuery } from '../../../contexts/ml'; import { OMIT_FIELDS } from '../../../../../common/constants/field_types'; @@ -22,15 +22,12 @@ import { RuntimeMappings } from '../../../../../common/types/fields'; const MAX_EXAMPLES_DEFAULT: number = 10; export class DataLoader { - private _indexPattern: IndexPattern; + private _indexPattern: DataView; private _runtimeMappings: RuntimeMappings; private _indexPatternTitle: IndexPatternTitle = ''; private _maxExamples: number = MAX_EXAMPLES_DEFAULT; - constructor( - indexPattern: IndexPattern, - toastNotifications?: CoreSetup['notifications']['toasts'] - ) { + constructor(indexPattern: DataView, toastNotifications?: CoreSetup['notifications']['toasts']) { this._indexPattern = indexPattern; this._runtimeMappings = this._indexPattern.getComputedFields().runtimeFields as RuntimeMappings; this._indexPatternTitle = indexPattern.title; diff --git a/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx index 6e8b5f762558ff..f57d2c1b01d983 100644 --- a/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx +++ b/x-pack/plugins/ml/public/application/explorer/components/explorer_query_bar/explorer_query_bar.tsx @@ -10,7 +10,7 @@ import { EuiCode, EuiInputPopover } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; import { Query, QueryStringInput } from '../../../../../../../../src/plugins/data/public'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; import { SEARCH_QUERY_LANGUAGE, ErrorMessage } from '../../../../../common/constants/search'; import { explorerService } from '../../explorer_dashboard_service'; import { InfluencersFilterQuery } from '../../../../../common/types/es_client'; @@ -24,7 +24,7 @@ export function getKqlQueryValues({ }: { inputString: string | { [key: string]: any }; queryLanguage: string; - indexPattern: IIndexPattern; + indexPattern: DataView; }): { clearSettings: boolean; settings: any } { let influencersFilterQuery: InfluencersFilterQuery = {}; const filteredFields: string[] = []; @@ -89,7 +89,7 @@ function getInitSearchInputState({ interface ExplorerQueryBarProps { filterActive: boolean; filterPlaceHolder: string; - indexPattern: IIndexPattern; + indexPattern: DataView; queryString?: string; updateLanguage: (language: string) => void; } diff --git a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.test.tsx b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.test.tsx index f6769abb610b89..11e4c14cd4ab27 100644 --- a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.test.tsx +++ b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { CustomUrlEditor } from './editor'; import { TIME_RANGE_TYPE, URL_TYPE } from './constants'; import { CustomUrlSettings } from './utils'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; function prepareTest(customUrl: CustomUrlSettings, setEditCustomUrlFn: (url: UrlConfig) => void) { const savedCustomUrls = [ @@ -50,7 +50,7 @@ function prepareTest(customUrl: CustomUrlSettings, setEditCustomUrlFn: (url: Url const indexPatterns = [ { id: 'pattern1', title: 'Index Pattern 1' }, { id: 'pattern2', title: 'Index Pattern 2' }, - ] as IIndexPattern[]; + ] as DataView[]; const queryEntityFieldNames = ['airline']; diff --git a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.tsx b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.tsx index e22eb1484df2e8..7dd779ead78926 100644 --- a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.tsx +++ b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/editor.tsx @@ -29,7 +29,7 @@ import { isValidLabel } from '../../../util/custom_url_utils'; import { TIME_RANGE_TYPE, URL_TYPE } from './constants'; import { UrlConfig } from '../../../../../common/types/custom_urls'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; function getLinkToOptions() { return [ @@ -59,7 +59,7 @@ interface CustomUrlEditorProps { setEditCustomUrl: (url: any) => void; savedCustomUrls: UrlConfig[]; dashboards: any[]; - indexPatterns: IIndexPattern[]; + indexPatterns: DataView[]; queryEntityFieldNames: string[]; } diff --git a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts index 87000cdabd9137..1f815759c62429 100644 --- a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts +++ b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IIndexPattern } from 'src/plugins/data/common'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; import { UrlConfig } from '../../../../../common/types/custom_urls'; import { Job } from '../../../../../common/types/anomaly_detection_jobs'; import { TimeRangeType } from './constants'; @@ -34,7 +34,7 @@ export function isValidCustomUrlSettingsTimeRange(timeRangeSettings: any): boole export function getNewCustomUrlDefaults( job: Job, dashboards: any[], - indexPatterns: IIndexPattern[] + indexPatterns: DataView[] ): CustomUrlSettings; export function getQueryEntityFieldNames(job: Job): string[]; export function isValidCustomUrlSettings( diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.d.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.d.ts index 3a14715bca4b92..32e99e3e433e0b 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.d.ts +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.d.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IIndexPattern } from 'src/plugins/data/common'; +import type { DataView } from 'src/plugins/data_views/common'; export function loadSavedDashboards(maxNumber: number): Promise; -export function loadIndexPatterns(maxNumber: number): Promise; +export function loadIndexPatterns(maxNumber: number): Promise; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js index 8ce92ffa384798..ad192a738174e5 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js @@ -8,7 +8,7 @@ import { difference } from 'lodash'; import { getNewJobLimits } from '../../../../services/ml_server_info'; import { processCreatedBy } from '../../../../../../common/util/job_utils'; -import { getSavedObjectsClient } from '../../../../util/dependency_cache'; +import { getSavedObjectsClient, getDataViews } from '../../../../util/dependency_cache'; import { ml } from '../../../../services/ml_api_service'; export function saveJob(job, newJobData, finish) { @@ -107,26 +107,12 @@ export function loadIndexPatterns(maxNumber) { // TODO - amend loadIndexPatterns in index_utils.js to do the request, // without needing an Angular Provider. return new Promise((resolve, reject) => { - const savedObjectsClient = getSavedObjectsClient(); - savedObjectsClient - .find({ - type: 'index-pattern', - fields: ['title'], - perPage: maxNumber, - }) - .then((resp) => { - const savedObjects = resp.savedObjects; - if (savedObjects !== undefined) { - const indexPatterns = savedObjects.map((savedObj) => { - return { id: savedObj.id, title: savedObj.attributes.title }; - }); - - indexPatterns.sort((dash1, dash2) => { - return dash1.title.localeCompare(dash2.title); - }); - - resolve(indexPatterns); - } + const dataViewsContract = getDataViews(); + dataViewsContract + .find('*', maxNumber) + .then((dataViews) => { + const sortedDataViews = dataViews.sort((a, b) => a.title.localeCompare(b.title)); + resolve(sortedDataViews); }) .catch((resp) => { reject(resp); diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx index ce93080558016a..46ac1dbd01b7f7 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx @@ -37,7 +37,7 @@ import { loadSavedDashboards, loadIndexPatterns } from '../edit_utils'; import { openCustomUrlWindow } from '../../../../../util/custom_url_utils'; import { Job } from '../../../../../../../common/types/anomaly_detection_jobs'; import { UrlConfig } from '../../../../../../../common/types/custom_urls'; -import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../../../src/plugins/data_views/common'; import { MlKibanaReactContextValue } from '../../../../../contexts/kibana'; const MAX_NUMBER_DASHBOARDS = 1000; @@ -54,7 +54,7 @@ interface CustomUrlsProps { interface CustomUrlsState { customUrls: UrlConfig[]; dashboards: any[]; - indexPatterns: IIndexPattern[]; + indexPatterns: DataView[]; queryEntityFieldNames: string[]; editorOpen: boolean; editorSettings?: CustomUrlSettings; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts index 9c8f34260def03..5898a9dec1ad32 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts @@ -19,7 +19,7 @@ import { ml } from '../../../../services/ml_api_service'; import { mlResultsService } from '../../../../services/results_service'; import { getCategoryFields as getCategoryFieldsOrig } from './searches'; import { aggFieldPairsCanBeCharted } from '../job_creator/util/general'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/common'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/common'; type DetectorIndex = number; export interface LineChartPoint { @@ -41,7 +41,7 @@ export class ChartLoader { private _timeFieldName: string = ''; private _query: object = {}; - constructor(indexPattern: IndexPattern, query: object) { + constructor(indexPattern: DataView, query: object) { this._indexPatternTitle = indexPattern.title; this._query = query; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/index_pattern_context.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/index_pattern_context.ts index cb842937f1edef..9667465eb210d9 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/index_pattern_context.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/index_pattern_context.ts @@ -7,7 +7,7 @@ import React from 'react'; -import { IIndexPattern } from 'src/plugins/data/public'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; -export type IndexPatternContextValue = IIndexPattern | null; +export type IndexPatternContextValue = DataView | null; export const IndexPatternContext = React.createContext(null); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts index 35847839b02a02..3d8c34e0e5967f 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts @@ -21,7 +21,7 @@ import { JOB_TYPE } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; import { isValidJson } from '../../../../../../common/util/validation_utils'; import { ml } from '../../../../services/ml_api_service'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; export interface RichDetector { agg: Aggregation | null; @@ -40,11 +40,7 @@ export class AdvancedJobCreator extends JobCreator { private _richDetectors: RichDetector[] = []; private _queryString: string; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this._queryString = JSON.stringify(this._datafeed_config.query); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts index 128a541ff9f960..b46d3b539b44a7 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts @@ -6,7 +6,7 @@ */ import { isEqual } from 'lodash'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, Aggregation, mlCategory } from '../../../../../../common/types/fields'; @@ -47,11 +47,7 @@ export class CategorizationJobCreator extends JobCreator { private _partitionFieldName: string | null = null; private _ccsVersionFailure: boolean = false; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.CATEGORIZATION; this._examplesLoader = new CategorizationExamplesLoader(this, indexPattern, query); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index e6cfe52933617c..a44b4bdef60c40 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -40,13 +40,13 @@ import { filterRuntimeMappings } from './util/filter_runtime_mappings'; import { parseInterval } from '../../../../../../common/util/parse_interval'; import { Calendar } from '../../../../../../common/types/calendars'; import { mlCalendarService } from '../../../../services/calendar_service'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { getDatafeedAggregations } from '../../../../../../common/util/datafeed_utils'; import { getFirstKeyInObject } from '../../../../../../common/util/object_utils'; export class JobCreator { protected _type: JOB_TYPE = JOB_TYPE.SINGLE_METRIC; - protected _indexPattern: IndexPattern; + protected _indexPattern: DataView; protected _savedSearch: SavedSearchSavedObject | null; protected _indexPatternTitle: IndexPatternTitle = ''; protected _job_config: Job; @@ -74,11 +74,7 @@ export class JobCreator { protected _wizardInitialized$ = new BehaviorSubject(false); public wizardInitialized$ = this._wizardInitialized$.asObservable(); - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { this._indexPattern = indexPattern; this._savedSearch = savedSearch; this._indexPatternTitle = indexPattern.title; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts index 8c77ae5def1029..6af3df888514c0 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator_factory.ts @@ -10,7 +10,7 @@ import { SingleMetricJobCreator } from './single_metric_job_creator'; import { MultiMetricJobCreator } from './multi_metric_job_creator'; import { PopulationJobCreator } from './population_job_creator'; import { AdvancedJobCreator } from './advanced_job_creator'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { CategorizationJobCreator } from './categorization_job_creator'; import { RareJobCreator } from './rare_job_creator'; @@ -18,7 +18,7 @@ import { JOB_TYPE } from '../../../../../../common/constants/new_job'; export const jobCreatorFactory = (jobType: JOB_TYPE) => - (indexPattern: IndexPattern, savedSearch: SavedSearchSavedObject | null, query: object) => { + (indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) => { let jc; switch (jobType) { case JOB_TYPE.SINGLE_METRIC: diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts index f63aa1b569a2c6..12543f34003d52 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts @@ -17,7 +17,7 @@ import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_ import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { isSparseDataJob } from './util/general'; export class MultiMetricJobCreator extends JobCreator { @@ -27,11 +27,7 @@ export class MultiMetricJobCreator extends JobCreator { protected _type: JOB_TYPE = JOB_TYPE.MULTI_METRIC; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.MULTI_METRIC; this._wizardInitialized$.next(true); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts index 24b31922312113..7f001ce3344622 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts @@ -17,7 +17,7 @@ import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_ import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; export class PopulationJobCreator extends JobCreator { // a population job has one overall over (split) field, which is the same for all detectors @@ -26,11 +26,7 @@ export class PopulationJobCreator extends JobCreator { private _byFields: SplitField[] = []; protected _type: JOB_TYPE = JOB_TYPE.POPULATION; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.POPULATION; this._wizardInitialized$.next(true); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/rare_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/rare_job_creator.ts index 73050dc4b78349..8973aa655b83db 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/rare_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/rare_job_creator.ts @@ -11,7 +11,7 @@ import { Field, SplitField, Aggregation } from '../../../../../../common/types/f import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_detection_jobs'; import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { isSparseDataJob } from './util/general'; import { ML_JOB_AGGREGATION } from '../../../../../../common/constants/aggregation_types'; @@ -26,11 +26,7 @@ export class RareJobCreator extends JobCreator { private _rareAgg: Aggregation; private _freqRareAgg: Aggregation; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.RARE; this._wizardInitialized$.next(true); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts index 57ff76979ea14b..9c4fd52888c82c 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts @@ -22,17 +22,13 @@ import { } from '../../../../../../common/constants/aggregation_types'; import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { isSparseDataJob } from './util/general'; export class SingleMetricJobCreator extends JobCreator { protected _type: JOB_TYPE = JOB_TYPE.SINGLE_METRIC; - constructor( - indexPattern: IndexPattern, - savedSearch: SavedSearchSavedObject | null, - query: object - ) { + constructor(indexPattern: DataView, savedSearch: SavedSearchSavedObject | null, query: object) { super(indexPattern, savedSearch, query); this.createdBy = CREATED_BY_LABEL.SINGLE_METRIC; this._wizardInitialized$.next(true); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts index 641eda3dbf3e81..6e65bde8793793 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../../../src/plugins/data_views/public'; import { IndexPatternTitle } from '../../../../../../common/types/kibana'; import { CategorizationJobCreator } from '../job_creator'; import { ml } from '../../../../services/ml_api_service'; @@ -20,7 +20,7 @@ export class CategorizationExamplesLoader { private _timeFieldName: string = ''; private _query: object = {}; - constructor(jobCreator: CategorizationJobCreator, indexPattern: IndexPattern, query: object) { + constructor(jobCreator: CategorizationJobCreator, indexPattern: DataView, query: object) { this._jobCreator = jobCreator; this._indexPatternTitle = indexPattern.title; this._query = query; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts b/x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts index ba750795e4f8ff..03428bd47e4904 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { ApplicationStart } from 'kibana/public'; -import { IndexPatternsContract } from '../../../../../../../../../src/plugins/data/public'; +import type { ApplicationStart } from 'kibana/public'; +import type { DataViewsContract } from '../../../../../../../../../src/plugins/data_views/public'; import { mlJobService } from '../../../../services/job_service'; import { loadIndexPatterns, getIndexPatternIdFromName } from '../../../../util/index_utils'; import { Datafeed, Job } from '../../../../../../common/types/anomaly_detection_jobs'; import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../common/constants/new_job'; export async function preConfiguredJobRedirect( - indexPatterns: IndexPatternsContract, + indexPatterns: DataViewsContract, basePath: string, navigateToUrl: ApplicationStart['navigateToUrl'] ) { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts index 3f19f3137934ed..12beda414bbead 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts @@ -6,7 +6,7 @@ */ import { IUiSettingsClient } from 'kibana/public'; -import { IIndexPattern } from '../../../../../../../../src/plugins/data/common'; +import { DataView } from '../../../../../../../../src/plugins/data_views/common'; import { SavedSearchSavedObject } from '../../../../../common/types/kibana'; import { createSearchItems } from './new_job_utils'; @@ -14,7 +14,7 @@ describe('createSearchItems', () => { const kibanaConfig = {} as IUiSettingsClient; const indexPattern = { fields: [], - } as unknown as IIndexPattern; + } as unknown as DataView; let savedSearch = {} as unknown as SavedSearchSavedObject; beforeEach(() => { diff --git a/x-pack/plugins/ml/public/application/routing/resolvers.ts b/x-pack/plugins/ml/public/application/routing/resolvers.ts index f6364ecc6568f5..3479005809efba 100644 --- a/x-pack/plugins/ml/public/application/routing/resolvers.ts +++ b/x-pack/plugins/ml/public/application/routing/resolvers.ts @@ -11,7 +11,7 @@ import { checkGetJobsCapabilitiesResolver } from '../capabilities/check_capabili import { getMlNodeCount } from '../ml_nodes_check/check_ml_nodes'; import { loadMlServerInfo } from '../services/ml_server_info'; -import { IndexPatternsContract } from '../../../../../../src/plugins/data/public'; +import type { DataViewsContract } from '../../../../../../src/plugins/data_views/public'; export interface Resolvers { [name: string]: () => Promise; @@ -21,7 +21,7 @@ export interface ResolverResults { } interface BasicResolverDependencies { - indexPatterns: IndexPatternsContract; + indexPatterns: DataViewsContract; redirectToMlAccessDeniedPage: () => Promise; } diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index c2129ef18df3a0..847dcc1ae11078 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -9,9 +9,13 @@ import React, { useEffect, FC } from 'react'; import { useHistory, useLocation, Router, Route, RouteProps } from 'react-router-dom'; import { Location } from 'history'; -import { AppMountParameters, IUiSettingsClient, ChromeStart } from 'kibana/public'; -import { ChromeBreadcrumb } from 'kibana/public'; -import { IndexPatternsContract } from 'src/plugins/data/public'; +import type { + AppMountParameters, + IUiSettingsClient, + ChromeStart, + ChromeBreadcrumb, +} from 'kibana/public'; +import type { DataViewsContract } from 'src/plugins/data_views/public'; import { useMlKibana, useNavigateToPath } from '../contexts/kibana'; import { MlContext, MlContextValue } from '../contexts/ml'; @@ -39,7 +43,7 @@ export interface PageProps { interface PageDependencies { config: IUiSettingsClient; history: AppMountParameters['history']; - indexPatterns: IndexPatternsContract; + indexPatterns: DataViewsContract; setBreadcrumbs: ChromeStart['setBreadcrumbs']; redirectToMlAccessDeniedPage: () => Promise; } diff --git a/x-pack/plugins/ml/public/application/services/field_format_service.ts b/x-pack/plugins/ml/public/application/services/field_format_service.ts index 18b489682318e5..fe6fc7751bb85b 100644 --- a/x-pack/plugins/ml/public/application/services/field_format_service.ts +++ b/x-pack/plugins/ml/public/application/services/field_format_service.ts @@ -8,7 +8,7 @@ import { mlFunctionToESAggregation } from '../../../common/util/job_utils'; import { getIndexPatternById, getIndexPatternIdFromName } from '../util/index_utils'; import { mlJobService } from './job_service'; -import { IndexPattern } from '../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../src/plugins/data_views/public'; type FormatsByJobId = Record; type IndexPatternIdsByJob = Record; @@ -66,11 +66,7 @@ class FieldFormatService { // Utility for returning the FieldFormat from a full populated Kibana index pattern object // containing the list of fields by name with their formats. - getFieldFormatFromIndexPattern( - fullIndexPattern: IndexPattern, - fieldName: string, - esAggName: string - ) { + getFieldFormatFromIndexPattern(fullIndexPattern: DataView, fieldName: string, esAggName: string) { // Don't use the field formatter for distinct count detectors as // e.g. distinct_count(clientip) should be formatted as a count, not as an IP address. let fieldFormat; diff --git a/x-pack/plugins/ml/public/application/services/new_job_capabilities/load_new_job_capabilities.ts b/x-pack/plugins/ml/public/application/services/new_job_capabilities/load_new_job_capabilities.ts index d3b407c2bb65a8..02b2e573f8c699 100644 --- a/x-pack/plugins/ml/public/application/services/new_job_capabilities/load_new_job_capabilities.ts +++ b/x-pack/plugins/ml/public/application/services/new_job_capabilities/load_new_job_capabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IIndexPattern, IndexPatternsContract } from '../../../../../../../src/plugins/data/public'; +import { DataView, DataViewsContract } from '../../../../../../../src/plugins/data_views/public'; import { getIndexPatternAndSavedSearch } from '../../util/index_utils'; import { JobType } from '../../../../common/types/saved_objects'; import { newJobCapsServiceAnalytics } from '../new_job_capabilities/new_job_capabilities_service_analytics'; @@ -19,7 +19,7 @@ export const DATA_FRAME_ANALYTICS = 'data-frame-analytics'; export function loadNewJobCapabilities( indexPatternId: string, savedSearchId: string, - indexPatterns: IndexPatternsContract, + indexPatterns: DataViewsContract, jobType: JobType ) { return new Promise(async (resolve, reject) => { @@ -29,7 +29,7 @@ export function loadNewJobCapabilities( if (indexPatternId !== undefined) { // index pattern is being used - const indexPattern: IIndexPattern = await indexPatterns.get(indexPatternId); + const indexPattern: DataView = await indexPatterns.get(indexPatternId); await serviceToUse.initializeFromIndexPattern(indexPattern); resolve(serviceToUse.newJobCaps); } else if (savedSearchId !== undefined) { diff --git a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities._service.test.ts b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities._service.test.ts index 8c515255927b43..49c8b08007d52d 100644 --- a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities._service.test.ts +++ b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities._service.test.ts @@ -6,7 +6,7 @@ */ import { newJobCapsService } from './new_job_capabilities_service'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; // there is magic happening here. starting the include name with `mock..` // ensures it can be lazily loaded by the jest.mock function below. @@ -23,7 +23,7 @@ jest.mock('../ml_api_service', () => ({ const indexPattern = { id: 'cloudwatch-*', title: 'cloudwatch-*', -} as unknown as IndexPattern; +} as unknown as DataView; describe('new_job_capabilities_service', () => { describe('cloudwatch newJobCaps()', () => { diff --git a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts index c17f379355cea8..45dc71ed6a6b93 100644 --- a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts +++ b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts @@ -11,7 +11,8 @@ import { FieldId, EVENT_RATE_FIELD_ID, } from '../../../../common/types/fields'; -import { ES_FIELD_TYPES, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; +import { DataView } from '../../../../../../../src/plugins/data_views/public'; import { ml } from '../ml_api_service'; import { processTextAndKeywordFields, NewJobCapabilitiesServiceBase } from './new_job_capabilities'; @@ -36,7 +37,7 @@ class NewJobCapsService extends NewJobCapabilitiesServiceBase { } public async initializeFromIndexPattern( - indexPattern: IIndexPattern, + indexPattern: DataView, includeEventRateField = true, removeTextFields = true ) { diff --git a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts index 3a362a88e40bbc..f8f9ae6b2b0a37 100644 --- a/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts +++ b/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts @@ -6,7 +6,8 @@ */ import { Field, NewJobCapsResponse } from '../../../../common/types/fields'; -import { ES_FIELD_TYPES, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; +import { DataView } from '../../../../../../../src/plugins/data_views/public'; import { processTextAndKeywordFields, NewJobCapabilitiesServiceBase } from './new_job_capabilities'; import { ml } from '../ml_api_service'; @@ -42,7 +43,7 @@ export function removeNestedFieldChildren(resp: NewJobCapsResponse, indexPattern } class NewJobCapsServiceAnalytics extends NewJobCapabilitiesServiceBase { - public async initializeFromIndexPattern(indexPattern: IIndexPattern) { + public async initializeFromIndexPattern(indexPattern: DataView) { try { const resp: NewJobCapsResponse = await ml.dataFrameAnalytics.newJobCapsAnalytics( indexPattern.title, diff --git a/x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts b/x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts index eaf30d9894f605..ec2a2a1077a7fa 100644 --- a/x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts +++ b/x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts @@ -6,7 +6,7 @@ */ import { removeNestedFieldChildren } from './new_job_capabilities_service_analytics'; -import { IndexPattern } from '../../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../../src/plugins/data_views/public'; // there is magic happening here. starting the include name with `mock..` // ensures it can be lazily loaded by the jest.mock function below. @@ -15,7 +15,7 @@ import nestedFieldIndexResponse from '../__mocks__/nested_field_index_response.j const indexPattern = { id: 'nested-field-index', title: 'nested-field-index', -} as unknown as IndexPattern; +} as unknown as DataView; describe('removeNestedFieldChildren', () => { describe('cloudwatch newJobCapsAnalytics()', () => { diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 4a3194ed4113fc..7b6b75677dddd3 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -19,8 +19,9 @@ import type { ChromeRecentlyAccessed, IBasePath, } from 'kibana/public'; -import type { IndexPatternsContract, DataPublicPluginStart } from 'src/plugins/data/public'; +import type { DataPublicPluginStart } from 'src/plugins/data/public'; import type { SharePluginStart } from 'src/plugins/share/public'; +import type { DataViewsContract } from '../../../../../../src/plugins/data_views/public'; import type { SecurityPluginSetup } from '../../../../security/public'; import type { MapsStartApi } from '../../../../maps/public'; import type { DataVisualizerPluginStart } from '../../../../data_visualizer/public'; @@ -28,7 +29,7 @@ import type { DataVisualizerPluginStart } from '../../../../data_visualizer/publ export interface DependencyCache { timefilter: DataPublicPluginSetup['query']['timefilter'] | null; config: IUiSettingsClient | null; - indexPatterns: IndexPatternsContract | null; + indexPatterns: DataViewsContract | null; chrome: ChromeStart | null; docLinks: DocLinksStart | null; toastNotifications: ToastsStart | null; @@ -45,6 +46,7 @@ export interface DependencyCache { urlGenerators: SharePluginStart['urlGenerators'] | null; maps: MapsStartApi | null; dataVisualizer: DataVisualizerPluginStart | null; + dataViews: DataViewsContract | null; } const cache: DependencyCache = { @@ -67,6 +69,7 @@ const cache: DependencyCache = { urlGenerators: null, maps: null, dataVisualizer: null, + dataViews: null, }; export function setDependencyCache(deps: Partial) { @@ -88,6 +91,7 @@ export function setDependencyCache(deps: Partial) { cache.i18n = deps.i18n || null; cache.urlGenerators = deps.urlGenerators || null; cache.dataVisualizer = deps.dataVisualizer || null; + cache.dataViews = deps.dataViews || null; } export function getTimefilter() { @@ -208,6 +212,13 @@ export function getGetUrlGenerator() { return cache.urlGenerators.getUrlGenerator; } +export function getDataViews() { + if (cache.dataViews === null) { + throw new Error("dataViews hasn't been initialized"); + } + return cache.dataViews; +} + export function clearCache() { Object.keys(cache).forEach((k) => { cache[k as keyof DependencyCache] = null; diff --git a/x-pack/plugins/ml/public/application/util/field_types_utils.test.ts b/x-pack/plugins/ml/public/application/util/field_types_utils.test.ts index 440ac411e8ee78..0c50dc9efa343b 100644 --- a/x-pack/plugins/ml/public/application/util/field_types_utils.test.ts +++ b/x-pack/plugins/ml/public/application/util/field_types_utils.test.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { IFieldType, KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; +import { KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; +import { DataViewField } from '../../../../../../src/plugins/data_views/common'; import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; import { kbnTypeToMLJobType, @@ -16,28 +17,34 @@ import { describe('ML - field type utils', () => { describe('kbnTypeToMLJobType', () => { test('returns correct ML_JOB_FIELD_TYPES for KBN_FIELD_TYPES', () => { - const field: IFieldType = { + // @ts-ignore reassigning missing properties + const field: DataViewField = { type: KBN_FIELD_TYPES.NUMBER, name: KBN_FIELD_TYPES.NUMBER, aggregatable: true, }; expect(kbnTypeToMLJobType(field)).toBe(ML_JOB_FIELD_TYPES.NUMBER); + // @ts-ignore reassigning read-only type field.type = KBN_FIELD_TYPES.DATE; expect(kbnTypeToMLJobType(field)).toBe(ML_JOB_FIELD_TYPES.DATE); + // @ts-ignore reassigning read-only type field.type = KBN_FIELD_TYPES.IP; expect(kbnTypeToMLJobType(field)).toBe(ML_JOB_FIELD_TYPES.IP); + // @ts-ignore reassigning read-only type field.type = KBN_FIELD_TYPES.BOOLEAN; expect(kbnTypeToMLJobType(field)).toBe(ML_JOB_FIELD_TYPES.BOOLEAN); + // @ts-ignore reassigning read-only type field.type = KBN_FIELD_TYPES.GEO_POINT; expect(kbnTypeToMLJobType(field)).toBe(ML_JOB_FIELD_TYPES.GEO_POINT); }); test('returns ML_JOB_FIELD_TYPES.KEYWORD for aggregatable KBN_FIELD_TYPES.STRING', () => { - const field: IFieldType = { + // @ts-ignore reassigning missing properties + const field: DataViewField = { type: KBN_FIELD_TYPES.STRING, name: KBN_FIELD_TYPES.STRING, aggregatable: true, @@ -46,7 +53,8 @@ describe('ML - field type utils', () => { }); test('returns ML_JOB_FIELD_TYPES.TEXT for non-aggregatable KBN_FIELD_TYPES.STRING', () => { - const field: IFieldType = { + // @ts-ignore reassigning missing properties + const field: DataViewField = { type: KBN_FIELD_TYPES.STRING, name: KBN_FIELD_TYPES.STRING, aggregatable: false, @@ -55,7 +63,8 @@ describe('ML - field type utils', () => { }); test('returns undefined for non-aggregatable "foo"', () => { - const field: IFieldType = { + // @ts-ignore reassigning missing properties + const field: DataViewField = { type: 'foo', name: 'foo', aggregatable: false, diff --git a/x-pack/plugins/ml/public/application/util/field_types_utils.ts b/x-pack/plugins/ml/public/application/util/field_types_utils.ts index 0cb21fec1862ff..c02a1cbec56eca 100644 --- a/x-pack/plugins/ml/public/application/util/field_types_utils.ts +++ b/x-pack/plugins/ml/public/application/util/field_types_utils.ts @@ -8,12 +8,13 @@ import { i18n } from '@kbn/i18n'; import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; -import { IFieldType, KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; +import { KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/public'; +import { DataViewField } from '../../../../../../src/plugins/data_views/common'; // convert kibana types to ML Job types // this is needed because kibana types only have string and not text and keyword. // and we can't use ES_FIELD_TYPES because it has no NUMBER type -export function kbnTypeToMLJobType(field: IFieldType) { +export function kbnTypeToMLJobType(field: DataViewField) { // Return undefined if not one of the supported data visualizer field types. let type; switch (field.type) { diff --git a/x-pack/plugins/ml/public/application/util/index_utils.ts b/x-pack/plugins/ml/public/application/util/index_utils.ts index 9d705c8cd725fb..b4f46d4df0cbb9 100644 --- a/x-pack/plugins/ml/public/application/util/index_utils.ts +++ b/x-pack/plugins/ml/public/application/util/index_utils.ts @@ -6,33 +6,20 @@ */ import { i18n } from '@kbn/i18n'; -import { - IndexPattern, - IIndexPattern, - IndexPatternsContract, - Query, - IndexPatternAttributes, -} from '../../../../../../src/plugins/data/public'; -import { getToastNotifications, getSavedObjectsClient } from './dependency_cache'; -import { IndexPatternSavedObject, SavedSearchSavedObject } from '../../../common/types/kibana'; - -let indexPatternCache: IndexPatternSavedObject[] = []; +import type { Query } from '../../../../../../src/plugins/data/public'; +import type { DataView, DataViewsContract } from '../../../../../../src/plugins/data_views/public'; +import type { SavedSearchSavedObject } from '../../../common/types/kibana'; +import { getToastNotifications, getSavedObjectsClient, getDataViews } from './dependency_cache'; + +let indexPatternCache: DataView[] = []; let savedSearchesCache: SavedSearchSavedObject[] = []; -let indexPatternsContract: IndexPatternsContract | null = null; +let indexPatternsContract: DataViewsContract | null = null; -export function loadIndexPatterns(indexPatterns: IndexPatternsContract) { +export async function loadIndexPatterns(indexPatterns: DataViewsContract) { indexPatternsContract = indexPatterns; - const savedObjectsClient = getSavedObjectsClient(); - return savedObjectsClient - .find({ - type: 'index-pattern', - fields: ['id', 'title', 'type', 'fields'], - perPage: 10000, - }) - .then((response) => { - indexPatternCache = response.savedObjects; - return indexPatternCache; - }); + const dataViewsContract = getDataViews(); + indexPatternCache = await dataViewsContract.find('*', 10000); + return indexPatternCache; } export function loadSavedSearches() { @@ -63,20 +50,15 @@ export function getIndexPatternsContract() { } export function getIndexPatternNames() { - return indexPatternCache.map((i) => i.attributes && i.attributes.title); + return indexPatternCache.map((i) => i.title); } export function getIndexPatternIdFromName(name: string) { - for (let j = 0; j < indexPatternCache.length; j++) { - if (indexPatternCache[j].get('title') === name) { - return indexPatternCache[j].id; - } - } - return null; + return indexPatternCache.find((i) => i.title === name)?.id ?? null; } export interface IndexPatternAndSavedSearch { savedSearch: SavedSearchSavedObject | null; - indexPattern: IIndexPattern | null; + indexPattern: DataView | null; } export async function getIndexPatternAndSavedSearch(savedSearchId: string) { const resp: IndexPatternAndSavedSearch = { @@ -106,7 +88,7 @@ export function getQueryFromSavedSearch(savedSearch: SavedSearchSavedObject) { }; } -export function getIndexPatternById(id: string): Promise { +export function getIndexPatternById(id: string): Promise { if (indexPatternsContract !== null) { if (id) { return indexPatternsContract.get(id); @@ -127,7 +109,7 @@ export function getSavedSearchById(id: string): SavedSearchSavedObject | undefin * an optional flag will trigger the display a notification at the top of the page * warning that the index is not time based */ -export function timeBasedIndexCheck(indexPattern: IndexPattern, showNotification = false) { +export function timeBasedIndexCheck(indexPattern: DataView, showNotification = false) { if (!indexPattern.isTimeBased()) { if (showNotification) { const toastNotifications = getToastNotifications(); diff --git a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx index 65d26b844e960e..47be6065aa99b6 100644 --- a/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx +++ b/x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx @@ -21,7 +21,7 @@ import { AnomalyChartsEmbeddableOutput, AnomalyChartsServices, } from '..'; -import type { IndexPattern } from '../../../../../../src/plugins/data/common'; +import type { DataView } from '../../../../../../src/plugins/data_views/common'; import { EmbeddableLoading } from '../common/components/embeddable_loading_fallback'; export const getDefaultExplorerChartsPanelTitle = (jobIds: JobId[]) => i18n.translate('xpack.ml.anomalyChartsEmbeddable.title', { @@ -66,7 +66,7 @@ export class AnomalyChartsEmbeddable extends Embeddable< const indices = new Set(jobs.map((j) => j.datafeed_config.indices).flat()); // Then find the index patterns assuming the index pattern title matches the index name - const indexPatterns: Record = {}; + const indexPatterns: Record = {}; for (const indexName of indices) { const response = await indexPatternsService.find(`"${indexName}"`); diff --git a/x-pack/plugins/ml/public/embeddables/types.ts b/x-pack/plugins/ml/public/embeddables/types.ts index 7c93fb31e9a6cb..bf23f397fe08cd 100644 --- a/x-pack/plugins/ml/public/embeddables/types.ts +++ b/x-pack/plugins/ml/public/embeddables/types.ts @@ -27,7 +27,7 @@ import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, } from './constants'; import { MlResultsService } from '../application/services/results_service'; -import { IndexPattern } from '../../../../../src/plugins/data/common'; +import type { DataView } from '../../../../../src/plugins/data_views/common'; export interface AnomalySwimlaneEmbeddableCustomInput { jobIds: JobId[]; @@ -110,7 +110,7 @@ export type AnomalyChartsEmbeddableServices = [CoreStart, MlDependencies, Anomal export interface AnomalyChartsCustomOutput { entityFields?: EntityField[]; severity?: number; - indexPatterns?: IndexPattern[]; + indexPatterns?: DataView[]; } export type AnomalyChartsEmbeddableOutput = EmbeddableOutput & AnomalyChartsCustomOutput; export interface EditAnomalyChartsPanelContext { diff --git a/x-pack/plugins/ml/server/lib/data_views_utils.ts b/x-pack/plugins/ml/server/lib/data_views_utils.ts new file mode 100644 index 00000000000000..497404425eff83 --- /dev/null +++ b/x-pack/plugins/ml/server/lib/data_views_utils.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; + +import type { DataViewsService } from '../../../../../src/plugins/data_views/common'; +import type { PluginStart as DataViewsPluginStart } from '../../../../../src/plugins/data_views/server'; + +export type GetDataViewsService = () => Promise; + +export function getDataViewsServiceFactory( + getDataViews: () => DataViewsPluginStart | null, + savedObjectClient: SavedObjectsClientContract, + scopedClient: IScopedClusterClient +): GetDataViewsService { + const dataViews = getDataViews(); + if (dataViews === null) { + throw Error('data views service has not been initialized'); + } + + return () => dataViews.dataViewsServiceFactory(savedObjectClient, scopedClient.asInternalUser); +} diff --git a/x-pack/plugins/ml/server/lib/route_guard.ts b/x-pack/plugins/ml/server/lib/route_guard.ts index 1a066660d4ee0b..b7b0568c10a312 100644 --- a/x-pack/plugins/ml/server/lib/route_guard.ts +++ b/x-pack/plugins/ml/server/lib/route_guard.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { KibanaRequest, KibanaResponseFactory, RequestHandlerContext, @@ -13,14 +13,17 @@ import { RequestHandler, SavedObjectsClientContract, } from 'kibana/server'; -import { SpacesPluginSetup } from '../../../spaces/server'; +import type { SpacesPluginSetup } from '../../../spaces/server'; import type { SecurityPluginSetup } from '../../../security/server'; import { jobSavedObjectServiceFactory, JobSavedObjectService } from '../saved_objects'; -import { MlLicense } from '../../common/license'; +import type { MlLicense } from '../../common/license'; import { MlClient, getMlClient } from '../lib/ml_client'; import type { AlertingApiRequestHandlerContext } from '../../../alerting/server'; +import type { PluginStart as DataViewsPluginStart } from '../../../../../src/plugins/data_views/server'; +import type { DataViewsService } from '../../../../../src/plugins/data_views/common'; +import { getDataViewsServiceFactory } from './data_views_utils'; type MLRequestHandlerContext = RequestHandlerContext & { alerting?: AlertingApiRequestHandlerContext; @@ -33,10 +36,12 @@ type Handler

= (handlerParams: { context: MLRequestHandlerContext; jobSavedObjectService: JobSavedObjectService; mlClient: MlClient; + getDataViewsService(): Promise; }) => ReturnType>; type GetMlSavedObjectClient = (request: KibanaRequest) => SavedObjectsClientContract | null; type GetInternalSavedObjectClient = () => SavedObjectsClientContract | null; +type GetDataViews = () => DataViewsPluginStart | null; export class RouteGuard { private _mlLicense: MlLicense; @@ -45,6 +50,7 @@ export class RouteGuard { private _spacesPlugin: SpacesPluginSetup | undefined; private _authorization: SecurityPluginSetup['authz'] | undefined; private _isMlReady: () => Promise; + private _getDataViews: GetDataViews; constructor( mlLicense: MlLicense, @@ -52,7 +58,8 @@ export class RouteGuard { getInternalSavedObject: GetInternalSavedObjectClient, spacesPlugin: SpacesPluginSetup | undefined, authorization: SecurityPluginSetup['authz'] | undefined, - isMlReady: () => Promise + isMlReady: () => Promise, + getDataViews: GetDataViews ) { this._mlLicense = mlLicense; this._getMlSavedObjectClient = getSavedObject; @@ -60,6 +67,7 @@ export class RouteGuard { this._spacesPlugin = spacesPlugin; this._authorization = authorization; this._isMlReady = isMlReady; + this._getDataViews = getDataViews; } public fullLicenseAPIGuard(handler: Handler) { @@ -79,6 +87,7 @@ export class RouteGuard { return response.forbidden(); } + const client = context.core.elasticsearch.client; const mlSavedObjectClient = this._getMlSavedObjectClient(request); const internalSavedObjectsClient = this._getInternalSavedObjectClient(); if (mlSavedObjectClient === null || internalSavedObjectsClient === null) { @@ -94,7 +103,6 @@ export class RouteGuard { this._authorization, this._isMlReady ); - const client = context.core.elasticsearch.client; return handler({ client, @@ -103,6 +111,11 @@ export class RouteGuard { context, jobSavedObjectService, mlClient: getMlClient(client, jobSavedObjectService), + getDataViewsService: getDataViewsServiceFactory( + this._getDataViews, + context.core.savedObjects.client, + client + ), }); }; } diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts index 15b4cfa5be8b16..568be4197baf8f 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts @@ -5,29 +5,19 @@ * 2.0. */ -import { SavedObjectsClientContract } from 'kibana/server'; -import { IndexPatternAttributes } from 'src/plugins/data/server'; +import { DataViewsService } from '../../../../../../src/plugins/data_views/common'; export class IndexPatternHandler { - constructor(private savedObjectsClient: SavedObjectsClientContract) {} + constructor(private dataViewService: DataViewsService) {} // returns a id based on an index pattern name async getIndexPatternId(indexName: string) { - const response = await this.savedObjectsClient.find({ - type: 'index-pattern', - perPage: 10, - search: `"${indexName}"`, - searchFields: ['title'], - fields: ['title'], - }); - - const ip = response.saved_objects.find( - (obj) => obj.attributes.title.toLowerCase() === indexName.toLowerCase() + const dv = (await this.dataViewService.find(indexName)).find( + ({ title }) => title === indexName ); - - return ip?.id; + return dv?.id; } async deleteIndexPatternById(indexId: string) { - return await this.savedObjectsClient.delete('index-pattern', indexId); + return await this.dataViewService.delete(indexId); } } diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts index 8ddb805af20338..e853d5de5899d1 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts @@ -5,11 +5,16 @@ * 2.0. */ -import { SavedObjectsClientContract, KibanaRequest, IScopedClusterClient } from 'kibana/server'; -import { Module } from '../../../common/types/modules'; +import type { + SavedObjectsClientContract, + KibanaRequest, + IScopedClusterClient, +} from 'kibana/server'; +import type { DataViewsService } from '../../../../../../src/plugins/data_views/common'; +import type { Module } from '../../../common/types/modules'; import { DataRecognizer } from '../data_recognizer'; import type { MlClient } from '../../lib/ml_client'; -import { JobSavedObjectService } from '../../saved_objects'; +import type { JobSavedObjectService } from '../../saved_objects'; const callAs = () => Promise.resolve({ body: {} }); @@ -28,6 +33,7 @@ describe('ML - data recognizer', () => { find: jest.fn(), bulkCreate: jest.fn(), } as unknown as SavedObjectsClientContract, + { find: jest.fn() } as unknown as DataViewsService, {} as JobSavedObjectService, { headers: { authorization: '' } } as KibanaRequest ); diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index f9c609803217e4..711ec0d458f277 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -8,17 +8,21 @@ import fs from 'fs'; import Boom from '@hapi/boom'; import numeral from '@elastic/numeral'; -import { KibanaRequest, IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; +import type { + KibanaRequest, + IScopedClusterClient, + SavedObjectsClientContract, +} from 'kibana/server'; import moment from 'moment'; -import { IndexPatternAttributes } from 'src/plugins/data/server'; import { merge } from 'lodash'; -import { AnalysisLimits } from '../../../common/types/anomaly_detection_jobs'; +import type { DataViewsService } from '../../../../../../src/plugins/data_views/common'; +import type { AnalysisLimits } from '../../../common/types/anomaly_detection_jobs'; import { getAuthorizationHeader } from '../../lib/request_authorization'; -import { MlInfoResponse } from '../../../common/types/ml_server_info'; +import type { MlInfoResponse } from '../../../common/types/ml_server_info'; import type { MlClient } from '../../lib/ml_client'; import { ML_MODULE_SAVED_OBJECT_TYPE } from '../../../common/types/saved_objects'; -import { +import type { KibanaObjects, KibanaObjectConfig, ModuleDatafeed, @@ -35,8 +39,8 @@ import { DataRecognizerConfigResponse, GeneralDatafeedsOverride, JobSpecificOverride, - isGeneralJobOverride, } from '../../../common/types/modules'; +import { isGeneralJobOverride } from '../../../common/types/modules'; import { getLatestDataOrBucketTimestamp, prefixDatafeedId, @@ -47,10 +51,10 @@ import { calculateModelMemoryLimitProvider } from '../calculate_model_memory_lim import { fieldsServiceProvider } from '../fields_service'; import { jobServiceProvider } from '../job_service'; import { resultsServiceProvider } from '../results_service'; -import { JobExistResult, JobStat } from '../../../common/types/data_recognizer'; -import { MlJobsStatsResponse } from '../../../common/types/job_service'; -import { Datafeed } from '../../../common/types/anomaly_detection_jobs'; -import { JobSavedObjectService } from '../../saved_objects'; +import type { JobExistResult, JobStat } from '../../../common/types/data_recognizer'; +import type { MlJobsStatsResponse } from '../../../common/types/job_service'; +import type { Datafeed } from '../../../common/types/anomaly_detection_jobs'; +import type { JobSavedObjectService } from '../../saved_objects'; import { isDefined } from '../../../common/types/guards'; import { isPopulatedObject } from '../../../common/util/object_utils'; @@ -110,6 +114,7 @@ export class DataRecognizer { private _mlClient: MlClient; private _savedObjectsClient: SavedObjectsClientContract; private _jobSavedObjectService: JobSavedObjectService; + private _dataViewsService: DataViewsService; private _request: KibanaRequest; private _authorizationHeader: object; @@ -130,12 +135,14 @@ export class DataRecognizer { mlClusterClient: IScopedClusterClient, mlClient: MlClient, savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, jobSavedObjectService: JobSavedObjectService, request: KibanaRequest ) { this._client = mlClusterClient; this._mlClient = mlClient; this._savedObjectsClient = savedObjectsClient; + this._dataViewsService = dataViewsService; this._jobSavedObjectService = jobSavedObjectService; this._request = request; this._authorizationHeader = getAuthorizationHeader(request); @@ -615,22 +622,11 @@ export class DataRecognizer { return results; } - private async _loadIndexPatterns() { - return await this._savedObjectsClient.find({ - type: 'index-pattern', - perPage: 1000, - }); - } - // returns a id based on an index pattern name - private async _getIndexPatternId(name: string) { + private async _getIndexPatternId(name: string): Promise { try { - const indexPatterns = await this._loadIndexPatterns(); - if (indexPatterns === undefined || indexPatterns.saved_objects === undefined) { - return; - } - const ip = indexPatterns.saved_objects.find((i) => i.attributes.title === name); - return ip !== undefined ? ip.id : undefined; + const dataViews = await this._dataViewsService.find(name); + return dataViews.find((d) => d.title === name)?.id; } catch (error) { mlLog.warn(`Error loading index patterns, ${error}`); return; @@ -1387,3 +1383,21 @@ export class DataRecognizer { } } } + +export function dataRecognizerFactory( + client: IScopedClusterClient, + mlClient: MlClient, + savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, + jobSavedObjectService: JobSavedObjectService, + request: KibanaRequest +) { + return new DataRecognizer( + client, + mlClient, + savedObjectsClient, + dataViewsService, + jobSavedObjectService, + request + ); +} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/index.ts b/x-pack/plugins/ml/server/models/data_recognizer/index.ts index 27c45726ae2493..fbddf17a50ede0 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/index.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { DataRecognizer, RecognizeResult } from './data_recognizer'; +export { DataRecognizer, RecognizeResult, dataRecognizerFactory } from './data_recognizer'; diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/data_view_rollup_cloudwatch.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/data_view_rollup_cloudwatch.json new file mode 100644 index 00000000000000..a6aeb814315327 --- /dev/null +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/data_view_rollup_cloudwatch.json @@ -0,0 +1,151 @@ +[ + { + "id": "d6ac99b0-2777-11ec-8e1c-aba6d0767aaa", + "title": "cloud_roll_index", + "fieldFormatMap": {}, + "typeMeta": { + "params": { + "rollup_index": "cloud_roll_index" + }, + "aggs": { + "date_histogram": { + "@timestamp": { + "agg": "date_histogram", + "fixed_interval": "5m", + "time_zone": "UTC" + } + } + } + }, + "fields": [ + { + "count": 0, + "name": "_source", + "type": "_source", + "esTypes": [ + "_source" + ], + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "_id", + "type": "string", + "esTypes": [ + "_id" + ], + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "_type", + "type": "string", + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "_index", + "type": "string", + "esTypes": [ + "_index" + ], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "count": 0, + "name": "_score", + "type": "number", + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "@timestamp", + "type": "date", + "esTypes": [ + "date" + ], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + } + ], + "timeFieldName": "@timestamp", + "type": "rollup", + "metaFields": [ + "_source", + "_id", + "_type", + "_index", + "_score" + ], + "version": "WzY5NjEsNF0=", + "originalSavedObjectBody": { + "fieldAttrs": "{}", + "title": "cloud_roll_index", + "timeFieldName": "@timestamp", + "fields": "[]", + "type": "rollup", + "typeMeta": "{\"params\":{\"rollup_index\":\"cloud_roll_index\"},\"aggs\":{\"date_histogram\":{\"@timestamp\":{\"agg\":\"date_histogram\",\"fixed_interval\":\"5m\",\"time_zone\":\"UTC\"}}}}", + "runtimeFieldMap": "{}" + }, + "shortDotsEnable": false, + "fieldFormats": { + "fieldFormats": {}, + "defaultMap": { + "ip": { + "id": "ip", + "params": {} + }, + "date": { + "id": "date", + "params": {} + }, + "date_nanos": { + "id": "date_nanos", + "params": {}, + "es": true + }, + "number": { + "id": "number", + "params": {} + }, + "boolean": { + "id": "boolean", + "params": {} + }, + "histogram": { + "id": "histogram", + "params": {} + }, + "_source": { + "id": "_source", + "params": {} + }, + "_default_": { + "id": "string", + "params": {} + } + }, + "metaParamsOptions": {} + }, + "fieldAttrs": {}, + "runtimeFieldMap": {}, + "allowNoIndex": false + } +] diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json b/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json deleted file mode 100644 index 9e2af762642315..00000000000000 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/__mocks__/responses/kibana_saved_objects.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "page": 1, - "per_page": 1000, - "total": 4, - "saved_objects": [ - { - "type": "index-pattern", - "id": "be0eebe0-65ac-11e9-aa86-0793be5f3670", - "attributes": { - "title": "farequote-*" - }, - "references": [], - "migrationVersion": { - "index-pattern": "6.5.0" - }, - "updated_at": "2019-04-23T09:47:02.203Z", - "version": "WzcsMV0=" - }, - { - "type": "index-pattern", - "id": "be14ceb0-66b1-11e9-91c9-ffa52374d341", - "attributes": { - "typeMeta": "{\"params\":{\"rollup_index\":\"cloud_roll_index\"},\"aggs\":{\"histogram\":{\"NetworkOut\":{\"agg\":\"histogram\",\"interval\":5},\"CPUUtilization\":{\"agg\":\"histogram\",\"interval\":5},\"NetworkIn\":{\"agg\":\"histogram\",\"interval\":5}},\"avg\":{\"NetworkOut\":{\"agg\":\"avg\"},\"CPUUtilization\":{\"agg\":\"avg\"},\"NetworkIn\":{\"agg\":\"avg\"},\"DiskReadBytes\":{\"agg\":\"avg\"}},\"min\":{\"NetworkOut\":{\"agg\":\"min\"},\"NetworkIn\":{\"agg\":\"min\"}},\"value_count\":{\"NetworkOut\":{\"agg\":\"value_count\"},\"DiskReadBytes\":{\"agg\":\"value_count\"},\"CPUUtilization\":{\"agg\":\"value_count\"},\"NetworkIn\":{\"agg\":\"value_count\"}},\"max\":{\"CPUUtilization\":{\"agg\":\"max\"},\"DiskReadBytes\":{\"agg\":\"max\"}},\"date_histogram\":{\"@timestamp\":{\"agg\":\"date_histogram\",\"delay\":\"1d\",\"fixed_interval\":\"5m\",\"time_zone\":\"UTC\"}},\"terms\":{\"instance\":{\"agg\":\"terms\"},\"sourcetype.keyword\":{\"agg\":\"terms\"},\"region\":{\"agg\":\"terms\"}},\"sum\":{\"DiskReadBytes\":{\"agg\":\"sum\"},\"NetworkOut\":{\"agg\":\"sum\"}}}}", - "title": "cloud_roll_index", - "type": "rollup" - }, - "references": [], - "migrationVersion": { - "index-pattern": "6.5.0" - }, - "updated_at": "2019-04-24T16:55:20.550Z", - "version": "Wzc0LDJd" - } - ] -} diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index b838165826da15..a25b3183362b36 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; -import { IScopedClusterClient } from 'kibana/server'; import { cloneDeep } from 'lodash'; -import { SavedObjectsClientContract } from 'kibana/server'; -import { Field, FieldId, NewJobCaps, RollupFields } from '../../../../common/types/fields'; +import { estypes } from '@elastic/elasticsearch'; +import type { IScopedClusterClient } from 'kibana/server'; +import type { Field, FieldId, NewJobCaps, RollupFields } from '../../../../common/types/fields'; import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/common'; +import type { DataViewsService } from '../../../../../../../src/plugins/data_views/common'; import { combineFieldsAndAggs } from '../../../../common/util/fields_utils'; import { rollupServiceProvider } from './rollup'; import { aggregations, mlOnlyAggregations } from '../../../../common/constants/aggregation_types'; @@ -38,27 +38,27 @@ export function fieldServiceProvider( indexPattern: string, isRollup: boolean, client: IScopedClusterClient, - savedObjectsClient: SavedObjectsClientContract + dataViewsService: DataViewsService ) { - return new FieldsService(indexPattern, isRollup, client, savedObjectsClient); + return new FieldsService(indexPattern, isRollup, client, dataViewsService); } class FieldsService { private _indexPattern: string; private _isRollup: boolean; private _mlClusterClient: IScopedClusterClient; - private _savedObjectsClient: SavedObjectsClientContract; + private _dataViewsService: DataViewsService; constructor( indexPattern: string, isRollup: boolean, client: IScopedClusterClient, - savedObjectsClient: SavedObjectsClientContract + dataViewsService: DataViewsService ) { this._indexPattern = indexPattern; this._isRollup = isRollup; this._mlClusterClient = client; - this._savedObjectsClient = savedObjectsClient; + this._dataViewsService = dataViewsService; } private async loadFieldCaps(): Promise { @@ -111,7 +111,7 @@ class FieldsService { const rollupService = await rollupServiceProvider( this._indexPattern, this._mlClusterClient, - this._savedObjectsClient + this._dataViewsService ); const rollupConfigs: estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] | null = await rollupService.getRollupJobs(); diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts index 3eb2ba5bbaced3..c0f270f1df96c2 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts @@ -10,7 +10,7 @@ import { newJobCapsProvider } from './index'; import farequoteFieldCaps from './__mocks__/responses/farequote_field_caps.json'; import cloudwatchFieldCaps from './__mocks__/responses/cloudwatch_field_caps.json'; import rollupCaps from './__mocks__/responses/rollup_caps.json'; -import kibanaSavedObjects from './__mocks__/responses/kibana_saved_objects.json'; +import dataView from './__mocks__/responses/data_view_rollup_cloudwatch.json'; import farequoteJobCaps from './__mocks__/results/farequote_job_caps.json'; import farequoteJobCapsEmpty from './__mocks__/results/farequote_job_caps_empty.json'; @@ -19,7 +19,7 @@ import cloudwatchJobCaps from './__mocks__/results/cloudwatch_rollup_job_caps.js describe('job_service - job_caps', () => { let mlClusterClientNonRollupMock: any; let mlClusterClientRollupMock: any; - let savedObjectsClientMock: any; + let dataViews: any; beforeEach(() => { const asNonRollupMock = { @@ -41,9 +41,9 @@ describe('job_service - job_caps', () => { asInternalUser: callAsRollupMock, }; - savedObjectsClientMock = { + dataViews = { async find() { - return Promise.resolve(kibanaSavedObjects); + return Promise.resolve(dataView); }, }; }); @@ -53,7 +53,7 @@ describe('job_service - job_caps', () => { const indexPattern = 'farequote-*'; const isRollup = false; const { newJobCaps } = newJobCapsProvider(mlClusterClientNonRollupMock); - const response = await newJobCaps(indexPattern, isRollup, savedObjectsClientMock); + const response = await newJobCaps(indexPattern, isRollup, dataViews); expect(response).toEqual(farequoteJobCaps); }); @@ -61,7 +61,7 @@ describe('job_service - job_caps', () => { const indexPattern = 'farequote-*'; const isRollup = true; const { newJobCaps } = newJobCapsProvider(mlClusterClientNonRollupMock); - const response = await newJobCaps(indexPattern, isRollup, savedObjectsClientMock); + const response = await newJobCaps(indexPattern, isRollup, dataViews); expect(response).toEqual(farequoteJobCapsEmpty); }); }); @@ -71,7 +71,7 @@ describe('job_service - job_caps', () => { const indexPattern = 'cloud_roll_index'; const isRollup = true; const { newJobCaps } = newJobCapsProvider(mlClusterClientRollupMock); - const response = await newJobCaps(indexPattern, isRollup, savedObjectsClientMock); + const response = await newJobCaps(indexPattern, isRollup, dataViews); expect(response).toEqual(cloudwatchJobCaps); }); @@ -79,7 +79,7 @@ describe('job_service - job_caps', () => { const indexPattern = 'cloud_roll_index'; const isRollup = false; const { newJobCaps } = newJobCapsProvider(mlClusterClientRollupMock); - const response = await newJobCaps(indexPattern, isRollup, savedObjectsClientMock); + const response = await newJobCaps(indexPattern, isRollup, dataViews); expect(response).not.toEqual(cloudwatchJobCaps); }); }); diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts index 6444f9ae3f61a2..bab4fb31aa1a98 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts @@ -5,18 +5,19 @@ * 2.0. */ -import { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; +import type { IScopedClusterClient } from 'kibana/server'; +import type { DataViewsService } from '../../../../../../../src/plugins/data_views/common'; +import type { Aggregation, Field, NewJobCapsResponse } from '../../../../common/types/fields'; import { _DOC_COUNT } from '../../../../common/constants/field_types'; -import { Aggregation, Field, NewJobCapsResponse } from '../../../../common/types/fields'; import { fieldServiceProvider } from './field_service'; export function newJobCapsProvider(client: IScopedClusterClient) { async function newJobCaps( indexPattern: string, isRollup: boolean = false, - savedObjectsClient: SavedObjectsClientContract + dataViewsService: DataViewsService ): Promise { - const fieldService = fieldServiceProvider(indexPattern, isRollup, client, savedObjectsClient); + const fieldService = fieldServiceProvider(indexPattern, isRollup, client, dataViewsService); const { aggs, fields } = await fieldService.getData(); convertForStringify(aggs, fields); diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts index 72408b7f9c5346..87504a1bc0e10a 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts @@ -6,11 +6,12 @@ */ import { estypes } from '@elastic/elasticsearch'; -import { IScopedClusterClient } from 'kibana/server'; -import { SavedObject } from 'kibana/server'; -import { IndexPatternAttributes } from 'src/plugins/data/server'; -import { SavedObjectsClientContract } from 'kibana/server'; -import { RollupFields } from '../../../../common/types/fields'; +import type { IScopedClusterClient } from 'kibana/server'; +import type { + DataViewsService, + DataView, +} from '../../../../../../../src/plugins/data_views/common'; +import type { RollupFields } from '../../../../common/types/fields'; export interface RollupJob { job_id: string; @@ -22,17 +23,19 @@ export interface RollupJob { export async function rollupServiceProvider( indexPattern: string, { asCurrentUser }: IScopedClusterClient, - savedObjectsClient: SavedObjectsClientContract + dataViewsService: DataViewsService ) { - const rollupIndexPatternObject = await loadRollupIndexPattern(indexPattern, savedObjectsClient); + const rollupIndexPatternObject = await loadRollupIndexPattern(indexPattern, dataViewsService); let jobIndexPatterns: string[] = [indexPattern]; async function getRollupJobs(): Promise< estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] | null > { - if (rollupIndexPatternObject !== null) { - const parsedTypeMetaData = JSON.parse(rollupIndexPatternObject.attributes.typeMeta!); - const rollUpIndex: string = parsedTypeMetaData.params.rollup_index; + if ( + rollupIndexPatternObject !== null && + rollupIndexPatternObject.typeMeta?.params !== undefined + ) { + const rollUpIndex: string = rollupIndexPatternObject.typeMeta.params.rollup_index; const { body: rollupCaps } = await asCurrentUser.rollup.getRollupIndexCaps({ index: rollUpIndex, }); @@ -60,21 +63,12 @@ export async function rollupServiceProvider( async function loadRollupIndexPattern( indexPattern: string, - savedObjectsClient: SavedObjectsClientContract -): Promise | null> { - const resp = await savedObjectsClient.find({ - type: 'index-pattern', - fields: ['title', 'type', 'typeMeta'], - perPage: 1000, - }); - - const obj = resp.saved_objects.find( - (r) => - r.attributes && - r.attributes.type === 'rollup' && - r.attributes.title === indexPattern && - r.attributes.typeMeta !== undefined + dataViewsService: DataViewsService +): Promise { + const resp = await dataViewsService.find('*', 10000); + const obj = resp.find( + (dv) => dv.type === 'rollup' && dv.title === indexPattern && dv.typeMeta !== undefined ); - return obj || null; + return obj ?? null; } diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index 3876193cfbe392..efa61593655ac7 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { +import type { CoreSetup, CoreStart, Plugin, @@ -21,10 +21,11 @@ import { } from 'kibana/server'; import type { SecurityPluginSetup } from '../../security/server'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; -import { PluginsSetup, PluginsStart, RouteInitialization } from './types'; -import { SpacesPluginSetup } from '../../spaces/server'; +import type { PluginStart as DataViewsPluginStart } from '../../../../src/plugins/data_views/server'; +import type { PluginsSetup, PluginsStart, RouteInitialization } from './types'; +import type { SpacesPluginSetup } from '../../spaces/server'; import { PLUGIN_ID } from '../common/constants/app'; -import { MlCapabilities } from '../common/types/capabilities'; +import type { MlCapabilities } from '../common/types/capabilities'; import { initMlServerLog } from './lib/log'; import { initSampleDataSets } from './lib/sample_data_sets'; @@ -78,6 +79,7 @@ export class MlServerPlugin private savedObjectsStart: SavedObjectsServiceStart | null = null; private spacesPlugin: SpacesPluginSetup | undefined; private security: SecurityPluginSetup | undefined; + private dataViews: DataViewsPluginStart | null = null; private isMlReady: Promise; private setMlReady: () => void = () => {}; private readonly kibanaIndexConfig: SharedGlobalConfig; @@ -156,7 +158,8 @@ export class MlServerPlugin getInternalSavedObjectsClient, plugins.spaces, plugins.security?.authz, - () => this.isMlReady + () => this.isMlReady, + () => this.dataViews ), mlLicense: this.mlLicense, }; @@ -173,6 +176,13 @@ export class MlServerPlugin ? () => coreSetup.getStartServices().then(([, { spaces }]) => spaces!) : undefined; + const getDataViews = () => { + if (this.dataViews === null) { + throw Error('Data views plugin not initialized'); + } + return this.dataViews; + }; + annotationRoutes(routeInit, plugins.security); calendars(routeInit); dataFeedRoutes(routeInit); @@ -211,6 +221,7 @@ export class MlServerPlugin () => getInternalSavedObjectsClient(), () => this.uiSettings, () => this.fieldsFormat, + getDataViews, () => this.isMlReady ); @@ -236,6 +247,7 @@ export class MlServerPlugin this.capabilities = coreStart.capabilities; this.clusterClient = coreStart.elasticsearch.client; this.savedObjectsStart = coreStart.savedObjects; + this.dataViews = plugins.dataViews; // check whether the job saved objects exist // and create them if needed. diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index bedc70566a62f0..bbfcc0fd5e500a 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { RequestHandlerContext, IScopedClusterClient } from 'kibana/server'; +import type { IScopedClusterClient } from 'kibana/server'; import { wrapError } from '../client/error_wrapper'; import { analyticsAuditMessagesProvider } from '../models/data_frame_analytics/analytics_audit_messages'; -import { RouteInitialization } from '../types'; +import type { RouteInitialization } from '../types'; import { JOB_MAP_NODE_TYPES } from '../../common/constants/data_frame_analytics'; -import { Field, Aggregation } from '../../common/types/fields'; +import type { Field, Aggregation } from '../../common/types/fields'; import { dataAnalyticsJobConfigSchema, dataAnalyticsJobUpdateSchema, @@ -25,22 +25,26 @@ import { analyticsNewJobCapsParamsSchema, analyticsNewJobCapsQuerySchema, } from './schemas/data_analytics_schema'; -import { GetAnalyticsMapArgs, ExtendAnalyticsMapArgs } from '../models/data_frame_analytics/types'; +import type { + GetAnalyticsMapArgs, + ExtendAnalyticsMapArgs, +} from '../models/data_frame_analytics/types'; import { IndexPatternHandler } from '../models/data_frame_analytics/index_patterns'; import { AnalyticsManager } from '../models/data_frame_analytics/analytics_manager'; import { validateAnalyticsJob } from '../models/data_frame_analytics/validation'; import { fieldServiceProvider } from '../models/job_service/new_job_caps/field_service'; -import { DeleteDataFrameAnalyticsWithIndexStatus } from '../../common/types/data_frame_analytics'; +import type { DeleteDataFrameAnalyticsWithIndexStatus } from '../../common/types/data_frame_analytics'; import { getAuthorizationHeader } from '../lib/request_authorization'; import type { MlClient } from '../lib/ml_client'; +import type { DataViewsService } from '../../../../../src/plugins/data_views/common'; -function getIndexPatternId(context: RequestHandlerContext, patternName: string) { - const iph = new IndexPatternHandler(context.core.savedObjects.client); +function getIndexPatternId(dataViewsService: DataViewsService, patternName: string) { + const iph = new IndexPatternHandler(dataViewsService); return iph.getIndexPatternId(patternName); } -function deleteDestIndexPatternById(context: RequestHandlerContext, indexPatternId: string) { - const iph = new IndexPatternHandler(context.core.savedObjects.client); +function deleteDestIndexPatternById(dataViewsService: DataViewsService, indexPatternId: string) { + const iph = new IndexPatternHandler(dataViewsService); return iph.deleteIndexPatternById(indexPatternId); } @@ -374,86 +378,89 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense, routeGuard }: Rout tags: ['access:ml:canDeleteDataFrameAnalytics'], }, }, - routeGuard.fullLicenseAPIGuard(async ({ mlClient, client, request, response, context }) => { - try { - const { analyticsId } = request.params; - const { deleteDestIndex, deleteDestIndexPattern } = request.query; - let destinationIndex: string | undefined; - const analyticsJobDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false }; - const destIndexDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false }; - const destIndexPatternDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { - success: false, - }; - + routeGuard.fullLicenseAPIGuard( + async ({ mlClient, client, request, response, getDataViewsService }) => { try { - // Check if analyticsId is valid and get destination index - const { body } = await mlClient.getDataFrameAnalytics({ - id: analyticsId, - }); - if (Array.isArray(body.data_frame_analytics) && body.data_frame_analytics.length > 0) { - destinationIndex = body.data_frame_analytics[0].dest.index; + const { analyticsId } = request.params; + const { deleteDestIndex, deleteDestIndexPattern } = request.query; + let destinationIndex: string | undefined; + const analyticsJobDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false }; + const destIndexDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { success: false }; + const destIndexPatternDeleted: DeleteDataFrameAnalyticsWithIndexStatus = { + success: false, + }; + + try { + // Check if analyticsId is valid and get destination index + const { body } = await mlClient.getDataFrameAnalytics({ + id: analyticsId, + }); + if (Array.isArray(body.data_frame_analytics) && body.data_frame_analytics.length > 0) { + destinationIndex = body.data_frame_analytics[0].dest.index; + } + } catch (e) { + // exist early if the job doesn't exist + return response.customError(wrapError(e)); } - } catch (e) { - // exist early if the job doesn't exist - return response.customError(wrapError(e)); - } - if (deleteDestIndex || deleteDestIndexPattern) { - // If user checks box to delete the destinationIndex associated with the job - if (destinationIndex && deleteDestIndex) { - // Verify if user has privilege to delete the destination index - const userCanDeleteDestIndex = await userCanDeleteIndex(client, destinationIndex); - // If user does have privilege to delete the index, then delete the index - if (userCanDeleteDestIndex) { - try { - await client.asCurrentUser.indices.delete({ - index: destinationIndex, - }); - destIndexDeleted.success = true; - } catch ({ body }) { - destIndexDeleted.error = body; + if (deleteDestIndex || deleteDestIndexPattern) { + // If user checks box to delete the destinationIndex associated with the job + if (destinationIndex && deleteDestIndex) { + // Verify if user has privilege to delete the destination index + const userCanDeleteDestIndex = await userCanDeleteIndex(client, destinationIndex); + // If user does have privilege to delete the index, then delete the index + if (userCanDeleteDestIndex) { + try { + await client.asCurrentUser.indices.delete({ + index: destinationIndex, + }); + destIndexDeleted.success = true; + } catch ({ body }) { + destIndexDeleted.error = body; + } + } else { + return response.forbidden(); } - } else { - return response.forbidden(); } - } - // Delete the index pattern if there's an index pattern that matches the name of dest index - if (destinationIndex && deleteDestIndexPattern) { - try { - const indexPatternId = await getIndexPatternId(context, destinationIndex); - if (indexPatternId) { - await deleteDestIndexPatternById(context, indexPatternId); + // Delete the index pattern if there's an index pattern that matches the name of dest index + if (destinationIndex && deleteDestIndexPattern) { + try { + const dataViewsService = await getDataViewsService(); + const indexPatternId = await getIndexPatternId(dataViewsService, destinationIndex); + if (indexPatternId) { + await deleteDestIndexPatternById(dataViewsService, indexPatternId); + } + destIndexPatternDeleted.success = true; + } catch (deleteDestIndexPatternError) { + destIndexPatternDeleted.error = deleteDestIndexPatternError; } - destIndexPatternDeleted.success = true; - } catch (deleteDestIndexPatternError) { - destIndexPatternDeleted.error = deleteDestIndexPatternError; } } - } - // Grab the target index from the data frame analytics job id - // Delete the data frame analytics + // Grab the target index from the data frame analytics job id + // Delete the data frame analytics - try { - await mlClient.deleteDataFrameAnalytics({ - id: analyticsId, + try { + await mlClient.deleteDataFrameAnalytics({ + id: analyticsId, + }); + analyticsJobDeleted.success = true; + } catch ({ body }) { + analyticsJobDeleted.error = body; + } + const results = { + analyticsJobDeleted, + destIndexDeleted, + destIndexPatternDeleted, + }; + return response.ok({ + body: results, }); - analyticsJobDeleted.success = true; - } catch ({ body }) { - analyticsJobDeleted.error = body; + } catch (e) { + return response.customError(wrapError(e)); } - const results = { - analyticsJobDeleted, - destIndexDeleted, - destIndexPatternDeleted, - }; - return response.ok({ - body: results, - }); - } catch (e) { - return response.customError(wrapError(e)); } - }) + ) ); /** @@ -716,17 +723,12 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense, routeGuard }: Rout tags: ['access:ml:canGetJobs'], }, }, - routeGuard.fullLicenseAPIGuard(async ({ client, request, response, context }) => { + routeGuard.fullLicenseAPIGuard(async ({ client, request, response, getDataViewsService }) => { try { const { indexPattern } = request.params; const isRollup = request.query?.rollup === 'true'; - const savedObjectsClient = context.core.savedObjects.client; - const fieldService = fieldServiceProvider( - indexPattern, - isRollup, - client, - savedObjectsClient - ); + const dataViewsService = await getDataViewsService(); + const fieldService = fieldServiceProvider(indexPattern, isRollup, client, dataViewsService); const { fields, aggs } = await fieldService.getData(true); convertForStringify(aggs, fields); diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index da115a224d19ec..15b0b4449590cb 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -8,7 +8,7 @@ import { estypes } from '@elastic/elasticsearch'; import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; -import { RouteInitialization } from '../types'; +import type { RouteInitialization } from '../types'; import { categorizationFieldExamplesSchema, basicChartSchema, @@ -32,7 +32,7 @@ import { jobIdSchema } from './schemas/anomaly_detectors_schema'; import { jobServiceProvider } from '../models/job_service'; import { categorizationExamplesProvider } from '../models/job_service/new_job'; import { getAuthorizationHeader } from '../lib/request_authorization'; -import { Datafeed, Job } from '../../common/types/anomaly_detection_jobs'; +import type { Datafeed, Job } from '../../common/types/anomaly_detection_jobs'; /** * Routes for job service @@ -535,21 +535,24 @@ export function jobServiceRoutes({ router, routeGuard }: RouteInitialization) { tags: ['access:ml:canGetJobs'], }, }, - routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response, context }) => { - try { - const { indexPattern } = request.params; - const isRollup = request.query?.rollup === 'true'; - const savedObjectsClient = context.core.savedObjects.client; - const { newJobCaps } = jobServiceProvider(client, mlClient); - const resp = await newJobCaps(indexPattern, isRollup, savedObjectsClient); - - return response.ok({ - body: resp, - }); - } catch (e) { - return response.customError(wrapError(e)); + routeGuard.fullLicenseAPIGuard( + async ({ client, mlClient, request, response, getDataViewsService }) => { + try { + const { indexPattern } = request.params; + const isRollup = request.query?.rollup === 'true'; + const { newJobCaps } = jobServiceProvider(client, mlClient); + + const dataViewsService = await getDataViewsService(); + const resp = await newJobCaps(indexPattern, isRollup, dataViewsService); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } } - }) + ) ); /** diff --git a/x-pack/plugins/ml/server/routes/modules.ts b/x-pack/plugins/ml/server/routes/modules.ts index 097f3f8d676527..d814e91f70ca01 100644 --- a/x-pack/plugins/ml/server/routes/modules.ts +++ b/x-pack/plugins/ml/server/routes/modules.ts @@ -5,19 +5,24 @@ * 2.0. */ -import { TypeOf } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; -import { IScopedClusterClient, KibanaRequest, SavedObjectsClientContract } from 'kibana/server'; -import { DatafeedOverride, JobOverride } from '../../common/types/modules'; +import type { + IScopedClusterClient, + KibanaRequest, + SavedObjectsClientContract, +} from 'kibana/server'; +import type { DataViewsService } from '../../../../../src/plugins/data_views/common'; +import type { DatafeedOverride, JobOverride } from '../../common/types/modules'; import { wrapError } from '../client/error_wrapper'; -import { DataRecognizer } from '../models/data_recognizer'; +import { dataRecognizerFactory } from '../models/data_recognizer'; import { moduleIdParamSchema, optionalModuleIdParamSchema, modulesIndexPatternTitleSchema, setupModuleBodySchema, } from './schemas/modules'; -import { RouteInitialization } from '../types'; +import type { RouteInitialization } from '../types'; import type { MlClient } from '../lib/ml_client'; import type { JobSavedObjectService } from '../saved_objects'; @@ -25,14 +30,16 @@ function recognize( client: IScopedClusterClient, mlClient: MlClient, savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, jobSavedObjectService: JobSavedObjectService, request: KibanaRequest, indexPatternTitle: string ) { - const dr = new DataRecognizer( + const dr = dataRecognizerFactory( client, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -43,14 +50,16 @@ function getModule( client: IScopedClusterClient, mlClient: MlClient, savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, jobSavedObjectService: JobSavedObjectService, request: KibanaRequest, moduleId?: string ) { - const dr = new DataRecognizer( + const dr = dataRecognizerFactory( client, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -65,6 +74,7 @@ function setup( client: IScopedClusterClient, mlClient: MlClient, savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, jobSavedObjectService: JobSavedObjectService, request: KibanaRequest, moduleId: string, @@ -81,10 +91,11 @@ function setup( estimateModelMemory?: boolean, applyToAllSpaces?: boolean ) { - const dr = new DataRecognizer( + const dr = dataRecognizerFactory( client, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -109,14 +120,16 @@ function dataRecognizerJobsExist( client: IScopedClusterClient, mlClient: MlClient, savedObjectsClient: SavedObjectsClientContract, + dataViewsService: DataViewsService, jobSavedObjectService: JobSavedObjectService, request: KibanaRequest, moduleId: string ) { - const dr = new DataRecognizer( + const dr = dataRecognizerFactory( client, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -166,13 +179,23 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { }, }, routeGuard.fullLicenseAPIGuard( - async ({ client, mlClient, request, response, context, jobSavedObjectService }) => { + async ({ + client, + mlClient, + request, + response, + context, + jobSavedObjectService, + getDataViewsService, + }) => { try { const { indexPatternTitle } = request.params; + const dataViewService = await getDataViewsService(); const results = await recognize( client, mlClient, context.core.savedObjects.client, + dataViewService, jobSavedObjectService, request, indexPatternTitle @@ -305,7 +328,15 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { }, }, routeGuard.fullLicenseAPIGuard( - async ({ client, mlClient, request, response, context, jobSavedObjectService }) => { + async ({ + client, + mlClient, + request, + response, + context, + jobSavedObjectService, + getDataViewsService, + }) => { try { let { moduleId } = request.params; if (moduleId === '') { @@ -313,10 +344,12 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { // the moduleId will be an empty string. moduleId = undefined; } + const dataViewService = await getDataViewsService(); const results = await getModule( client, mlClient, context.core.savedObjects.client, + dataViewService, jobSavedObjectService, request, moduleId @@ -482,7 +515,15 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { }, }, routeGuard.fullLicenseAPIGuard( - async ({ client, mlClient, request, response, context, jobSavedObjectService }) => { + async ({ + client, + mlClient, + request, + response, + context, + jobSavedObjectService, + getDataViewsService, + }) => { try { const { moduleId } = request.params; @@ -501,10 +542,13 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { applyToAllSpaces, } = request.body as TypeOf; + const dataViewService = await getDataViewsService(); + const result = await setup( client, mlClient, context.core.savedObjects.client, + dataViewService, jobSavedObjectService, request, moduleId, @@ -593,13 +637,23 @@ export function dataRecognizer({ router, routeGuard }: RouteInitialization) { }, }, routeGuard.fullLicenseAPIGuard( - async ({ client, mlClient, request, response, context, jobSavedObjectService }) => { + async ({ + client, + mlClient, + request, + response, + context, + jobSavedObjectService, + getDataViewsService, + }) => { try { const { moduleId } = request.params; + const dataViewService = await getDataViewsService(); const result = await dataRecognizerJobsExist( client, mlClient, context.core.savedObjects.client, + dataViewService, jobSavedObjectService, request, moduleId diff --git a/x-pack/plugins/ml/server/shared_services/providers/modules.ts b/x-pack/plugins/ml/server/shared_services/providers/modules.ts index c86a40e4224ce5..f6a6c58fadb4ef 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/modules.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/modules.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { IScopedClusterClient, KibanaRequest, SavedObjectsClientContract } from 'kibana/server'; -import { TypeOf } from '@kbn/config-schema'; -import { DataRecognizer } from '../../models/data_recognizer'; -import { GetGuards } from '../shared_services'; +import type { KibanaRequest, SavedObjectsClientContract } from 'kibana/server'; +import type { TypeOf } from '@kbn/config-schema'; +import type { PluginStart as DataViewsPluginStart } from '../../../../../../src/plugins/data_views/server'; +import type { GetGuards } from '../shared_services'; +import { DataRecognizer, dataRecognizerFactory } from '../../models/data_recognizer'; import { moduleIdParamSchema, setupModuleBodySchema } from '../../routes/schemas/modules'; -import { MlClient } from '../../lib/ml_client'; -import { JobSavedObjectService } from '../../saved_objects'; export type ModuleSetupPayload = TypeOf & TypeOf; @@ -28,7 +27,10 @@ export interface ModulesProvider { }; } -export function getModulesProvider(getGuards: GetGuards): ModulesProvider { +export function getModulesProvider( + getGuards: GetGuards, + getDataViews: () => DataViewsPluginStart +): ModulesProvider { return { modulesProvider(request: KibanaRequest, savedObjectsClient: SavedObjectsClientContract) { return { @@ -36,11 +38,13 @@ export function getModulesProvider(getGuards: GetGuards): ModulesProvider { return await getGuards(request, savedObjectsClient) .isFullLicense() .hasMlCapabilities(['canGetJobs']) - .ok(async ({ scopedClient, mlClient, jobSavedObjectService }) => { + .ok(async ({ scopedClient, mlClient, jobSavedObjectService, getDataViewsService }) => { + const dataViewsService = await getDataViewsService(); const dr = dataRecognizerFactory( scopedClient, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -51,11 +55,13 @@ export function getModulesProvider(getGuards: GetGuards): ModulesProvider { return await getGuards(request, savedObjectsClient) .isFullLicense() .hasMlCapabilities(['canGetJobs']) - .ok(async ({ scopedClient, mlClient, jobSavedObjectService }) => { + .ok(async ({ scopedClient, mlClient, jobSavedObjectService, getDataViewsService }) => { + const dataViewsService = await getDataViewsService(); const dr = dataRecognizerFactory( scopedClient, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -66,11 +72,13 @@ export function getModulesProvider(getGuards: GetGuards): ModulesProvider { return await getGuards(request, savedObjectsClient) .isFullLicense() .hasMlCapabilities(['canGetJobs']) - .ok(async ({ scopedClient, mlClient, jobSavedObjectService }) => { + .ok(async ({ scopedClient, mlClient, jobSavedObjectService, getDataViewsService }) => { + const dataViewsService = await getDataViewsService(); const dr = dataRecognizerFactory( scopedClient, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -81,11 +89,13 @@ export function getModulesProvider(getGuards: GetGuards): ModulesProvider { return await getGuards(request, savedObjectsClient) .isFullLicense() .hasMlCapabilities(['canCreateJob']) - .ok(async ({ scopedClient, mlClient, jobSavedObjectService }) => { + .ok(async ({ scopedClient, mlClient, jobSavedObjectService, getDataViewsService }) => { + const dataViewsService = await getDataViewsService(); const dr = dataRecognizerFactory( scopedClient, mlClient, savedObjectsClient, + dataViewsService, jobSavedObjectService, request ); @@ -109,13 +119,3 @@ export function getModulesProvider(getGuards: GetGuards): ModulesProvider { }, }; } - -function dataRecognizerFactory( - client: IScopedClusterClient, - mlClient: MlClient, - savedObjectsClient: SavedObjectsClientContract, - jobSavedObjectService: JobSavedObjectService, - request: KibanaRequest -) { - return new DataRecognizer(client, mlClient, savedObjectsClient, jobSavedObjectService, request); -} diff --git a/x-pack/plugins/ml/server/shared_services/shared_services.ts b/x-pack/plugins/ml/server/shared_services/shared_services.ts index 5c8bbffe10aedd..9c8ab1e069258c 100644 --- a/x-pack/plugins/ml/server/shared_services/shared_services.ts +++ b/x-pack/plugins/ml/server/shared_services/shared_services.ts @@ -5,17 +5,18 @@ * 2.0. */ -import { +import type { IClusterClient, IScopedClusterClient, SavedObjectsClientContract, UiSettingsServiceStart, } from 'kibana/server'; -import { SpacesPluginStart } from '../../../spaces/server'; +import type { SpacesPluginStart } from '../../../spaces/server'; import { KibanaRequest } from '../../.././../../src/core/server'; import { MlLicense } from '../../common/license'; import type { CloudSetup } from '../../../cloud/server'; +import type { PluginStart as DataViewsPluginStart } from '../../../../../src/plugins/data_views/server'; import type { SecurityPluginSetup } from '../../../security/server'; import { licenseChecks } from './license_checks'; import { MlSystemProvider, getMlSystemProvider } from './providers/system'; @@ -26,7 +27,7 @@ import { AnomalyDetectorsProvider, getAnomalyDetectorsProvider, } from './providers/anomaly_detectors'; -import { ResolveMlCapabilities, MlCapabilitiesKey } from '../../common/types/capabilities'; +import type { ResolveMlCapabilities, MlCapabilitiesKey } from '../../common/types/capabilities'; import { hasMlCapabilitiesProvider, HasMlCapabilities } from '../lib/capabilities'; import { MLClusterClientUninitialized, @@ -45,6 +46,7 @@ import { } from '../lib/alerts/jobs_health_service'; import type { FieldFormatsStart } from '../../../../../src/plugins/field_formats/server'; import type { FieldFormatsRegistryProvider } from '../../common/types/kibana'; +import { getDataViewsServiceFactory, GetDataViewsService } from '../lib/data_views_utils'; export type SharedServices = JobServiceProvider & AnomalyDetectorsProvider & @@ -76,6 +78,7 @@ interface OkParams { mlClient: MlClient; jobSavedObjectService: JobSavedObjectService; getFieldsFormatRegistry: FieldFormatsRegistryProvider; + getDataViewsService: GetDataViewsService; } type OkCallback = (okParams: OkParams) => any; @@ -90,6 +93,7 @@ export function createSharedServices( getInternalSavedObjectsClient: () => SavedObjectsClientContract | null, getUiSettings: () => UiSettingsServiceStart | null, getFieldsFormat: () => FieldFormatsStart | null, + getDataViews: () => DataViewsPluginStart, isMlReady: () => Promise ): { sharedServicesProviders: SharedServices; @@ -101,6 +105,7 @@ export function createSharedServices( savedObjectsClient: SavedObjectsClientContract ): Guards { const internalSavedObjectsClient = getInternalSavedObjectsClient(); + if (internalSavedObjectsClient === null) { throw new Error('Internal saved object client not initialized'); } @@ -113,7 +118,8 @@ export function createSharedServices( getSpaces !== undefined, isMlReady, getUiSettings, - getFieldsFormat + getFieldsFormat, + getDataViews ); const { @@ -122,6 +128,7 @@ export function createSharedServices( mlClient, jobSavedObjectService, getFieldsFormatRegistry, + getDataViewsService, } = getRequestItems(request); const asyncGuards: Array> = []; @@ -140,7 +147,13 @@ export function createSharedServices( }, async ok(callback: OkCallback) { await Promise.all(asyncGuards); - return callback({ scopedClient, mlClient, jobSavedObjectService, getFieldsFormatRegistry }); + return callback({ + scopedClient, + mlClient, + jobSavedObjectService, + getFieldsFormatRegistry, + getDataViewsService, + }); }, }; return guards; @@ -153,7 +166,7 @@ export function createSharedServices( sharedServicesProviders: { ...getJobServiceProvider(getGuards), ...getAnomalyDetectorsProvider(getGuards), - ...getModulesProvider(getGuards), + ...getModulesProvider(getGuards, getDataViews), ...getResultsServiceProvider(getGuards), ...getMlSystemProvider(getGuards, mlLicense, getSpaces, cloud, resolveMlCapabilities), ...getAlertingServiceProvider(getGuards), @@ -176,7 +189,8 @@ function getRequestItemsProvider( spaceEnabled: boolean, isMlReady: () => Promise, getUiSettings: () => UiSettingsServiceStart | null, - getFieldsFormat: () => FieldFormatsStart | null + getFieldsFormat: () => FieldFormatsStart | null, + getDataViews: () => DataViewsPluginStart ) { return (request: KibanaRequest) => { const getHasMlCapabilities = hasMlCapabilitiesProvider(resolveMlCapabilities); @@ -234,12 +248,20 @@ function getRequestItemsProvider( }; mlClient = getMlClient(scopedClient, jobSavedObjectService); } + + const getDataViewsService = getDataViewsServiceFactory( + getDataViews, + savedObjectsClient, + scopedClient + ); + return { hasMlCapabilities, scopedClient, mlClient, jobSavedObjectService, getFieldsFormatRegistry, + getDataViewsService, }; }; } diff --git a/x-pack/plugins/ml/server/types.ts b/x-pack/plugins/ml/server/types.ts index da83b03766af4a..d5c67bf99a7a0d 100644 --- a/x-pack/plugins/ml/server/types.ts +++ b/x-pack/plugins/ml/server/types.ts @@ -23,6 +23,7 @@ import type { PluginSetup as DataPluginSetup, PluginStart as DataPluginStart, } from '../../../../src/plugins/data/server'; +import type { PluginStart as DataViewsPluginStart } from '../../../../src/plugins/data_views/server'; import type { FieldFormatsSetup, FieldFormatsStart, @@ -64,6 +65,7 @@ export interface PluginsSetup { export interface PluginsStart { data: DataPluginStart; + dataViews: DataViewsPluginStart; fieldFormats: FieldFormatsStart; spaces?: SpacesPluginStart; } diff --git a/x-pack/plugins/ml/tsconfig.json b/x-pack/plugins/ml/tsconfig.json index db8fc463b05508..0c108f8b3b8a50 100644 --- a/x-pack/plugins/ml/tsconfig.json +++ b/x-pack/plugins/ml/tsconfig.json @@ -21,6 +21,7 @@ { "path": "../../../src/core/tsconfig.json" }, { "path": "../../../src/plugins/embeddable/tsconfig.json" }, { "path": "../../../src/plugins/index_pattern_management/tsconfig.json" }, + { "path": "../../../src/plugins/data_views/tsconfig.json" }, { "path": "../cloud/tsconfig.json" }, { "path": "../features/tsconfig.json" }, { "path": "../data_visualizer/tsconfig.json"},