Timelion reads raw field list from saved object, should grab from index pattern api (#89988)
* Timelion reads raw field list from saved object, should grab from index pattern api Closes: #84387 * fix PR comment
This commit is contained in:
parent
14cf1875b5
commit
af454d61bf
|
@ -8,14 +8,12 @@
|
||||||
|
|
||||||
import { SUGGESTION_TYPE, suggest } from './timelion_expression_input_helpers';
|
import { SUGGESTION_TYPE, suggest } from './timelion_expression_input_helpers';
|
||||||
import { getArgValueSuggestions } from '../helpers/arg_value_suggestions';
|
import { getArgValueSuggestions } from '../helpers/arg_value_suggestions';
|
||||||
import { setIndexPatterns, setSavedObjectsClient } from '../helpers/plugin_services';
|
import { setIndexPatterns } from '../helpers/plugin_services';
|
||||||
import { IndexPatternsContract } from 'src/plugins/data/public';
|
import { IndexPatternsContract } from 'src/plugins/data/public';
|
||||||
import { SavedObjectsClient } from 'kibana/public';
|
|
||||||
import { ITimelionFunction } from '../../common/types';
|
import { ITimelionFunction } from '../../common/types';
|
||||||
|
|
||||||
describe('Timelion expression suggestions', () => {
|
describe('Timelion expression suggestions', () => {
|
||||||
setIndexPatterns({} as IndexPatternsContract);
|
setIndexPatterns({} as IndexPatternsContract);
|
||||||
setSavedObjectsClient({} as SavedObjectsClient);
|
|
||||||
|
|
||||||
const argValueSuggestions = getArgValueSuggestions();
|
const argValueSuggestions = getArgValueSuggestions();
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { getIndexPatterns, getSavedObjectsClient } from './plugin_services';
|
import { getIndexPatterns } from './plugin_services';
|
||||||
import { TimelionFunctionArgs } from '../../common/types';
|
import { TimelionFunctionArgs } from '../../common/types';
|
||||||
import { indexPatterns as indexPatternsUtils, IndexPatternAttributes } from '../../../data/public';
|
import { indexPatterns as indexPatternsUtils } from '../../../data/public';
|
||||||
|
|
||||||
export interface Location {
|
export interface Location {
|
||||||
min: number;
|
min: number;
|
||||||
|
@ -32,7 +32,6 @@ export interface FunctionArg {
|
||||||
|
|
||||||
export function getArgValueSuggestions() {
|
export function getArgValueSuggestions() {
|
||||||
const indexPatterns = getIndexPatterns();
|
const indexPatterns = getIndexPatterns();
|
||||||
const savedObjectsClient = getSavedObjectsClient();
|
|
||||||
|
|
||||||
async function getIndexPattern(functionArgs: FunctionArg[]) {
|
async function getIndexPattern(functionArgs: FunctionArg[]) {
|
||||||
const indexPatternArg = functionArgs.find(({ name }) => name === 'index');
|
const indexPatternArg = functionArgs.find(({ name }) => name === 'index');
|
||||||
|
@ -42,22 +41,9 @@ export function getArgValueSuggestions() {
|
||||||
}
|
}
|
||||||
const indexPatternTitle = get(indexPatternArg, 'value.text');
|
const indexPatternTitle = get(indexPatternArg, 'value.text');
|
||||||
|
|
||||||
const { savedObjects } = await savedObjectsClient.find<IndexPatternAttributes>({
|
return (await indexPatterns.find(indexPatternTitle)).find(
|
||||||
type: 'index-pattern',
|
(index) => index.title === indexPatternTitle
|
||||||
fields: ['title'],
|
|
||||||
search: `"${indexPatternTitle}"`,
|
|
||||||
searchFields: ['title'],
|
|
||||||
perPage: 10,
|
|
||||||
});
|
|
||||||
const indexPatternSavedObject = savedObjects.find(
|
|
||||||
({ attributes }) => attributes.title === indexPatternTitle
|
|
||||||
);
|
);
|
||||||
if (!indexPatternSavedObject) {
|
|
||||||
// index argument does not match an index pattern
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await indexPatterns.get(indexPatternSavedObject.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function containsFieldName(partial: string, field: { name: string }) {
|
function containsFieldName(partial: string, field: { name: string }) {
|
||||||
|
@ -73,18 +59,11 @@ export function getArgValueSuggestions() {
|
||||||
es: {
|
es: {
|
||||||
async index(partial: string) {
|
async index(partial: string) {
|
||||||
const search = partial ? `${partial}*` : '*';
|
const search = partial ? `${partial}*` : '*';
|
||||||
const resp = await savedObjectsClient.find<IndexPatternAttributes>({
|
const size = 25;
|
||||||
type: 'index-pattern',
|
|
||||||
fields: ['title', 'type'],
|
return (await indexPatterns.find(search, size)).map(({ title }) => ({
|
||||||
search: `${search}`,
|
name: title,
|
||||||
searchFields: ['title'],
|
}));
|
||||||
perPage: 25,
|
|
||||||
});
|
|
||||||
return resp.savedObjects
|
|
||||||
.filter((savedObject) => !savedObject.get('type'))
|
|
||||||
.map((savedObject) => {
|
|
||||||
return { name: savedObject.attributes.title };
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
async metric(partial: string, functionArgs: FunctionArg[]) {
|
async metric(partial: string, functionArgs: FunctionArg[]) {
|
||||||
if (!partial || !partial.includes(':')) {
|
if (!partial || !partial.includes(':')) {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { IndexPatternsContract, ISearchStart } from 'src/plugins/data/public';
|
import type { IndexPatternsContract, ISearchStart } from 'src/plugins/data/public';
|
||||||
import type { SavedObjectsClientContract } from 'kibana/public';
|
|
||||||
import { createGetterSetter } from '../../../kibana_utils/public';
|
import { createGetterSetter } from '../../../kibana_utils/public';
|
||||||
|
|
||||||
export const [getIndexPatterns, setIndexPatterns] = createGetterSetter<IndexPatternsContract>(
|
export const [getIndexPatterns, setIndexPatterns] = createGetterSetter<IndexPatternsContract>(
|
||||||
|
@ -15,8 +14,3 @@ export const [getIndexPatterns, setIndexPatterns] = createGetterSetter<IndexPatt
|
||||||
);
|
);
|
||||||
|
|
||||||
export const [getDataSearch, setDataSearch] = createGetterSetter<ISearchStart>('Search');
|
export const [getDataSearch, setDataSearch] = createGetterSetter<ISearchStart>('Search');
|
||||||
|
|
||||||
export const [
|
|
||||||
getSavedObjectsClient,
|
|
||||||
setSavedObjectsClient,
|
|
||||||
] = createGetterSetter<SavedObjectsClientContract>('SavedObjectsClient');
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { VisualizationsSetup } from '../../visualizations/public';
|
||||||
|
|
||||||
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
|
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
|
||||||
import { getTimelionVisDefinition } from './timelion_vis_type';
|
import { getTimelionVisDefinition } from './timelion_vis_type';
|
||||||
import { setIndexPatterns, setSavedObjectsClient, setDataSearch } from './helpers/plugin_services';
|
import { setIndexPatterns, setDataSearch } from './helpers/plugin_services';
|
||||||
import { ConfigSchema } from '../config';
|
import { ConfigSchema } from '../config';
|
||||||
|
|
||||||
import { getArgValueSuggestions } from './helpers/arg_value_suggestions';
|
import { getArgValueSuggestions } from './helpers/arg_value_suggestions';
|
||||||
|
@ -92,7 +92,6 @@ export class TimelionVisPlugin
|
||||||
|
|
||||||
public start(core: CoreStart, plugins: TimelionVisStartDependencies) {
|
public start(core: CoreStart, plugins: TimelionVisStartDependencies) {
|
||||||
setIndexPatterns(plugins.data.indexPatterns);
|
setIndexPatterns(plugins.data.indexPatterns);
|
||||||
setSavedObjectsClient(core.savedObjects.client);
|
|
||||||
setDataSearch(plugins.data.search);
|
setDataSearch(plugins.data.search);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -46,7 +46,9 @@ export interface TimelionPluginStartDeps {
|
||||||
export class Plugin {
|
export class Plugin {
|
||||||
constructor(private readonly initializerContext: PluginInitializerContext) {}
|
constructor(private readonly initializerContext: PluginInitializerContext) {}
|
||||||
|
|
||||||
public async setup(core: CoreSetup): Promise<RecursiveReadonly<PluginSetupContract>> {
|
public async setup(
|
||||||
|
core: CoreSetup<TimelionPluginStartDeps>
|
||||||
|
): Promise<RecursiveReadonly<PluginSetupContract>> {
|
||||||
const config = await this.initializerContext.config
|
const config = await this.initializerContext.config
|
||||||
.create<TypeOf<typeof configSchema>>()
|
.create<TypeOf<typeof configSchema>>()
|
||||||
.pipe(first())
|
.pipe(first())
|
||||||
|
|
|
@ -18,6 +18,7 @@ import getNamespacesSettings from '../lib/get_namespaced_settings';
|
||||||
import getTlConfig from '../handlers/lib/tl_config';
|
import getTlConfig from '../handlers/lib/tl_config';
|
||||||
import { TimelionFunctionInterface } from '../types';
|
import { TimelionFunctionInterface } from '../types';
|
||||||
import { ConfigManager } from '../lib/config_manager';
|
import { ConfigManager } from '../lib/config_manager';
|
||||||
|
import { TimelionPluginStartDeps } from '../plugin';
|
||||||
|
|
||||||
const timelionDefaults = getNamespacesSettings();
|
const timelionDefaults = getNamespacesSettings();
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ export function runRoute(
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
getFunction: (name: string) => TimelionFunctionInterface;
|
getFunction: (name: string) => TimelionFunctionInterface;
|
||||||
configManager: ConfigManager;
|
configManager: ConfigManager;
|
||||||
core: CoreSetup;
|
core: CoreSetup<TimelionPluginStartDeps>;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
router.post(
|
router.post(
|
||||||
|
@ -77,17 +78,22 @@ export function runRoute(
|
||||||
},
|
},
|
||||||
router.handleLegacyErrors(async (context, request, response) => {
|
router.handleLegacyErrors(async (context, request, response) => {
|
||||||
try {
|
try {
|
||||||
|
const [, { data }] = await core.getStartServices();
|
||||||
const uiSettings = await context.core.uiSettings.client.getAll();
|
const uiSettings = await context.core.uiSettings.client.getAll();
|
||||||
|
const indexPatternsService = await data.indexPatterns.indexPatternsServiceFactory(
|
||||||
|
context.core.savedObjects.client,
|
||||||
|
context.core.elasticsearch.client.asCurrentUser
|
||||||
|
);
|
||||||
|
|
||||||
const tlConfig = getTlConfig({
|
const tlConfig = getTlConfig({
|
||||||
context,
|
context,
|
||||||
request,
|
request,
|
||||||
settings: _.defaults(uiSettings, timelionDefaults), // Just in case they delete some setting.
|
settings: _.defaults(uiSettings, timelionDefaults), // Just in case they delete some setting.
|
||||||
getFunction,
|
getFunction,
|
||||||
|
getIndexPatternsService: () => indexPatternsService,
|
||||||
getStartServices: core.getStartServices,
|
getStartServices: core.getStartServices,
|
||||||
allowedGraphiteUrls: configManager.getGraphiteUrls(),
|
allowedGraphiteUrls: configManager.getGraphiteUrls(),
|
||||||
esShardTimeout: configManager.getEsShardTimeout(),
|
esShardTimeout: configManager.getEsShardTimeout(),
|
||||||
savedObjectsClient: context.core.savedObjects.client,
|
|
||||||
});
|
});
|
||||||
const chainRunner = chainRunnerFn(tlConfig);
|
const chainRunner = chainRunnerFn(tlConfig);
|
||||||
const sheet = await Bluebird.all(chainRunner.processRequest(request.body));
|
const sheet = await Bluebird.all(chainRunner.processRequest(request.body));
|
||||||
|
|
|
@ -22,16 +22,12 @@ import { UI_SETTINGS } from '../../../../data/server';
|
||||||
describe('es', () => {
|
describe('es', () => {
|
||||||
let tlConfig;
|
let tlConfig;
|
||||||
|
|
||||||
function stubRequestAndServer(response, indexPatternSavedObjects = []) {
|
function stubRequestAndServer(response) {
|
||||||
return {
|
return {
|
||||||
context: { search: { search: jest.fn().mockReturnValue(of(response)) } },
|
context: { search: { search: jest.fn().mockReturnValue(of(response)) } },
|
||||||
savedObjectsClient: {
|
getIndexPatternsService: () => ({
|
||||||
find: function () {
|
find: async () => [],
|
||||||
return Promise.resolve({
|
}),
|
||||||
saved_objects: indexPatternSavedObjects,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,23 +96,12 @@ export default new Datasource('es', {
|
||||||
kibana: true,
|
kibana: true,
|
||||||
fit: 'nearest',
|
fit: 'nearest',
|
||||||
});
|
});
|
||||||
|
const indexPatternsService = tlConfig.getIndexPatternsService();
|
||||||
|
const indexPatternSpec = (await indexPatternsService.find(config.index)).find(
|
||||||
|
(index) => index.title === config.index
|
||||||
|
);
|
||||||
|
|
||||||
const findResp = await tlConfig.savedObjectsClient.find({
|
const scriptedFields = indexPatternSpec?.getScriptedFields() ?? [];
|
||||||
type: 'index-pattern',
|
|
||||||
fields: ['title', 'fields'],
|
|
||||||
search: `"${config.index}"`,
|
|
||||||
search_fields: ['title'],
|
|
||||||
});
|
|
||||||
const indexPatternSavedObject = findResp.saved_objects.find((savedObject) => {
|
|
||||||
return savedObject.attributes.title === config.index;
|
|
||||||
});
|
|
||||||
let scriptedFields = [];
|
|
||||||
if (indexPatternSavedObject) {
|
|
||||||
const fields = JSON.parse(indexPatternSavedObject.attributes.fields);
|
|
||||||
scriptedFields = fields.filter((field) => {
|
|
||||||
return field.scripted;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const esShardTimeout = tlConfig.esShardTimeout;
|
const esShardTimeout = tlConfig.esShardTimeout;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue