From 9472bd17198e571f011565a199ec21cd0a88c88f Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 25 Feb 2021 16:13:27 -0700 Subject: [PATCH] [kbn/test] add import/export support to KbnClient (#92526) Co-authored-by: Tre' Seymour Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: spalger --- package.json | 1 + packages/kbn-dev-utils/src/index.ts | 1 - .../src/actions/empty_kibana_index.ts | 3 +- packages/kbn-es-archiver/src/actions/load.ts | 3 +- .../kbn-es-archiver/src/actions/unload.ts | 3 +- packages/kbn-es-archiver/src/cli.ts | 4 +- packages/kbn-es-archiver/src/es_archiver.ts | 3 +- .../src/lib/indices/kibana_index.ts | 3 +- .../lib/config/schema.ts | 7 + packages/kbn-test/src/index.ts | 4 + packages/kbn-test/src/kbn_archiver_cli.ts | 149 ++++++++++++++++ .../src/kbn_client/index.ts | 0 .../src/kbn_client/kbn_client.ts | 12 +- .../kbn_client/kbn_client_import_export.ts | 163 ++++++++++++++++++ .../src/kbn_client/kbn_client_plugins.ts | 0 .../src/kbn_client/kbn_client_requester.ts | 9 +- .../kbn_client/kbn_client_saved_objects.ts | 102 ++++++++++- .../src/kbn_client/kbn_client_status.ts | 0 .../src/kbn_client/kbn_client_ui_settings.ts | 2 +- .../src/kbn_client/kbn_client_version.ts | 0 scripts/kbn_archiver.js | 10 ++ .../services/kibana_server/kibana_server.ts | 3 +- test/common/services/security/role.ts | 3 +- .../common/services/security/role_mappings.ts | 3 +- test/common/services/security/user.ts | 3 +- test/functional/apps/discover/_discover.ts | 5 +- .../fixtures/kbn_archiver/discover.json | 51 ++++++ .../case/server/scripts/sub_cases/index.ts | 3 +- .../common/endpoint/index_data.ts | 2 +- .../kbn_client_with_api_key_support.ts | 2 +- .../endpoint/resolver_generator_script.ts | 3 +- .../scripts/endpoint/trusted_apps/index.ts | 3 +- .../detection_engine_api_integration/utils.ts | 2 +- yarn.lock | 9 + 34 files changed, 546 insertions(+), 25 deletions(-) create mode 100644 packages/kbn-test/src/kbn_archiver_cli.ts rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/index.ts (100%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client.ts (87%) create mode 100644 packages/kbn-test/src/kbn_client/kbn_client_import_export.ts rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_plugins.ts (100%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_requester.ts (93%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_saved_objects.ts (60%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_status.ts (100%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_ui_settings.ts (98%) rename packages/{kbn-dev-utils => kbn-test}/src/kbn_client/kbn_client_version.ts (100%) create mode 100644 scripts/kbn_archiver.js create mode 100644 test/functional/fixtures/kbn_archiver/discover.json diff --git a/package.json b/package.json index 1006d1bfcaace..80a82dc32c215 100644 --- a/package.json +++ b/package.json @@ -652,6 +652,7 @@ "fetch-mock": "^7.3.9", "file-loader": "^4.2.0", "file-saver": "^1.3.8", + "form-data": "^4.0.0", "formsy-react": "^1.1.5", "geckodriver": "^1.21.0", "glob-watcher": "5.0.3", diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts index 66ad4e7be589b..3ac3927d25c05 100644 --- a/packages/kbn-dev-utils/src/index.ts +++ b/packages/kbn-dev-utils/src/index.ts @@ -23,7 +23,6 @@ export { KBN_P12_PATH, KBN_P12_PASSWORD, } from './certs'; -export * from './kbn_client'; export * from './run'; export * from './axios'; export * from './stdio'; diff --git a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts index f86865ffa6670..821e3a872820e 100644 --- a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts +++ b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts @@ -7,7 +7,8 @@ */ import { Client } from '@elastic/elasticsearch'; -import { ToolingLog, KbnClient } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { migrateKibanaIndex, createStats, cleanKibanaIndices } from '../lib'; diff --git a/packages/kbn-es-archiver/src/actions/load.ts b/packages/kbn-es-archiver/src/actions/load.ts index 3ac7242b67d01..bfa12938da476 100644 --- a/packages/kbn-es-archiver/src/actions/load.ts +++ b/packages/kbn-es-archiver/src/actions/load.ts @@ -9,7 +9,8 @@ import { resolve } from 'path'; import { createReadStream } from 'fs'; import { Readable } from 'stream'; -import { ToolingLog, KbnClient } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { Client } from '@elastic/elasticsearch'; import { createPromiseFromStreams, concatStreamProviders } from '@kbn/utils'; import { ES_CLIENT_HEADERS } from '../client_headers'; diff --git a/packages/kbn-es-archiver/src/actions/unload.ts b/packages/kbn-es-archiver/src/actions/unload.ts index c12fa935f786a..b5f259a1496bb 100644 --- a/packages/kbn-es-archiver/src/actions/unload.ts +++ b/packages/kbn-es-archiver/src/actions/unload.ts @@ -10,7 +10,8 @@ import { resolve } from 'path'; import { createReadStream } from 'fs'; import { Readable, Writable } from 'stream'; import { Client } from '@elastic/elasticsearch'; -import { ToolingLog, KbnClient } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { createPromiseFromStreams } from '@kbn/utils'; import { diff --git a/packages/kbn-es-archiver/src/cli.ts b/packages/kbn-es-archiver/src/cli.ts index 919aff5c3851b..9617457d4573e 100644 --- a/packages/kbn-es-archiver/src/cli.ts +++ b/packages/kbn-es-archiver/src/cli.ts @@ -17,8 +17,8 @@ import Url from 'url'; import readline from 'readline'; import Fs from 'fs'; -import { RunWithCommands, createFlagError, KbnClient, CA_CERT_PATH } from '@kbn/dev-utils'; -import { readConfigFile } from '@kbn/test'; +import { RunWithCommands, createFlagError, CA_CERT_PATH } from '@kbn/dev-utils'; +import { readConfigFile, KbnClient } from '@kbn/test'; import { Client } from '@elastic/elasticsearch'; import { EsArchiver } from './es_archiver'; diff --git a/packages/kbn-es-archiver/src/es_archiver.ts b/packages/kbn-es-archiver/src/es_archiver.ts index b00b9fb8b3f25..68eacb4f3caf2 100644 --- a/packages/kbn-es-archiver/src/es_archiver.ts +++ b/packages/kbn-es-archiver/src/es_archiver.ts @@ -7,7 +7,8 @@ */ import { Client } from '@elastic/elasticsearch'; -import { ToolingLog, KbnClient } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { saveAction, diff --git a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts index b0e1b74e62cc1..ab90f4424d9fa 100644 --- a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts +++ b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts @@ -9,7 +9,8 @@ import { inspect } from 'util'; import { Client } from '@elastic/elasticsearch'; -import { ToolingLog, KbnClient } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { Stats } from '../stats'; import { deleteIndex } from './delete_index'; import { ES_CLIENT_HEADERS } from '../../client_headers'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index 4fd28678d2653..0694bc4ffdb0f 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -213,6 +213,13 @@ export const schema = Joi.object() }) .default(), + // settings for the saved objects svc + kbnArchiver: Joi.object() + .keys({ + directory: Joi.string().default(defaultRelativeToConfigPath('fixtures/kbn_archiver')), + }) + .default(), + // settings for the kibanaServer.uiSettings module uiSettings: Joi.object() .keys({ diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 25a5c6541bf07..919dc8b4477f3 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -48,3 +48,7 @@ export { getUrl } from './jest/utils/get_url'; export { runCheckJestConfigsCli } from './jest/run_check_jest_configs_cli'; export { runJest } from './jest/run'; + +export * from './kbn_archiver_cli'; + +export * from './kbn_client'; diff --git a/packages/kbn-test/src/kbn_archiver_cli.ts b/packages/kbn-test/src/kbn_archiver_cli.ts new file mode 100644 index 0000000000000..98bfa6eaa4046 --- /dev/null +++ b/packages/kbn-test/src/kbn_archiver_cli.ts @@ -0,0 +1,149 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import Url from 'url'; + +import { RunWithCommands, createFlagError, Flags } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; + +import { readConfigFile } from './functional_test_runner'; + +function getSinglePositionalArg(flags: Flags) { + const positional = flags._; + if (positional.length < 1) { + throw createFlagError('missing name of export to import'); + } + + if (positional.length > 1) { + throw createFlagError(`extra positional arguments, expected 1, got [${positional}]`); + } + + return positional[0]; +} + +function parseTypesFlag(flags: Flags) { + if (!flags.type || (typeof flags.type !== 'string' && !Array.isArray(flags.type))) { + throw createFlagError('--type is a required flag'); + } + + const types = typeof flags.type === 'string' ? [flags.type] : flags.type; + return types.reduce( + (acc: string[], type) => [...acc, ...type.split(',').map((t) => t.trim())], + [] + ); +} + +export function runKbnArchiverCli() { + new RunWithCommands({ + description: 'Import/export saved objects from archives, for testing', + globalFlags: { + string: ['config', 'space', 'kibana-url', 'dir'], + help: ` + --space space id to operate on, defaults to the default space + --config optional path to an FTR config file that will be parsed and used for defaults + --kibana-url set the url that kibana can be reached at, uses the "servers.kibana" setting from --config by default + --dir directory that contains exports to be imported, or where exports will be saved, uses the "kbnArchiver.directory" + setting from --config by default + `, + }, + async extendContext({ log, flags }) { + let config; + if (flags.config) { + if (typeof flags.config !== 'string') { + throw createFlagError('expected --config to be a string'); + } + + config = await readConfigFile(log, Path.resolve(flags.config)); + } + + let kibanaUrl; + if (flags['kibana-url']) { + if (typeof flags['kibana-url'] !== 'string') { + throw createFlagError('expected --kibana-url to be a string'); + } + + kibanaUrl = flags['kibana-url']; + } else if (config) { + kibanaUrl = Url.format(config.get('servers.kibana')); + } + + if (!kibanaUrl) { + throw createFlagError( + 'Either a --config file with `servers.kibana` defined, or a --kibana-url must be passed' + ); + } + + let importExportDir; + if (flags.dir) { + if (typeof flags.dir !== 'string') { + throw createFlagError('expected --dir to be a string'); + } + + importExportDir = flags.dir; + } else if (config) { + importExportDir = config.get('kbnArchiver.directory'); + } + + if (!importExportDir) { + throw createFlagError( + '--config does not include a kbnArchiver.directory, specify it or include --dir flag' + ); + } + + const space = flags.space; + if (!(space === undefined || typeof space === 'string')) { + throw createFlagError('--space must be a string'); + } + + return { + space, + kbnClient: new KbnClient({ + log, + url: kibanaUrl, + importExportDir, + }), + }; + }, + }) + .command({ + name: 'save', + usage: 'save ', + description: 'export saved objects from Kibana to a file', + flags: { + string: ['type'], + help: ` + --type saved object type that should be fetched and stored in the archive, can + be specified multiple times or be a comma-separated list. + `, + }, + async run({ kbnClient, flags, space }) { + await kbnClient.importExport.save(getSinglePositionalArg(flags), { + types: parseTypesFlag(flags), + space, + }); + }, + }) + .command({ + name: 'load', + usage: 'load ', + description: 'import a saved export to Kibana', + async run({ kbnClient, flags, space }) { + await kbnClient.importExport.load(getSinglePositionalArg(flags), { space }); + }, + }) + .command({ + name: 'unload', + usage: 'unload ', + description: 'delete the saved objects saved in the archive from the Kibana index', + async run({ kbnClient, flags, space }) { + await kbnClient.importExport.unload(getSinglePositionalArg(flags), { space }); + }, + }) + .execute(); +} diff --git a/packages/kbn-dev-utils/src/kbn_client/index.ts b/packages/kbn-test/src/kbn_client/index.ts similarity index 100% rename from packages/kbn-dev-utils/src/kbn_client/index.ts rename to packages/kbn-test/src/kbn_client/index.ts diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts b/packages/kbn-test/src/kbn_client/kbn_client.ts similarity index 87% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client.ts rename to packages/kbn-test/src/kbn_client/kbn_client.ts index 963639d47045b..3fa74412c1a8b 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts +++ b/packages/kbn-test/src/kbn_client/kbn_client.ts @@ -6,19 +6,22 @@ * Side Public License, v 1. */ -import { ToolingLog } from '../tooling_log'; +import { ToolingLog } from '@kbn/dev-utils'; + import { KbnClientRequester, ReqOptions } from './kbn_client_requester'; import { KbnClientStatus } from './kbn_client_status'; import { KbnClientPlugins } from './kbn_client_plugins'; import { KbnClientVersion } from './kbn_client_version'; import { KbnClientSavedObjects } from './kbn_client_saved_objects'; import { KbnClientUiSettings, UiSettingValues } from './kbn_client_ui_settings'; +import { KbnClientImportExport } from './kbn_client_import_export'; export interface KbnClientOptions { url: string; certificateAuthorities?: Buffer[]; log: ToolingLog; uiSettingDefaults?: UiSettingValues; + importExportDir?: string; } export class KbnClient { @@ -27,6 +30,7 @@ export class KbnClient { readonly version: KbnClientVersion; readonly savedObjects: KbnClientSavedObjects; readonly uiSettings: KbnClientUiSettings; + readonly importExport: KbnClientImportExport; private readonly requester: KbnClientRequester; private readonly log: ToolingLog; @@ -56,6 +60,12 @@ export class KbnClient { this.version = new KbnClientVersion(this.status); this.savedObjects = new KbnClientSavedObjects(this.log, this.requester); this.uiSettings = new KbnClientUiSettings(this.log, this.requester, this.uiSettingDefaults); + this.importExport = new KbnClientImportExport( + this.log, + this.requester, + this.savedObjects, + options.importExportDir + ); } /** diff --git a/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts b/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts new file mode 100644 index 0000000000000..bb5b99fdc4439 --- /dev/null +++ b/packages/kbn-test/src/kbn_client/kbn_client_import_export.ts @@ -0,0 +1,163 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { inspect } from 'util'; +import Fs from 'fs/promises'; +import Path from 'path'; + +import FormData from 'form-data'; +import { ToolingLog, isAxiosResponseError, createFailError } from '@kbn/dev-utils'; + +import { KbnClientRequester, uriencode, ReqOptions } from './kbn_client_requester'; +import { KbnClientSavedObjects } from './kbn_client_saved_objects'; + +interface ImportApiResponse { + success: boolean; + [key: string]: unknown; +} + +interface SavedObject { + id: string; + type: string; + [key: string]: unknown; +} + +async function parseArchive(path: string): Promise { + return (await Fs.readFile(path, 'utf-8')) + .split('\n\n') + .filter((line) => !!line) + .map((line) => JSON.parse(line)); +} + +export class KbnClientImportExport { + constructor( + public readonly log: ToolingLog, + public readonly requester: KbnClientRequester, + public readonly savedObjects: KbnClientSavedObjects, + public readonly dir?: string + ) {} + + private resolvePath(path: string) { + if (!Path.extname(path)) { + path = `${path}.json`; + } + + if (!this.dir && !Path.isAbsolute(path)) { + throw new Error( + 'unable to resolve relative path to import/export without a configured dir, either path absolute path or specify --dir' + ); + } + + return this.dir ? Path.resolve(this.dir, path) : path; + } + + async load(name: string, options?: { space?: string }) { + const src = this.resolvePath(name); + this.log.debug('resolved import for', name, 'to', src); + + const objects = await parseArchive(src); + this.log.info('importing', objects.length, 'saved objects', { space: options?.space }); + + const formData = new FormData(); + formData.append('file', objects.map((obj) => JSON.stringify(obj)).join('\n'), 'import.ndjson'); + + // TODO: should we clear out the existing saved objects? + const resp = await this.req(options?.space, { + method: 'POST', + path: '/api/saved_objects/_import', + query: { + overwrite: true, + }, + body: formData, + headers: formData.getHeaders(), + }); + + if (resp.data.success) { + this.log.success('import success'); + } else { + throw createFailError(`failed to import all saved objects: ${inspect(resp.data)}`); + } + } + + async unload(name: string, options?: { space?: string }) { + const src = this.resolvePath(name); + this.log.debug('unloading docs from archive at', src); + + const objects = await parseArchive(src); + this.log.info('deleting', objects.length, 'objects', { space: options?.space }); + + const { deleted, missing } = await this.savedObjects.bulkDelete({ + space: options?.space, + objects, + }); + + if (missing) { + this.log.info(missing, 'saved objects were already deleted'); + } + + this.log.success(deleted, 'saved objects deleted'); + } + + async save(name: string, options: { types: string[]; space?: string }) { + const dest = this.resolvePath(name); + this.log.debug('saving export to', dest); + + const resp = await this.req(options.space, { + method: 'POST', + path: '/api/saved_objects/_export', + body: { + type: options.types, + excludeExportDetails: true, + includeReferencesDeep: true, + }, + }); + + if (typeof resp.data !== 'string') { + throw createFailError(`unexpected response from export API: ${inspect(resp.data)}`); + } + + const objects = resp.data + .split('\n') + .filter((l) => !!l) + .map((line) => JSON.parse(line)); + + const fileContents = objects + .map((obj) => { + const { sort: _, ...nonSortFields } = obj; + return JSON.stringify(nonSortFields, null, 2); + }) + .join('\n\n'); + + await Fs.writeFile(dest, fileContents, 'utf-8'); + + this.log.success('Exported', objects.length, 'saved objects to', dest); + } + + private async req(space: string | undefined, options: ReqOptions) { + if (!options.path.startsWith('/')) { + throw new Error('options.path must start with a /'); + } + + try { + return await this.requester.request({ + ...options, + path: space ? uriencode`/s/${space}` + options.path : options.path, + }); + } catch (error) { + if (!isAxiosResponseError(error)) { + throw error; + } + + throw createFailError( + `${error.response.status} resp: ${inspect(error.response.data)}\nreq: ${inspect( + error.config + )}` + ); + } + } +} diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_plugins.ts b/packages/kbn-test/src/kbn_client/kbn_client_plugins.ts similarity index 100% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_plugins.ts rename to packages/kbn-test/src/kbn_client/kbn_client_plugins.ts diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts b/packages/kbn-test/src/kbn_client/kbn_client_requester.ts similarity index 93% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts rename to packages/kbn-test/src/kbn_client/kbn_client_requester.ts index d940525f57e3c..2e1575aee1897 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts +++ b/packages/kbn-test/src/kbn_client/kbn_client_requester.ts @@ -8,10 +8,10 @@ import Url from 'url'; import Https from 'https'; -import Axios, { AxiosResponse } from 'axios'; +import Qs from 'querystring'; -import { isAxiosRequestError, isAxiosResponseError } from '../axios'; -import { ToolingLog } from '../tooling_log'; +import Axios, { AxiosResponse } from 'axios'; +import { ToolingLog, isAxiosRequestError, isAxiosResponseError } from '@kbn/dev-utils'; const isConcliftOnGetError = (error: any) => { return ( @@ -52,6 +52,7 @@ export interface ReqOptions { method: 'GET' | 'POST' | 'PUT' | 'DELETE'; body?: any; retries?: number; + headers?: Record; } const delay = (ms: number) => @@ -102,9 +103,11 @@ export class KbnClientRequester { data: options.body, params: options.query, headers: { + ...options.headers, 'kbn-xsrf': 'kbn-client', }, httpsAgent: this.httpsAgent, + paramsSerializer: (params) => Qs.stringify(params), }); return response; diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts b/packages/kbn-test/src/kbn_client/kbn_client_saved_objects.ts similarity index 60% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts rename to packages/kbn-test/src/kbn_client/kbn_client_saved_objects.ts index 9d616d6f50a88..904ccc385bd7d 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts +++ b/packages/kbn-test/src/kbn_client/kbn_client_saved_objects.ts @@ -6,7 +6,12 @@ * Side Public License, v 1. */ -import { ToolingLog } from '../tooling_log'; +import { inspect } from 'util'; + +import * as Rx from 'rxjs'; +import { mergeMap } from 'rxjs/operators'; +import { lastValueFrom } from '@kbn/std'; +import { ToolingLog, isAxiosResponseError, createFailError } from '@kbn/dev-utils'; import { KbnClientRequester, uriencode } from './kbn_client_requester'; @@ -51,6 +56,38 @@ interface MigrateResponse { result: Array<{ status: string }>; } +interface FindApiResponse { + saved_objects: Array<{ + type: string; + id: string; + [key: string]: unknown; + }>; + total: number; + per_page: number; + page: number; +} + +interface CleanOptions { + space?: string; + types: string[]; +} + +interface DeleteObjectsOptions { + space?: string; + objects: Array<{ + type: string; + id: string; + }>; +} + +async function concurrently(maxConcurrency: number, arr: T[], fn: (item: T) => Promise) { + if (arr.length) { + await lastValueFrom( + Rx.from(arr).pipe(mergeMap(async (item) => await fn(item), maxConcurrency)) + ); + } +} + export class KbnClientSavedObjects { constructor(private readonly log: ToolingLog, private readonly requester: KbnClientRequester) {} @@ -143,4 +180,67 @@ export class KbnClientSavedObjects { return data; } + + public async clean(options: CleanOptions) { + this.log.debug('Cleaning all saved objects', { space: options.space }); + + let deleted = 0; + + while (true) { + const resp = await this.requester.request({ + method: 'GET', + path: options.space + ? uriencode`/s/${options.space}/api/saved_objects/_find` + : '/api/saved_objects/_find', + query: { + per_page: 1000, + type: options.types, + fields: 'none', + }, + }); + + this.log.info('deleting batch of', resp.data.saved_objects.length, 'objects'); + const deletion = await this.bulkDelete({ + space: options.space, + objects: resp.data.saved_objects, + }); + deleted += deletion.deleted; + + if (resp.data.total <= resp.data.per_page) { + break; + } + } + + this.log.success('deleted', deleted, 'objects'); + } + + public async bulkDelete(options: DeleteObjectsOptions) { + let deleted = 0; + let missing = 0; + + await concurrently(20, options.objects, async (obj) => { + try { + await this.requester.request({ + method: 'DELETE', + path: options.space + ? uriencode`/s/${options.space}/api/saved_objects/${obj.type}/${obj.id}` + : uriencode`/api/saved_objects/${obj.type}/${obj.id}`, + }); + deleted++; + } catch (error) { + if (isAxiosResponseError(error)) { + if (error.response.status === 404) { + missing++; + return; + } + + throw createFailError(`${error.response.status} resp: ${inspect(error.response.data)}`); + } + + throw error; + } + }); + + return { deleted, missing }; + } } diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_status.ts b/packages/kbn-test/src/kbn_client/kbn_client_status.ts similarity index 100% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_status.ts rename to packages/kbn-test/src/kbn_client/kbn_client_status.ts diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts b/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts similarity index 98% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts rename to packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts index 75fd7a4c8391e..78155098ef038 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts +++ b/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ToolingLog } from '../tooling_log'; +import { ToolingLog } from '@kbn/dev-utils'; import { KbnClientRequester, uriencode } from './kbn_client_requester'; diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_version.ts b/packages/kbn-test/src/kbn_client/kbn_client_version.ts similarity index 100% rename from packages/kbn-dev-utils/src/kbn_client/kbn_client_version.ts rename to packages/kbn-test/src/kbn_client/kbn_client_version.ts diff --git a/scripts/kbn_archiver.js b/scripts/kbn_archiver.js new file mode 100644 index 0000000000000..b04b86a0d4eed --- /dev/null +++ b/scripts/kbn_archiver.js @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +require('../src/setup_node_env'); +require('@kbn/test').runKbnArchiverCli(); diff --git a/test/common/services/kibana_server/kibana_server.ts b/test/common/services/kibana_server/kibana_server.ts index 51f9dc9d00772..f366a864db980 100644 --- a/test/common/services/kibana_server/kibana_server.ts +++ b/test/common/services/kibana_server/kibana_server.ts @@ -7,7 +7,7 @@ */ import Url from 'url'; -import { KbnClient } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -22,6 +22,7 @@ export function KibanaServerProvider({ getService }: FtrProviderContext) { url, certificateAuthorities: config.get('servers.kibana.certificateAuthorities'), uiSettingDefaults: defaults, + importExportDir: config.get('kbnArchiver.directory'), }); if (defaults) { diff --git a/test/common/services/security/role.ts b/test/common/services/security/role.ts index 2aae5b2282940..420bed027f317 100644 --- a/test/common/services/security/role.ts +++ b/test/common/services/security/role.ts @@ -7,7 +7,8 @@ */ import util from 'util'; -import { KbnClient, ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; export class Role { constructor(private log: ToolingLog, private kibanaServer: KbnClient) {} diff --git a/test/common/services/security/role_mappings.ts b/test/common/services/security/role_mappings.ts index c20ff7e327b64..af9204866ad47 100644 --- a/test/common/services/security/role_mappings.ts +++ b/test/common/services/security/role_mappings.ts @@ -7,7 +7,8 @@ */ import util from 'util'; -import { KbnClient, ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; export class RoleMappings { constructor(private log: ToolingLog, private kbnClient: KbnClient) {} diff --git a/test/common/services/security/user.ts b/test/common/services/security/user.ts index 0d12a0dae2e46..3bd31bb5ed186 100644 --- a/test/common/services/security/user.ts +++ b/test/common/services/security/user.ts @@ -7,7 +7,8 @@ */ import util from 'util'; -import { KbnClient, ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; export class User { constructor(private log: ToolingLog, private kbnClient: KbnClient) {} diff --git a/test/functional/apps/discover/_discover.ts b/test/functional/apps/discover/_discover.ts index 151bd39af2121..6f4a0c40c26a3 100644 --- a/test/functional/apps/discover/_discover.ts +++ b/test/functional/apps/discover/_discover.ts @@ -20,6 +20,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const inspector = getService('inspector'); const elasticChart = getService('elasticChart'); const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + const defaultSettings = { defaultIndex: 'logstash-*', }; @@ -27,7 +28,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('discover test', function describeIndexTests() { before(async function () { log.debug('load kibana index with default index pattern'); - await esArchiver.load('discover'); + + await kibanaServer.savedObjects.clean({ types: ['search'] }); + await kibanaServer.importExport.load('discover'); // and load a set of makelogs data await esArchiver.loadIfNeeded('logstash_functional'); diff --git a/test/functional/fixtures/kbn_archiver/discover.json b/test/functional/fixtures/kbn_archiver/discover.json new file mode 100644 index 0000000000000..e861f875a2d9e --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/discover.json @@ -0,0 +1,51 @@ +{ + "attributes": { + "fieldAttrs": "{\"referer\":{\"customLabel\":\"Referer custom\"}}", + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nestedField.child\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"nested\":{\"path\":\"nestedField\"}}},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.0.0", + "id": "logstash-*", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzQsMl0=" +} + +{ + "attributes": { + "columns": [ + "_source" + ], + "description": "A Saved Search Description", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "A Saved Search", + "version": 1 + }, + "coreMigrationVersion": "8.0.0", + "id": "ab12e3c0-f231-11e6-9486-733b1ac9221a", + "migrationVersion": { + "search": "7.9.3" + }, + "references": [ + { + "id": "logstash-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "version": "WzUsMl0=" +} \ No newline at end of file diff --git a/x-pack/plugins/case/server/scripts/sub_cases/index.ts b/x-pack/plugins/case/server/scripts/sub_cases/index.ts index 9dd577c40c74e..f6ec1f44076e4 100644 --- a/x-pack/plugins/case/server/scripts/sub_cases/index.ts +++ b/x-pack/plugins/case/server/scripts/sub_cases/index.ts @@ -6,7 +6,8 @@ */ /* eslint-disable no-console */ import yargs from 'yargs'; -import { KbnClient, ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { CaseResponse, CaseType, diff --git a/x-pack/plugins/security_solution/common/endpoint/index_data.ts b/x-pack/plugins/security_solution/common/endpoint/index_data.ts index 3ff719d267f40..96f83f1073fcc 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -7,7 +7,7 @@ import { Client } from '@elastic/elasticsearch'; import seedrandom from 'seedrandom'; -import { KbnClient } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { AxiosResponse } from 'axios'; import { EndpointDocGenerator, TreeOptions, Event } from './generate_data'; import { firstNonNullValue } from './models/ecs_safety_helpers'; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/kbn_client_with_api_key_support.ts b/x-pack/plugins/security_solution/scripts/endpoint/kbn_client_with_api_key_support.ts index 557b485682e15..a8ed7b77a5d9e 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/kbn_client_with_api_key_support.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/kbn_client_with_api_key_support.ts @@ -7,7 +7,7 @@ import { URL } from 'url'; -import { KbnClient, KbnClientOptions } from '@kbn/dev-utils'; +import { KbnClient, KbnClientOptions } from '@kbn/test'; import fetch, { RequestInit } from 'node-fetch'; export class KbnClientWithApiKeySupport extends KbnClient { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts index a4664e4a51ca2..72f56f13eaddf 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts @@ -10,7 +10,8 @@ import yargs from 'yargs'; import fs from 'fs'; import { Client, ClientOptions } from '@elastic/elasticsearch'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; -import { KbnClient, ToolingLog, CA_CERT_PATH } from '@kbn/dev-utils'; +import { ToolingLog, CA_CERT_PATH } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { AxiosResponse } from 'axios'; import { indexHostsAndAlerts } from '../../common/endpoint/index_data'; import { ANCESTRY_LIMIT, EndpointDocGenerator } from '../../common/endpoint/generate_data'; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts index 3b914f987456a..582969f1dcd45 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts @@ -7,7 +7,8 @@ // @ts-ignore import minimist from 'minimist'; -import { KbnClient, ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import bluebird from 'bluebird'; import { basename } from 'path'; import { TRUSTED_APPS_CREATE_API, TRUSTED_APPS_LIST_API } from '../../../common/endpoint/constants'; diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index 7711338b44697..683d57081a267 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { KbnClient } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; import { ApiResponse, Client } from '@elastic/elasticsearch'; import { SuperTest } from 'supertest'; import supertestAsPromised from 'supertest-as-promised'; diff --git a/yarn.lock b/yarn.lock index 4d89446282aa3..ac0c16b23c070 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14954,6 +14954,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"