Skip to content

Commit

Permalink
added a new dataViews endpoint and updated the hasData service
Browse files Browse the repository at this point in the history
  • Loading branch information
shivindera committed Mar 8, 2022
1 parent 76653ae commit dae01c2
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import { EmptyIndexPatternPrompt } from './empty_index_pattern_prompt';
import { PromptFooter } from './prompt_footer';
import { FLEET_ASSETS_TO_IGNORE } from '../../../../data/common';

const removeAliases = (item: MatchedItem) =>
!(item as unknown as ResolveIndexResponseItemAlias).indices;
const removeAliases = (mItem: MatchedItem) => !mItem.item.indices;

interface Props {
onCancel: () => void;
Expand Down
15 changes: 0 additions & 15 deletions src/plugins/data_view_editor/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,6 @@ export interface IndexPatternTableItem {
sort: string;
}

// copied from index pattern management, needs review
export interface MatchedItem {
name: string;
tags: Tag[];
item: {
name: string;
backing_indices?: string[];
timestamp_field?: string;
indices?: string[];
aliases?: string[];
attributes?: ResolveIndexResponseItemIndexAttrs[];
data_stream?: string;
};
}

export enum ResolveIndexResponseItemIndexAttrs {
OPEN = 'open',
CLOSED = 'closed',
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data_views/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type {
DataViewFieldMap,
DataViewSpec,
SourceFilter,
HasDataService,
} from './types';
export { DataViewType } from './types';
export type { IndexPatternsContract, DataViewsContract } from './data_views';
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data_views/public/data_views_service_public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { DataViewsService } from '.';

import { DataViewsServiceDeps } from '../common/data_views/data_views';
import { HasDataService } from '../common/types';
import { HasDataService } from '../common';

interface DataViewsServicePublicDeps extends DataViewsServiceDeps {
getCanSaveSync: () => boolean;
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/data_views/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ export type {
DataViewsPublicPluginSetup,
DataViewsPublicPluginStart,
DataViewsContract,
HasDataViewsResponse,
IndicesResponse,
IndicesResponseModified,
} from './types';

// Export plugin after all other imports
Expand Down
5 changes: 1 addition & 4 deletions src/plugins/data_views/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,8 @@ export class DataViewsPublicPlugin
{ fieldFormats }: DataViewsPublicStartDependencies
): DataViewsPublicPluginStart {
const { uiSettings, http, notifications, savedObjects, theme, overlays, application } = core;
const hasDataStart = this.hasData.start(core);
console.log(core);
console.log({ hasDataStart });
return new DataViewsServicePublic({
hasData: { ...hasDataStart },
hasData: this.hasData.start(core),
uiSettings: new UiSettingsPublicToCommon(uiSettings),
savedObjectsClient: new SavedObjectsClientPublicToCommon(savedObjects.client),
apiClient: new DataViewsApiClient(http),
Expand Down
122 changes: 75 additions & 47 deletions src/plugins/data_views/public/services/has_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,21 @@
* Side Public License, v 1.
*/

import { CoreStart, HttpSetup } from 'kibana/public';
import {
MatchedItem,
ResolveIndexResponseItemAlias,
} from 'src/plugins/data_view_editor/public/types';
import { getIndices } from '../../../data_view_editor/public/lib';

const FLEET_ASSETS_TO_IGNORE = {
LOGS_INDEX_PATTERN: 'logs-*',
METRICS_INDEX_PATTERN: 'metrics-*',
LOGS_DATA_STREAM_TO_IGNORE: 'logs-elastic_agent', // ignore ds created by Fleet server itself
METRICS_DATA_STREAM_TO_IGNORE: 'metrics-elastic_agent', // ignore ds created by Fleet server itself
METRICS_ENDPOINT_INDEX_TO_IGNORE: 'metrics-endpoint.metadata_current_default', // ignore index created by Fleet endpoint package installed by default in Cloud
};
import { CoreStart, HttpStart } from 'kibana/public';
import { FLEET_ASSETS_TO_IGNORE } from '../../common';
import { HasDataViewsResponse, IndicesResponse, IndicesResponseModified } from '../';

export class HasData {
private removeAliases = (item: MatchedItem) =>
!(item as unknown as ResolveIndexResponseItemAlias).indices;
private removeAliases = (source: IndicesResponseModified): boolean => !source.item.indices;

private isUserDataIndex = (source: MatchedItem) => {
private isUserDataIndex = (source: IndicesResponseModified): boolean => {
// filter out indices that start with `.`
if (source.name.startsWith('.')) return false;

// filter out sources from FLEET_ASSETS_TO_IGNORE
if (source.name === FLEET_ASSETS_TO_IGNORE.LOGS_DATA_STREAM_TO_IGNORE) return false;
if (source.name === FLEET_ASSETS_TO_IGNORE.METRICS_DATA_STREAM_TO_IGNORE) return false;
if (source.name === FLEET_ASSETS_TO_IGNORE.METRICS_ENDPOINT_INDEX_TO_IGNORE) return false;
for (const key in FLEET_ASSETS_TO_IGNORE) {
if (source.name === (FLEET_ASSETS_TO_IGNORE as any)[key]) return false;
}

// filter out empty sources created by apm server
if (source.name.startsWith('apm-')) return false;
Expand All @@ -46,7 +34,7 @@ export class HasData {
/**
* Check to see if ES data exists
*/
hasESData: async () => {
hasESData: async (): Promise<boolean> => {
const hasLocalESData = await this.checkLocalESData(http);
if (!hasLocalESData) {
const hasRemoteESData = await this.checkRemoteESData(http);
Expand All @@ -55,55 +43,95 @@ export class HasData {
return hasLocalESData;
},
/**
* Check to see if user created data views exist
* Check to see if any data view exists
*/
hasUserDataView: async () => {
const hasLocalESData = await this.findUserDataViews();
return hasLocalESData;
hasDataView: async (): Promise<boolean> => {
const dataViewsCheck = await this.findDataViews(http);
return dataViewsCheck;
},
/**
* Check to see if any data view exists
* Check to see if user created data views exist
*/
hasDataView: async () => {
const hasLocalESData = await this.findDataViews();
return hasLocalESData;
hasUserDataView: async (): Promise<boolean> => {
const userDataViewsCheck = await this.findUserDataViews(http);
return userDataViewsCheck;
},
};
}

private checkLocalESData = (http: HttpSetup) => {
return getIndices({
// ES Data

private responseToItemArray = (response: IndicesResponse): IndicesResponseModified[] => {
const { indices = [], aliases = [] } = response;
const source: IndicesResponseModified[] = [];

[...indices, ...aliases, ...(response.data_streams || [])].forEach((item) => {
source.push({
name: item.name,
item,
});
});

return source;
};

private getIndices = async ({
http,
pattern,
showAllIndices,
}: {
http: HttpStart;
pattern: string;
showAllIndices: boolean;
}): Promise<IndicesResponseModified[]> =>
http
.get<IndicesResponse>(`/internal/index-pattern-management/resolve_index/${pattern}`, {
query: showAllIndices ? { expand_wildcards: 'all' } : undefined,
})
.then((response) => {
if (!response) {
return [];
} else {
return this.responseToItemArray(response);
}
});

private checkLocalESData = (http: HttpStart): Promise<boolean> =>
this.getIndices({
http,
isRollupIndex: () => false,
pattern: '*',
showAllIndices: false,
searchClient: data.search.search,
}).then((dataSources) => {
}).then((dataSources: IndicesResponseModified[]) => {
return dataSources.some(this.isUserDataIndex);
});
};

private checkRemoteESData = (http: HttpSetup) => {
return getIndices({
private checkRemoteESData = (http: HttpStart): Promise<boolean> =>
this.getIndices({
http,
isRollupIndex: () => false,
pattern: '*:*',
showAllIndices: false,
searchClient: data.search.search,
}).then((dataSources) => {
}).then((dataSources: IndicesResponseModified[]) => {
return !!dataSources.filter(this.removeAliases).length;
});
};

private findDataViews = () => {
return Promise.resolve(true);
// Data Views

private getHasDataViews = async ({ http }: { http: HttpStart }): Promise<HasDataViewsResponse> =>
http.get<HasDataViewsResponse>(`/internal/index_patterns/has_data_views`);

private findDataViews = (http: HttpStart): Promise<boolean> => {
return this.getHasDataViews({ http }).then((response: HasDataViewsResponse) => {
const { hasDataView } = response;
return hasDataView;
});
};

private findUserDataViews = () => {
return Promise.resolve(true);
private findUserDataViews = (http: HttpStart): Promise<boolean> => {
return this.getHasDataViews({ http }).then((response: HasDataViewsResponse) => {
const { hasUserDataView } = response;
return hasUserDataView;
});
};
}

export type HasDataStart = ReturnType<HasData['start']>;

// searchClient: data.search.search,
58 changes: 54 additions & 4 deletions src/plugins/data_views/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,57 @@ import { ExpressionsSetup } from 'src/plugins/expressions/public';
import { FieldFormatsSetup, FieldFormatsStart } from 'src/plugins/field_formats/public';
import { PublicMethodsOf } from '@kbn/utility-types';
import { DataViewsService } from './data_views';
import { HasDataService } from '../common/types';
import { HasDataService } from '../common';

export enum IndicesResponseItemIndexAttrs {
OPEN = 'open',
CLOSED = 'closed',
HIDDEN = 'hidden',
FROZEN = 'frozen',
}

export interface IndicesResponseModified {
name: string;
item: {
name: string;
backing_indices?: string[];
timestamp_field?: string;
indices?: string[];
aliases?: string[];
attributes?: IndicesResponseItemIndexAttrs[];
data_stream?: string;
};
}

export interface IndicesResponseItem {
name: string;
}

export interface IndicesResponseItemAlias extends IndicesResponseItem {
indices: string[];
}

export interface IndicesResponseItemDataStream extends IndicesResponseItem {
backing_indices: string[];
timestamp_field: string;
}

export interface IndicesResponseItemIndex extends IndicesResponseItem {
aliases?: string[];
attributes?: IndicesResponseItemIndexAttrs[];
data_stream?: string;
}

export interface IndicesResponse {
indices?: IndicesResponseItemIndex[];
aliases?: IndicesResponseItemAlias[];
data_streams?: IndicesResponseItemDataStream[];
}

export interface HasDataViewsResponse {
hasDataView: boolean;
hasUserDataView: boolean;
}

export interface DataViewsPublicSetupDependencies {
expressions: ExpressionsSetup;
Expand All @@ -27,14 +77,14 @@ export interface DataViewsPublicStartDependencies {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataViewsPublicPluginSetup {}

export interface DataViewsServicePublic extends DataViewsService {
export interface DataViewsServicePublic extends PublicMethodsOf<DataViewsService> {
getCanSaveSync: () => boolean;
hasData: HasDataService;
}

export type DataViewsContract = PublicMethodsOf<DataViewsServicePublic>;
export type DataViewsContract = DataViewsServicePublic;

/**
* Data views plugin public Start contract
*/
export type DataViewsPublicPluginStart = PublicMethodsOf<DataViewsServicePublic>;
export type DataViewsPublicPluginStart = DataViewsServicePublic;
26 changes: 20 additions & 6 deletions src/plugins/data_views/server/has_user_index_pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
* Side Public License, v 1.
*/

import { ElasticsearchClient, SavedObjectsClientContract } from '../../../core/server';
import {
ElasticsearchClient,
SavedObjectsClientContract,
SavedObjectsFindResponse,
} from '../../../core/server';
import { IndexPatternSavedObjectAttrs } from '../common/data_views';
import { FLEET_ASSETS_TO_IGNORE } from '../common/constants';

Expand All @@ -15,19 +19,31 @@ interface Deps {
soClient: SavedObjectsClientContract;
}

export const hasUserIndexPattern = async ({ esClient, soClient }: Deps): Promise<boolean> => {
const indexPatterns = await soClient.find<IndexPatternSavedObjectAttrs>({
export const hasIndexPattern = async ({
esClient,
soClient,
}: Deps): Promise<SavedObjectsFindResponse<IndexPatternSavedObjectAttrs, unknown>> =>
soClient.find<IndexPatternSavedObjectAttrs>({
type: 'index-pattern',
fields: ['title'],
search: `*`,
searchFields: ['title'],
perPage: 100,
});

export const hasUserIndexPattern = async (
{ esClient, soClient }: Deps,
iPatterns?: SavedObjectsFindResponse<IndexPatternSavedObjectAttrs, unknown>
): Promise<boolean> => {
let indexPatterns = iPatterns;

if (!indexPatterns) {
indexPatterns = await hasIndexPattern({ esClient, soClient });
}

if (indexPatterns.total === 0) {
return false;
}

// If there are any index patterns that are not the default metrics-* and logs-* ones created by Fleet,
// assume there are user created index patterns
if (
Expand All @@ -49,14 +65,12 @@ export const hasUserIndexPattern = async ({ esClient, soClient }: Deps): Promise
);

if (hasAnyNonDefaultFleetIndices) return true;

const hasAnyNonDefaultFleetDataStreams = resolveResponse.data_streams.some(
(ds) =>
ds.name !== FLEET_ASSETS_TO_IGNORE.METRICS_DATA_STREAM_TO_IGNORE &&
ds.name !== FLEET_ASSETS_TO_IGNORE.LOGS_DATA_STREAM_TO_IGNORE
);

if (hasAnyNonDefaultFleetDataStreams) return true;

return false;
};
Loading

0 comments on commit dae01c2

Please sign in to comment.