From 52991188c4b51ddc18b14208700b998d77514453 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 16:14:31 -0700 Subject: [PATCH 01/11] [ftr/savedObjects] add simple saved object api client to ftr services --- .../services/kibana_server/kibana_server.js | 2 + .../services/kibana_server/saved_objects.ts | 152 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 test/common/services/kibana_server/saved_objects.ts diff --git a/test/common/services/kibana_server/kibana_server.js b/test/common/services/kibana_server/kibana_server.js index 2d4ae030b153d..c83294f68ff6c 100644 --- a/test/common/services/kibana_server/kibana_server.js +++ b/test/common/services/kibana_server/kibana_server.js @@ -22,6 +22,7 @@ import { format as formatUrl } from 'url'; import { KibanaServerStatus } from './status'; import { KibanaServerUiSettings } from './ui_settings'; import { KibanaServerVersion } from './version'; +import { KibanaServerSavedObjects } from './saved_objects'; export function KibanaServerProvider({ getService }) { const log = getService('log'); @@ -33,6 +34,7 @@ export function KibanaServerProvider({ getService }) { const url = formatUrl(config.get('servers.kibana')); this.status = new KibanaServerStatus(url); this.version = new KibanaServerVersion(this.status); + this.savedObjects = new KibanaServerSavedObjects(url, log); this.uiSettings = new KibanaServerUiSettings(url, log, config.get('uiSettings.defaults'), lifecycle); } }; diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts new file mode 100644 index 0000000000000..fc10e8c304280 --- /dev/null +++ b/test/common/services/kibana_server/saved_objects.ts @@ -0,0 +1,152 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Url from 'url'; + +import Axios, { AxiosRequestConfig } from 'axios'; +import { ToolingLog } from '@kbn/dev-utils'; + +const joinPath = (...components: Array) => + `/${components + .filter(s => !!s) + .map(c => encodeURIComponent(c)) + .join('/')}`; + +type MigrationVersion = Record; + +interface Reference { + id: string; + name: string; + type: string; +} + +interface SavedObjectResponse> { + attributes: Attributes; + id: string; + migrationVersion?: MigrationVersion; + references: Reference[]; + type: string; + updated_at?: string; + version?: string; +} + +interface GetOptions { + type: string; + id: string; +} + +interface IndexOptions { + type: string; + attributes: Attributes; + id?: string; + overwrite?: boolean; + migrationVersion?: MigrationVersion; + references?: Reference[]; +} + +interface UpdateOptions extends IndexOptions { + id: string; +} + +export class KibanaServerSavedObjects { + private readonly x = Axios.create({ + baseURL: Url.resolve(this.url, '/api/saved_objects/'), + headers: { + 'kbn-xsrf': 'KibanaServerSavedObjects', + }, + }); + + constructor(private readonly url: string, private readonly log: ToolingLog) {} + + /** + * Get an object + */ + public async get>(options: GetOptions) { + this.log.debug('Gettings saved object: %j', options); + return await this.request>('get saved object', { + url: joinPath(options.type, options.id), + method: 'GET', + }); + } + + /** + * Create a saved object + */ + public async create>(options: IndexOptions) { + this.log.debug('Updating saved object: %j', options); + + return await this.request>('update saved object', { + url: joinPath(options.type, options.id), + params: { + overwrite: options.overwrite, + }, + method: 'POST', + data: { + attributes: options.attributes, + migrationVersion: options.migrationVersion, + references: options.references, + }, + }); + } + + /** + * Update a saved object + */ + public async update>(options: UpdateOptions) { + this.log.debug('Updating saved object: %j', options); + + return await this.request>('update saved object', { + url: joinPath(options.type, options.id), + params: { + overwrite: options.overwrite, + }, + method: 'PUT', + data: { + attributes: options.attributes, + migrationVersion: options.migrationVersion, + references: options.references, + }, + }); + } + + /** + * Delete an object + */ + public async delete(options: GetOptions) { + this.log.debug('Deleting saved object %s/%s', options); + + return await this.request('delete saved object', { + url: joinPath(options.type, options.id), + method: 'DELETE', + }); + } + + private async request(desc: string, options: AxiosRequestConfig) { + try { + const resp = await this.x.request(options); + return resp.data; + } catch (error) { + if (error.response) { + throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`); + } + + throw error; + } + } +} From 0946bec2c641ba11b927e51fc899c7041a91da8f Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 17:25:34 -0700 Subject: [PATCH 02/11] fix typo --- test/common/services/kibana_server/saved_objects.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts index fc10e8c304280..390a23054de8e 100644 --- a/test/common/services/kibana_server/saved_objects.ts +++ b/test/common/services/kibana_server/saved_objects.ts @@ -89,7 +89,7 @@ export class KibanaServerSavedObjects { * Create a saved object */ public async create>(options: IndexOptions) { - this.log.debug('Updating saved object: %j', options); + this.log.debug('Creating saved object: %j', options); return await this.request>('update saved object', { url: joinPath(options.type, options.id), From f7e8901a121ac93718e0e5014644b1da33bff117 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 17:26:08 -0700 Subject: [PATCH 03/11] use consistent spacing --- test/common/services/kibana_server/saved_objects.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts index 390a23054de8e..92c1ec2eada2a 100644 --- a/test/common/services/kibana_server/saved_objects.ts +++ b/test/common/services/kibana_server/saved_objects.ts @@ -79,6 +79,7 @@ export class KibanaServerSavedObjects { */ public async get>(options: GetOptions) { this.log.debug('Gettings saved object: %j', options); + return await this.request>('get saved object', { url: joinPath(options.type, options.id), method: 'GET', From 94a04d9253e35fe710b7edeff0452f02bb59bd10 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 18:35:41 -0700 Subject: [PATCH 04/11] fix types and TS-ify the rest of kibanaServer service --- packages/kbn-test/types/ftr.d.ts | 11 +++- test/common/services/es_archiver.ts | 11 ++-- test/common/services/index.ts | 1 - ...d_es_archiver.js => extend_es_archiver.ts} | 17 +++++- .../kibana_server/{index.js => index.ts} | 0 .../{kibana_server.js => kibana_server.ts} | 27 +++++---- .../services/kibana_server/saved_objects.ts | 2 +- .../kibana_server/{status.js => status.ts} | 33 +++++++---- .../{ui_settings.js => ui_settings.ts} | 56 ++++++++++--------- .../kibana_server/{version.js => version.ts} | 18 +++--- 10 files changed, 105 insertions(+), 71 deletions(-) rename test/common/services/kibana_server/{extend_es_archiver.js => extend_es_archiver.ts} (77%) rename test/common/services/kibana_server/{index.js => index.ts} (100%) rename test/common/services/kibana_server/{kibana_server.js => kibana_server.ts} (63%) rename test/common/services/kibana_server/{status.js => status.ts} (66%) rename test/common/services/kibana_server/{ui_settings.js => ui_settings.ts} (51%) rename test/common/services/kibana_server/{version.js => version.ts} (73%) diff --git a/packages/kbn-test/types/ftr.d.ts b/packages/kbn-test/types/ftr.d.ts index 8289877ed1b98..e917ed63ca5d3 100644 --- a/packages/kbn-test/types/ftr.d.ts +++ b/packages/kbn-test/types/ftr.d.ts @@ -20,6 +20,8 @@ import { ToolingLog } from '@kbn/dev-utils'; import { Config, Lifecycle } from '../src/functional_test_runner/lib'; +export { Lifecycle, Config }; + interface AsyncInstance { /** * Services that are initialized async are not ready before the tests execute, so you might need @@ -36,14 +38,17 @@ interface AsyncInstance { */ type MaybeAsyncInstance = T extends Promise ? AsyncInstance & X : T; +/** + * Covert a Provider type to the instance type it provides + */ +export type ProvidedType any> = MaybeAsyncInstance>; + /** * Convert a map of providers to a map of the instance types they provide, also converting * promise types into the async instances that other providers will receive. */ type ProvidedTypeMap = { - [K in keyof T]: T[K] extends (...args: any[]) => any - ? MaybeAsyncInstance> - : unknown; + [K in keyof T]: T[K] extends (...args: any[]) => any ? ProvidedType : unknown; }; export interface GenericFtrProviderContext< diff --git a/test/common/services/es_archiver.ts b/test/common/services/es_archiver.ts index e72bb49a76c0d..bb0c6d3e5a008 100644 --- a/test/common/services/es_archiver.ts +++ b/test/common/services/es_archiver.ts @@ -21,7 +21,6 @@ import { format as formatUrl } from 'url'; import { FtrProviderContext } from '../ftr_provider_context'; import { EsArchiver } from '../../../src/es_archiver'; -// @ts-ignore not TS yet import * as KibanaServer from './kibana_server'; export function EsArchiverProvider({ getService, hasService }: FtrProviderContext): EsArchiver { @@ -43,12 +42,12 @@ export function EsArchiverProvider({ getService, hasService }: FtrProviderContex }); if (hasService('kibanaServer')) { - KibanaServer.extendEsArchiver({ + KibanaServer.extendEsArchiver( esArchiver, - kibanaServer: getService('kibanaServer'), - retry: getService('retry'), - defaults: config.get('uiSettings.defaults'), - }); + getService('kibanaServer'), + getService('retry'), + config.get('uiSettings.defaults') + ); } return esArchiver; diff --git a/test/common/services/index.ts b/test/common/services/index.ts index 60b6a5141b918..0dbd2d0262cf4 100644 --- a/test/common/services/index.ts +++ b/test/common/services/index.ts @@ -19,7 +19,6 @@ import { EsProvider } from './es'; import { EsArchiverProvider } from './es_archiver'; -// @ts-ignore not TS yet import { KibanaServerProvider } from './kibana_server'; import { RetryProvider } from './retry'; diff --git a/test/common/services/kibana_server/extend_es_archiver.js b/test/common/services/kibana_server/extend_es_archiver.ts similarity index 77% rename from test/common/services/kibana_server/extend_es_archiver.js rename to test/common/services/kibana_server/extend_es_archiver.ts index d934e6725a9f5..a132a2731ea1c 100644 --- a/test/common/services/kibana_server/extend_es_archiver.js +++ b/test/common/services/kibana_server/extend_es_archiver.ts @@ -17,10 +17,21 @@ * under the License. */ -const ES_ARCHIVER_LOAD_METHODS = ['load', 'loadIfNeeded', 'unload']; +import { ProvidedType } from '@kbn/test/types/ftr'; + +import { EsArchiver } from '../../../../src/es_archiver'; +import { KibanaServerProvider } from './kibana_server'; +import { RetryProvider } from '../retry'; + +const ES_ARCHIVER_LOAD_METHODS = ['load', 'loadIfNeeded', 'unload'] as const; const KIBANA_INDEX = '.kibana'; -export function extendEsArchiver({ esArchiver, kibanaServer, retry, defaults }) { +export function extendEsArchiver( + esArchiver: EsArchiver, + kibanaServer: ProvidedType, + retry: ProvidedType, + defaults: Record +) { // only extend the esArchiver if there are default uiSettings to restore if (!defaults) { return; @@ -29,7 +40,7 @@ export function extendEsArchiver({ esArchiver, kibanaServer, retry, defaults }) ES_ARCHIVER_LOAD_METHODS.forEach(method => { const originalMethod = esArchiver[method]; - esArchiver[method] = async (...args) => { + esArchiver[method] = async (...args: any) => { // esArchiver methods return a stats object, with information about the indexes created const stats = await originalMethod.apply(esArchiver, args); diff --git a/test/common/services/kibana_server/index.js b/test/common/services/kibana_server/index.ts similarity index 100% rename from test/common/services/kibana_server/index.js rename to test/common/services/kibana_server/index.ts diff --git a/test/common/services/kibana_server/kibana_server.js b/test/common/services/kibana_server/kibana_server.ts similarity index 63% rename from test/common/services/kibana_server/kibana_server.js rename to test/common/services/kibana_server/kibana_server.ts index c83294f68ff6c..6979d6649f3ea 100644 --- a/test/common/services/kibana_server/kibana_server.js +++ b/test/common/services/kibana_server/kibana_server.ts @@ -19,23 +19,28 @@ import { format as formatUrl } from 'url'; +import { FtrProviderContext } from '../../ftr_provider_context'; import { KibanaServerStatus } from './status'; import { KibanaServerUiSettings } from './ui_settings'; import { KibanaServerVersion } from './version'; -import { KibanaServerSavedObjects } from './saved_objects'; +import { KibanaServerSavedObjects } from './saved_objects'; -export function KibanaServerProvider({ getService }) { +export function KibanaServerProvider({ getService }: FtrProviderContext) { const log = getService('log'); const config = getService('config'); const lifecycle = getService('lifecycle'); - return new class KibanaServer { - constructor() { - const url = formatUrl(config.get('servers.kibana')); - this.status = new KibanaServerStatus(url); - this.version = new KibanaServerVersion(this.status); - this.savedObjects = new KibanaServerSavedObjects(url, log); - this.uiSettings = new KibanaServerUiSettings(url, log, config.get('uiSettings.defaults'), lifecycle); - } - }; + const url = formatUrl(config.get('servers.kibana')); + + return new (class KibanaServer { + public readonly status = new KibanaServerStatus(url); + public readonly version = new KibanaServerVersion(this.status); + public readonly savedObjects = new KibanaServerSavedObjects(url, log); + public readonly uiSettings = new KibanaServerUiSettings( + url, + log, + config.get('uiSettings.defaults'), + lifecycle + ); + })(); } diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts index 92c1ec2eada2a..0e4a9a34bf2e4 100644 --- a/test/common/services/kibana_server/saved_objects.ts +++ b/test/common/services/kibana_server/saved_objects.ts @@ -24,7 +24,7 @@ import { ToolingLog } from '@kbn/dev-utils'; const joinPath = (...components: Array) => `/${components - .filter(s => !!s) + .filter((s): s is string => !!s) .map(c => encodeURIComponent(c)) .join('/')}`; diff --git a/test/common/services/kibana_server/status.js b/test/common/services/kibana_server/status.ts similarity index 66% rename from test/common/services/kibana_server/status.js rename to test/common/services/kibana_server/status.ts index 3988bab185fcc..9bc3199930f97 100644 --- a/test/common/services/kibana_server/status.js +++ b/test/common/services/kibana_server/status.ts @@ -17,22 +17,33 @@ * under the License. */ -import { resolve as resolveUrl } from 'url'; +import Axios from 'axios'; -import Wreck from '@hapi/wreck'; - -const get = async url => { - const { payload } = await Wreck.get(url, { json: 'force' }); - return payload; -}; +interface StatusResponse { + status: { + overall: { + state: string; + [key: string]: unknown; + }; + [key: string]: unknown; + }; + version?: { + number?: number; + build_snapshot?: boolean; + }; + [key: string]: unknown; +} export class KibanaServerStatus { - constructor(kibanaServerUrl) { - this.kibanaServerUrl = kibanaServerUrl; - } + private readonly x = Axios.create({ + baseURL: this.kibanaServerUrl, + }); + + constructor(private readonly kibanaServerUrl: string) {} async get() { - return await get(resolveUrl(this.kibanaServerUrl, './api/status')); + const resp = await this.x.get('api/status'); + return resp.data; } async getOverallState() { diff --git a/test/common/services/kibana_server/ui_settings.js b/test/common/services/kibana_server/ui_settings.ts similarity index 51% rename from test/common/services/kibana_server/ui_settings.js rename to test/common/services/kibana_server/ui_settings.ts index aa75839c20152..0a2b89e49d907 100644 --- a/test/common/services/kibana_server/ui_settings.js +++ b/test/common/services/kibana_server/ui_settings.ts @@ -17,22 +17,25 @@ * under the License. */ -import Wreck from '@hapi/wreck'; +import Axios from 'axios'; import { get } from 'lodash'; +import { Lifecycle } from '@kbn/test/types/ftr'; + +import { ToolingLog } from '@kbn/dev-utils'; export class KibanaServerUiSettings { - constructor(url, log, defaults, lifecycle) { - this._log = log; - this._defaults = defaults; - this._wreck = Wreck.defaults({ - headers: { 'kbn-xsrf': 'ftr/services/uiSettings' }, - baseUrl: url, - json: true, - redirects: 3, - }); + private readonly x = Axios.create({ + baseURL: this.url, + }); - if (this._defaults) { - lifecycle.on('beforeTests', async () => { + constructor( + private readonly url: string, + private readonly log: ToolingLog, + private readonly defaults: Record, + private readonly lifecycle: Lifecycle + ) { + if (this.defaults) { + this.lifecycle.on('beforeTests', async () => { await this.update(defaults); }); } @@ -42,27 +45,27 @@ export class KibanaServerUiSettings { * Gets defaultIndex from the config doc. */ async getDefaultIndex() { - const { payload } = await this._wreck.get('/api/kibana/settings'); - const defaultIndex = get(payload, 'settings.defaultIndex.userValue'); - this._log.verbose('uiSettings.defaultIndex: %j', defaultIndex); + const { data } = await this.x.get('/api/kibana/settings'); + const defaultIndex = get(data, 'settings.defaultIndex.userValue'); + this.log.verbose('uiSettings.defaultIndex: %j', defaultIndex); return defaultIndex; } - async replace(doc) { - const { payload } = await this._wreck.get('/api/kibana/settings'); + async replace(doc: Record) { + const { data } = await this.x.get('/api/kibana/settings'); - for (const key of Object.keys(payload.settings)) { - if (!payload.settings[key].isOverridden) { - await this._wreck.delete(`/api/kibana/settings/${key}`); + for (const key of Object.keys(data.settings)) { + if (!data.settings[key].isOverridden) { + await this.x.delete(`/api/kibana/settings/${key}`); } } - this._log.debug('replacing kibana config doc: %j', doc); + this.log.debug('replacing kibana config doc: %j', doc); - await this._wreck.post('/api/kibana/settings', { + await this.x.post('/api/kibana/settings', { payload: { changes: { - ...this._defaults, + ...this.defaults, ...doc, }, }, @@ -71,11 +74,10 @@ export class KibanaServerUiSettings { /** * Add fields to the config doc (like setting timezone and defaultIndex) - * @return {Promise} A promise that is resolved when elasticsearch has a response */ - async update(updates) { - this._log.debug('applying update to kibana config: %j', updates); - await this._wreck.post('/api/kibana/settings', { + async update(updates: Record) { + this.log.debug('applying update to kibana config: %j', updates); + await this.x.post('/api/kibana/settings', { payload: { changes: updates, }, diff --git a/test/common/services/kibana_server/version.js b/test/common/services/kibana_server/version.ts similarity index 73% rename from test/common/services/kibana_server/version.js rename to test/common/services/kibana_server/version.ts index b7efb01c63449..762223825ccd7 100644 --- a/test/common/services/kibana_server/version.js +++ b/test/common/services/kibana_server/version.ts @@ -17,21 +17,23 @@ * under the License. */ +import { KibanaServerStatus } from './status'; + export class KibanaServerVersion { - constructor(kibanaStatus) { - this.kibanaStatus = kibanaStatus; - this._cachedVersionNumber; - } + private cachedVersionNumber?: string; + + constructor(private readonly kibanaStatus: KibanaServerStatus) {} async get() { - if (this._cachedVersionNumber) { - return this._cachedVersionNumber; + if (this.cachedVersionNumber) { + return this.cachedVersionNumber; } const status = await this.kibanaStatus.get(); if (status && status.version && status.version.number) { - this._cachedVersionNumber = status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : ''); - return this._cachedVersionNumber; + this.cachedVersionNumber = + status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : ''); + return this.cachedVersionNumber; } throw new Error(`Unable to fetch Kibana Server status, received ${JSON.stringify(status)}`); From dbe719eea3f09f34b9adde04ef2f8725a6e3c198 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 20:53:22 -0700 Subject: [PATCH 05/11] expose server urls with better API --- test/common/services/kibana_server/kibana_server.ts | 8 ++++++-- .../tests/actions/builtin_action_types/pagerduty.ts | 9 ++++----- .../tests/actions/builtin_action_types/slack.ts | 9 ++++----- .../tests/actions/builtin_action_types/webhook.ts | 8 ++++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/test/common/services/kibana_server/kibana_server.ts b/test/common/services/kibana_server/kibana_server.ts index 6979d6649f3ea..9b6a9463d2d7f 100644 --- a/test/common/services/kibana_server/kibana_server.ts +++ b/test/common/services/kibana_server/kibana_server.ts @@ -17,7 +17,7 @@ * under the License. */ -import { format as formatUrl } from 'url'; +import Url from 'url'; import { FtrProviderContext } from '../../ftr_provider_context'; import { KibanaServerStatus } from './status'; @@ -30,7 +30,7 @@ export function KibanaServerProvider({ getService }: FtrProviderContext) { const config = getService('config'); const lifecycle = getService('lifecycle'); - const url = formatUrl(config.get('servers.kibana')); + const url = Url.format(config.get('servers.kibana')); return new (class KibanaServer { public readonly status = new KibanaServerStatus(url); @@ -42,5 +42,9 @@ export function KibanaServerProvider({ getService }: FtrProviderContext) { config.get('uiSettings.defaults'), lifecycle ); + + public resolveUrl(path = '/') { + return Url.resolve(url, path); + } })(); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts index 294f119881b70..4280e85376201 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts @@ -17,6 +17,7 @@ import { export default function pagerdutyTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); describe('pagerduty action', () => { let simulatedActionId = ''; @@ -24,11 +25,9 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) { // need to wait for kibanaServer to settle ... before(() => { - const kibanaServer = getService('kibanaServer'); - const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; - pagerdutySimulatorURL = `${kibanaUrl}${getExternalServiceSimulatorPath( - ExternalServiceSimulator.PAGERDUTY - )}`; + pagerdutySimulatorURL = kibanaServer.resolveUrl( + getExternalServiceSimulatorPath(ExternalServiceSimulator.PAGERDUTY) + ); }); after(() => esArchiver.unload('empty_kibana')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts index aa678ca910559..595058e72af0b 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts @@ -17,6 +17,7 @@ import { export default function slackTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); describe('slack action', () => { let simulatedActionId = ''; @@ -24,11 +25,9 @@ export default function slackTest({ getService }: FtrProviderContext) { // need to wait for kibanaServer to settle ... before(() => { - const kibanaServer = getService('kibanaServer'); - const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; - slackSimulatorURL = `${kibanaUrl}${getExternalServiceSimulatorPath( - ExternalServiceSimulator.SLACK - )}`; + slackSimulatorURL = kibanaServer.resolveUrl( + getExternalServiceSimulatorPath(ExternalServiceSimulator.SLACK) + ); }); after(() => esArchiver.unload('empty_kibana')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts index 89fc986fd0255..0f17019518824 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts @@ -28,6 +28,7 @@ function parsePort(url: Record): Record { - const kibanaServer = getService('kibanaServer'); - const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; - const webhookServiceUrl = getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK); - webhookSimulatorURL = `${kibanaUrl}${webhookServiceUrl}`; + webhookSimulatorURL = kibanaServer.resolveUrl( + getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK) + ); }); after(() => esArchiver.unload('empty_kibana')); From e94b60cca7acaa5d22c86d4ee03109ceabc3321e Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 21:09:28 -0700 Subject: [PATCH 06/11] tweak status api response types --- test/common/services/kibana_server/status.ts | 30 +++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/test/common/services/kibana_server/status.ts b/test/common/services/kibana_server/status.ts index 9bc3199930f97..ab53afce03b6e 100644 --- a/test/common/services/kibana_server/status.ts +++ b/test/common/services/kibana_server/status.ts @@ -19,19 +19,29 @@ import Axios from 'axios'; +interface Status { + id: string; + state: string; + icon: string; + message: string; + uiColor: string; + since: string; +} + interface StatusResponse { - status: { - overall: { - state: string; - [key: string]: unknown; - }; - [key: string]: unknown; + name: string; + uuid: string; + version: { + number: number; + build_hash: string; + build_number: number; + build_snapshot: boolean; }; - version?: { - number?: number; - build_snapshot?: boolean; + status: { + overall: Status; + statuses: Status[]; }; - [key: string]: unknown; + metrics: unknown; } export class KibanaServerStatus { From d713ce0cf64f67c622ca3ad65908cd6cb830b1f0 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 16 Sep 2019 22:06:44 -0700 Subject: [PATCH 07/11] fix http body param name --- test/common/services/kibana_server/ui_settings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/common/services/kibana_server/ui_settings.ts b/test/common/services/kibana_server/ui_settings.ts index 0a2b89e49d907..0b9b2bcc1c4b0 100644 --- a/test/common/services/kibana_server/ui_settings.ts +++ b/test/common/services/kibana_server/ui_settings.ts @@ -63,7 +63,7 @@ export class KibanaServerUiSettings { this.log.debug('replacing kibana config doc: %j', doc); await this.x.post('/api/kibana/settings', { - payload: { + data: { changes: { ...this.defaults, ...doc, @@ -78,7 +78,7 @@ export class KibanaServerUiSettings { async update(updates: Record) { this.log.debug('applying update to kibana config: %j', updates); await this.x.post('/api/kibana/settings', { - payload: { + data: { changes: updates, }, }); From 8dfcb733c6545559cd76eabb3b2bb3cd86438ba0 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 17 Sep 2019 06:56:19 -0700 Subject: [PATCH 08/11] second arg to axios post is the post data --- test/common/services/kibana_server/ui_settings.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/common/services/kibana_server/ui_settings.ts b/test/common/services/kibana_server/ui_settings.ts index 0b9b2bcc1c4b0..35c508c5c4b40 100644 --- a/test/common/services/kibana_server/ui_settings.ts +++ b/test/common/services/kibana_server/ui_settings.ts @@ -63,11 +63,9 @@ export class KibanaServerUiSettings { this.log.debug('replacing kibana config doc: %j', doc); await this.x.post('/api/kibana/settings', { - data: { - changes: { - ...this.defaults, - ...doc, - }, + changes: { + ...this.defaults, + ...doc, }, }); } @@ -78,9 +76,7 @@ export class KibanaServerUiSettings { async update(updates: Record) { this.log.debug('applying update to kibana config: %j', updates); await this.x.post('/api/kibana/settings', { - data: { - changes: updates, - }, + changes: updates, }); } } From 7e9a7f8dc50e26a9a38f120776dbd3d25e977557 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 17 Sep 2019 07:08:33 -0700 Subject: [PATCH 09/11] use standardized error handling behavior --- test/common/services/kibana_server/loader.ts | 44 +++++++++++++++++++ .../services/kibana_server/saved_objects.ts | 29 +++--------- test/common/services/kibana_server/status.ts | 9 ++-- .../services/kibana_server/ui_settings.ts | 36 +++++++++------ 4 files changed, 78 insertions(+), 40 deletions(-) create mode 100644 test/common/services/kibana_server/loader.ts diff --git a/test/common/services/kibana_server/loader.ts b/test/common/services/kibana_server/loader.ts new file mode 100644 index 0000000000000..4d275ca363cde --- /dev/null +++ b/test/common/services/kibana_server/loader.ts @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Axios, { AxiosRequestConfig } from 'axios'; + +export class Loader { + private readonly x = Axios.create({ + ...this.options, + headers: { + 'kbn-xsrf': 'KibanaServerSavedObjects', + }, + }); + + constructor(private readonly options: AxiosRequestConfig) {} + + public async req(desc: string, options: AxiosRequestConfig) { + try { + const resp = await this.x.request(options); + return resp.data; + } catch (error) { + if (error.response) { + throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`); + } + + throw error; + } + } +} diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts index 0e4a9a34bf2e4..9dbdd8d88dcc0 100644 --- a/test/common/services/kibana_server/saved_objects.ts +++ b/test/common/services/kibana_server/saved_objects.ts @@ -19,9 +19,10 @@ import Url from 'url'; -import Axios, { AxiosRequestConfig } from 'axios'; import { ToolingLog } from '@kbn/dev-utils'; +import { Loader } from './loader'; + const joinPath = (...components: Array) => `/${components .filter((s): s is string => !!s) @@ -65,11 +66,8 @@ interface UpdateOptions extends IndexOptions { } export class KibanaServerSavedObjects { - private readonly x = Axios.create({ + private readonly loader = new Loader({ baseURL: Url.resolve(this.url, '/api/saved_objects/'), - headers: { - 'kbn-xsrf': 'KibanaServerSavedObjects', - }, }); constructor(private readonly url: string, private readonly log: ToolingLog) {} @@ -80,7 +78,7 @@ export class KibanaServerSavedObjects { public async get>(options: GetOptions) { this.log.debug('Gettings saved object: %j', options); - return await this.request>('get saved object', { + return await this.loader.req>('get saved object', { url: joinPath(options.type, options.id), method: 'GET', }); @@ -92,7 +90,7 @@ export class KibanaServerSavedObjects { public async create>(options: IndexOptions) { this.log.debug('Creating saved object: %j', options); - return await this.request>('update saved object', { + return await this.loader.req>('update saved object', { url: joinPath(options.type, options.id), params: { overwrite: options.overwrite, @@ -112,7 +110,7 @@ export class KibanaServerSavedObjects { public async update>(options: UpdateOptions) { this.log.debug('Updating saved object: %j', options); - return await this.request>('update saved object', { + return await this.loader.req>('update saved object', { url: joinPath(options.type, options.id), params: { overwrite: options.overwrite, @@ -132,22 +130,9 @@ export class KibanaServerSavedObjects { public async delete(options: GetOptions) { this.log.debug('Deleting saved object %s/%s', options); - return await this.request('delete saved object', { + return await this.loader.req('delete saved object', { url: joinPath(options.type, options.id), method: 'DELETE', }); } - - private async request(desc: string, options: AxiosRequestConfig) { - try { - const resp = await this.x.request(options); - return resp.data; - } catch (error) { - if (error.response) { - throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`); - } - - throw error; - } - } } diff --git a/test/common/services/kibana_server/status.ts b/test/common/services/kibana_server/status.ts index ab53afce03b6e..0a09d6b05fc53 100644 --- a/test/common/services/kibana_server/status.ts +++ b/test/common/services/kibana_server/status.ts @@ -17,7 +17,7 @@ * under the License. */ -import Axios from 'axios'; +import { Loader } from './loader'; interface Status { id: string; @@ -45,15 +45,16 @@ interface StatusResponse { } export class KibanaServerStatus { - private readonly x = Axios.create({ + private readonly loader = new Loader({ baseURL: this.kibanaServerUrl, }); constructor(private readonly kibanaServerUrl: string) {} async get() { - const resp = await this.x.get('api/status'); - return resp.data; + return await this.loader.req('get status', { + url: 'api/status', + }); } async getOverallState() { diff --git a/test/common/services/kibana_server/ui_settings.ts b/test/common/services/kibana_server/ui_settings.ts index 35c508c5c4b40..0a5c166913b86 100644 --- a/test/common/services/kibana_server/ui_settings.ts +++ b/test/common/services/kibana_server/ui_settings.ts @@ -17,15 +17,17 @@ * under the License. */ -import Axios from 'axios'; +import Url from 'url'; + import { get } from 'lodash'; import { Lifecycle } from '@kbn/test/types/ftr'; - import { ToolingLog } from '@kbn/dev-utils'; +import { Loader } from './loader'; + export class KibanaServerUiSettings { - private readonly x = Axios.create({ - baseURL: this.url, + private readonly loader = new Loader({ + baseURL: Url.resolve(this.url, '/api/kibana/settings/'), }); constructor( @@ -45,27 +47,31 @@ export class KibanaServerUiSettings { * Gets defaultIndex from the config doc. */ async getDefaultIndex() { - const { data } = await this.x.get('/api/kibana/settings'); + const data = await this.loader.req('get default index', {}); const defaultIndex = get(data, 'settings.defaultIndex.userValue'); this.log.verbose('uiSettings.defaultIndex: %j', defaultIndex); return defaultIndex; } async replace(doc: Record) { - const { data } = await this.x.get('/api/kibana/settings'); + const data = await this.loader.req>('replace ui settings', {}); for (const key of Object.keys(data.settings)) { if (!data.settings[key].isOverridden) { - await this.x.delete(`/api/kibana/settings/${key}`); + await this.loader.req(`delete ${key}`, { + url: key, + method: 'DELETE', + }); } } this.log.debug('replacing kibana config doc: %j', doc); - - await this.x.post('/api/kibana/settings', { - changes: { - ...this.defaults, - ...doc, + await this.loader.req('replace kibana config doc', { + data: { + changes: { + ...this.defaults, + ...doc, + }, }, }); } @@ -75,8 +81,10 @@ export class KibanaServerUiSettings { */ async update(updates: Record) { this.log.debug('applying update to kibana config: %j', updates); - await this.x.post('/api/kibana/settings', { - changes: updates, + await this.loader.req('apply update to kibana config', { + data: { + changes: updates, + }, }); } } From ceca7ff3bbfac84578c24c0d084dff3556e88d14 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 17 Sep 2019 10:18:34 -0700 Subject: [PATCH 10/11] Revert "use standardized error handling behavior" This reverts commit 7e9a7f8dc50e26a9a38f120776dbd3d25e977557. --- test/common/services/kibana_server/loader.ts | 44 ------------------- .../services/kibana_server/saved_objects.ts | 29 +++++++++--- test/common/services/kibana_server/status.ts | 9 ++-- .../services/kibana_server/ui_settings.ts | 36 ++++++--------- 4 files changed, 40 insertions(+), 78 deletions(-) delete mode 100644 test/common/services/kibana_server/loader.ts diff --git a/test/common/services/kibana_server/loader.ts b/test/common/services/kibana_server/loader.ts deleted file mode 100644 index 4d275ca363cde..0000000000000 --- a/test/common/services/kibana_server/loader.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Axios, { AxiosRequestConfig } from 'axios'; - -export class Loader { - private readonly x = Axios.create({ - ...this.options, - headers: { - 'kbn-xsrf': 'KibanaServerSavedObjects', - }, - }); - - constructor(private readonly options: AxiosRequestConfig) {} - - public async req(desc: string, options: AxiosRequestConfig) { - try { - const resp = await this.x.request(options); - return resp.data; - } catch (error) { - if (error.response) { - throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`); - } - - throw error; - } - } -} diff --git a/test/common/services/kibana_server/saved_objects.ts b/test/common/services/kibana_server/saved_objects.ts index 9dbdd8d88dcc0..0e4a9a34bf2e4 100644 --- a/test/common/services/kibana_server/saved_objects.ts +++ b/test/common/services/kibana_server/saved_objects.ts @@ -19,10 +19,9 @@ import Url from 'url'; +import Axios, { AxiosRequestConfig } from 'axios'; import { ToolingLog } from '@kbn/dev-utils'; -import { Loader } from './loader'; - const joinPath = (...components: Array) => `/${components .filter((s): s is string => !!s) @@ -66,8 +65,11 @@ interface UpdateOptions extends IndexOptions { } export class KibanaServerSavedObjects { - private readonly loader = new Loader({ + private readonly x = Axios.create({ baseURL: Url.resolve(this.url, '/api/saved_objects/'), + headers: { + 'kbn-xsrf': 'KibanaServerSavedObjects', + }, }); constructor(private readonly url: string, private readonly log: ToolingLog) {} @@ -78,7 +80,7 @@ export class KibanaServerSavedObjects { public async get>(options: GetOptions) { this.log.debug('Gettings saved object: %j', options); - return await this.loader.req>('get saved object', { + return await this.request>('get saved object', { url: joinPath(options.type, options.id), method: 'GET', }); @@ -90,7 +92,7 @@ export class KibanaServerSavedObjects { public async create>(options: IndexOptions) { this.log.debug('Creating saved object: %j', options); - return await this.loader.req>('update saved object', { + return await this.request>('update saved object', { url: joinPath(options.type, options.id), params: { overwrite: options.overwrite, @@ -110,7 +112,7 @@ export class KibanaServerSavedObjects { public async update>(options: UpdateOptions) { this.log.debug('Updating saved object: %j', options); - return await this.loader.req>('update saved object', { + return await this.request>('update saved object', { url: joinPath(options.type, options.id), params: { overwrite: options.overwrite, @@ -130,9 +132,22 @@ export class KibanaServerSavedObjects { public async delete(options: GetOptions) { this.log.debug('Deleting saved object %s/%s', options); - return await this.loader.req('delete saved object', { + return await this.request('delete saved object', { url: joinPath(options.type, options.id), method: 'DELETE', }); } + + private async request(desc: string, options: AxiosRequestConfig) { + try { + const resp = await this.x.request(options); + return resp.data; + } catch (error) { + if (error.response) { + throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`); + } + + throw error; + } + } } diff --git a/test/common/services/kibana_server/status.ts b/test/common/services/kibana_server/status.ts index 0a09d6b05fc53..ab53afce03b6e 100644 --- a/test/common/services/kibana_server/status.ts +++ b/test/common/services/kibana_server/status.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Loader } from './loader'; +import Axios from 'axios'; interface Status { id: string; @@ -45,16 +45,15 @@ interface StatusResponse { } export class KibanaServerStatus { - private readonly loader = new Loader({ + private readonly x = Axios.create({ baseURL: this.kibanaServerUrl, }); constructor(private readonly kibanaServerUrl: string) {} async get() { - return await this.loader.req('get status', { - url: 'api/status', - }); + const resp = await this.x.get('api/status'); + return resp.data; } async getOverallState() { diff --git a/test/common/services/kibana_server/ui_settings.ts b/test/common/services/kibana_server/ui_settings.ts index 0a5c166913b86..35c508c5c4b40 100644 --- a/test/common/services/kibana_server/ui_settings.ts +++ b/test/common/services/kibana_server/ui_settings.ts @@ -17,17 +17,15 @@ * under the License. */ -import Url from 'url'; - +import Axios from 'axios'; import { get } from 'lodash'; import { Lifecycle } from '@kbn/test/types/ftr'; -import { ToolingLog } from '@kbn/dev-utils'; -import { Loader } from './loader'; +import { ToolingLog } from '@kbn/dev-utils'; export class KibanaServerUiSettings { - private readonly loader = new Loader({ - baseURL: Url.resolve(this.url, '/api/kibana/settings/'), + private readonly x = Axios.create({ + baseURL: this.url, }); constructor( @@ -47,31 +45,27 @@ export class KibanaServerUiSettings { * Gets defaultIndex from the config doc. */ async getDefaultIndex() { - const data = await this.loader.req('get default index', {}); + const { data } = await this.x.get('/api/kibana/settings'); const defaultIndex = get(data, 'settings.defaultIndex.userValue'); this.log.verbose('uiSettings.defaultIndex: %j', defaultIndex); return defaultIndex; } async replace(doc: Record) { - const data = await this.loader.req>('replace ui settings', {}); + const { data } = await this.x.get('/api/kibana/settings'); for (const key of Object.keys(data.settings)) { if (!data.settings[key].isOverridden) { - await this.loader.req(`delete ${key}`, { - url: key, - method: 'DELETE', - }); + await this.x.delete(`/api/kibana/settings/${key}`); } } this.log.debug('replacing kibana config doc: %j', doc); - await this.loader.req('replace kibana config doc', { - data: { - changes: { - ...this.defaults, - ...doc, - }, + + await this.x.post('/api/kibana/settings', { + changes: { + ...this.defaults, + ...doc, }, }); } @@ -81,10 +75,8 @@ export class KibanaServerUiSettings { */ async update(updates: Record) { this.log.debug('applying update to kibana config: %j', updates); - await this.loader.req('apply update to kibana config', { - data: { - changes: updates, - }, + await this.x.post('/api/kibana/settings', { + changes: updates, }); } } From d752fd0d617fc44b12c510ee0b5900d92ad9c99d Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 17 Sep 2019 10:23:41 -0700 Subject: [PATCH 11/11] revert unnecessary changes --- test/common/services/es_archiver.ts | 11 +-- ...d_es_archiver.ts => extend_es_archiver.js} | 17 +--- test/common/services/kibana_server/index.ts | 1 + .../services/kibana_server/kibana_server.ts | 3 + .../kibana_server/{status.ts => status.js} | 41 +++------ .../services/kibana_server/ui_settings.js | 84 +++++++++++++++++++ .../services/kibana_server/ui_settings.ts | 82 ------------------ .../kibana_server/{version.ts => version.js} | 18 ++-- .../actions/builtin_action_types/pagerduty.ts | 9 +- .../actions/builtin_action_types/slack.ts | 9 +- .../actions/builtin_action_types/webhook.ts | 8 +- 11 files changed, 129 insertions(+), 154 deletions(-) rename test/common/services/kibana_server/{extend_es_archiver.ts => extend_es_archiver.js} (77%) rename test/common/services/kibana_server/{status.ts => status.js} (60%) create mode 100644 test/common/services/kibana_server/ui_settings.js delete mode 100644 test/common/services/kibana_server/ui_settings.ts rename test/common/services/kibana_server/{version.ts => version.js} (73%) diff --git a/test/common/services/es_archiver.ts b/test/common/services/es_archiver.ts index bb0c6d3e5a008..e72bb49a76c0d 100644 --- a/test/common/services/es_archiver.ts +++ b/test/common/services/es_archiver.ts @@ -21,6 +21,7 @@ import { format as formatUrl } from 'url'; import { FtrProviderContext } from '../ftr_provider_context'; import { EsArchiver } from '../../../src/es_archiver'; +// @ts-ignore not TS yet import * as KibanaServer from './kibana_server'; export function EsArchiverProvider({ getService, hasService }: FtrProviderContext): EsArchiver { @@ -42,12 +43,12 @@ export function EsArchiverProvider({ getService, hasService }: FtrProviderContex }); if (hasService('kibanaServer')) { - KibanaServer.extendEsArchiver( + KibanaServer.extendEsArchiver({ esArchiver, - getService('kibanaServer'), - getService('retry'), - config.get('uiSettings.defaults') - ); + kibanaServer: getService('kibanaServer'), + retry: getService('retry'), + defaults: config.get('uiSettings.defaults'), + }); } return esArchiver; diff --git a/test/common/services/kibana_server/extend_es_archiver.ts b/test/common/services/kibana_server/extend_es_archiver.js similarity index 77% rename from test/common/services/kibana_server/extend_es_archiver.ts rename to test/common/services/kibana_server/extend_es_archiver.js index a132a2731ea1c..d934e6725a9f5 100644 --- a/test/common/services/kibana_server/extend_es_archiver.ts +++ b/test/common/services/kibana_server/extend_es_archiver.js @@ -17,21 +17,10 @@ * under the License. */ -import { ProvidedType } from '@kbn/test/types/ftr'; - -import { EsArchiver } from '../../../../src/es_archiver'; -import { KibanaServerProvider } from './kibana_server'; -import { RetryProvider } from '../retry'; - -const ES_ARCHIVER_LOAD_METHODS = ['load', 'loadIfNeeded', 'unload'] as const; +const ES_ARCHIVER_LOAD_METHODS = ['load', 'loadIfNeeded', 'unload']; const KIBANA_INDEX = '.kibana'; -export function extendEsArchiver( - esArchiver: EsArchiver, - kibanaServer: ProvidedType, - retry: ProvidedType, - defaults: Record -) { +export function extendEsArchiver({ esArchiver, kibanaServer, retry, defaults }) { // only extend the esArchiver if there are default uiSettings to restore if (!defaults) { return; @@ -40,7 +29,7 @@ export function extendEsArchiver( ES_ARCHIVER_LOAD_METHODS.forEach(method => { const originalMethod = esArchiver[method]; - esArchiver[method] = async (...args: any) => { + esArchiver[method] = async (...args) => { // esArchiver methods return a stats object, with information about the indexes created const stats = await originalMethod.apply(esArchiver, args); diff --git a/test/common/services/kibana_server/index.ts b/test/common/services/kibana_server/index.ts index 6d9035008c6b7..edf6cd6522284 100644 --- a/test/common/services/kibana_server/index.ts +++ b/test/common/services/kibana_server/index.ts @@ -18,4 +18,5 @@ */ export { KibanaServerProvider } from './kibana_server'; +// @ts-ignore export { extendEsArchiver } from './extend_es_archiver'; diff --git a/test/common/services/kibana_server/kibana_server.ts b/test/common/services/kibana_server/kibana_server.ts index 9b6a9463d2d7f..1455eb8ed8aa4 100644 --- a/test/common/services/kibana_server/kibana_server.ts +++ b/test/common/services/kibana_server/kibana_server.ts @@ -20,8 +20,11 @@ import Url from 'url'; import { FtrProviderContext } from '../../ftr_provider_context'; +// @ts-ignore not ts yet import { KibanaServerStatus } from './status'; +// @ts-ignore not ts yet import { KibanaServerUiSettings } from './ui_settings'; +// @ts-ignore not ts yet import { KibanaServerVersion } from './version'; import { KibanaServerSavedObjects } from './saved_objects'; diff --git a/test/common/services/kibana_server/status.ts b/test/common/services/kibana_server/status.js similarity index 60% rename from test/common/services/kibana_server/status.ts rename to test/common/services/kibana_server/status.js index ab53afce03b6e..3988bab185fcc 100644 --- a/test/common/services/kibana_server/status.ts +++ b/test/common/services/kibana_server/status.js @@ -17,43 +17,22 @@ * under the License. */ -import Axios from 'axios'; +import { resolve as resolveUrl } from 'url'; -interface Status { - id: string; - state: string; - icon: string; - message: string; - uiColor: string; - since: string; -} +import Wreck from '@hapi/wreck'; -interface StatusResponse { - name: string; - uuid: string; - version: { - number: number; - build_hash: string; - build_number: number; - build_snapshot: boolean; - }; - status: { - overall: Status; - statuses: Status[]; - }; - metrics: unknown; -} +const get = async url => { + const { payload } = await Wreck.get(url, { json: 'force' }); + return payload; +}; export class KibanaServerStatus { - private readonly x = Axios.create({ - baseURL: this.kibanaServerUrl, - }); - - constructor(private readonly kibanaServerUrl: string) {} + constructor(kibanaServerUrl) { + this.kibanaServerUrl = kibanaServerUrl; + } async get() { - const resp = await this.x.get('api/status'); - return resp.data; + return await get(resolveUrl(this.kibanaServerUrl, './api/status')); } async getOverallState() { diff --git a/test/common/services/kibana_server/ui_settings.js b/test/common/services/kibana_server/ui_settings.js new file mode 100644 index 0000000000000..aa75839c20152 --- /dev/null +++ b/test/common/services/kibana_server/ui_settings.js @@ -0,0 +1,84 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Wreck from '@hapi/wreck'; +import { get } from 'lodash'; + +export class KibanaServerUiSettings { + constructor(url, log, defaults, lifecycle) { + this._log = log; + this._defaults = defaults; + this._wreck = Wreck.defaults({ + headers: { 'kbn-xsrf': 'ftr/services/uiSettings' }, + baseUrl: url, + json: true, + redirects: 3, + }); + + if (this._defaults) { + lifecycle.on('beforeTests', async () => { + await this.update(defaults); + }); + } + } + + /** + * Gets defaultIndex from the config doc. + */ + async getDefaultIndex() { + const { payload } = await this._wreck.get('/api/kibana/settings'); + const defaultIndex = get(payload, 'settings.defaultIndex.userValue'); + this._log.verbose('uiSettings.defaultIndex: %j', defaultIndex); + return defaultIndex; + } + + async replace(doc) { + const { payload } = await this._wreck.get('/api/kibana/settings'); + + for (const key of Object.keys(payload.settings)) { + if (!payload.settings[key].isOverridden) { + await this._wreck.delete(`/api/kibana/settings/${key}`); + } + } + + this._log.debug('replacing kibana config doc: %j', doc); + + await this._wreck.post('/api/kibana/settings', { + payload: { + changes: { + ...this._defaults, + ...doc, + }, + }, + }); + } + + /** + * Add fields to the config doc (like setting timezone and defaultIndex) + * @return {Promise} A promise that is resolved when elasticsearch has a response + */ + async update(updates) { + this._log.debug('applying update to kibana config: %j', updates); + await this._wreck.post('/api/kibana/settings', { + payload: { + changes: updates, + }, + }); + } +} diff --git a/test/common/services/kibana_server/ui_settings.ts b/test/common/services/kibana_server/ui_settings.ts deleted file mode 100644 index 35c508c5c4b40..0000000000000 --- a/test/common/services/kibana_server/ui_settings.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Axios from 'axios'; -import { get } from 'lodash'; -import { Lifecycle } from '@kbn/test/types/ftr'; - -import { ToolingLog } from '@kbn/dev-utils'; - -export class KibanaServerUiSettings { - private readonly x = Axios.create({ - baseURL: this.url, - }); - - constructor( - private readonly url: string, - private readonly log: ToolingLog, - private readonly defaults: Record, - private readonly lifecycle: Lifecycle - ) { - if (this.defaults) { - this.lifecycle.on('beforeTests', async () => { - await this.update(defaults); - }); - } - } - - /** - * Gets defaultIndex from the config doc. - */ - async getDefaultIndex() { - const { data } = await this.x.get('/api/kibana/settings'); - const defaultIndex = get(data, 'settings.defaultIndex.userValue'); - this.log.verbose('uiSettings.defaultIndex: %j', defaultIndex); - return defaultIndex; - } - - async replace(doc: Record) { - const { data } = await this.x.get('/api/kibana/settings'); - - for (const key of Object.keys(data.settings)) { - if (!data.settings[key].isOverridden) { - await this.x.delete(`/api/kibana/settings/${key}`); - } - } - - this.log.debug('replacing kibana config doc: %j', doc); - - await this.x.post('/api/kibana/settings', { - changes: { - ...this.defaults, - ...doc, - }, - }); - } - - /** - * Add fields to the config doc (like setting timezone and defaultIndex) - */ - async update(updates: Record) { - this.log.debug('applying update to kibana config: %j', updates); - await this.x.post('/api/kibana/settings', { - changes: updates, - }); - } -} diff --git a/test/common/services/kibana_server/version.ts b/test/common/services/kibana_server/version.js similarity index 73% rename from test/common/services/kibana_server/version.ts rename to test/common/services/kibana_server/version.js index 762223825ccd7..b7efb01c63449 100644 --- a/test/common/services/kibana_server/version.ts +++ b/test/common/services/kibana_server/version.js @@ -17,23 +17,21 @@ * under the License. */ -import { KibanaServerStatus } from './status'; - export class KibanaServerVersion { - private cachedVersionNumber?: string; - - constructor(private readonly kibanaStatus: KibanaServerStatus) {} + constructor(kibanaStatus) { + this.kibanaStatus = kibanaStatus; + this._cachedVersionNumber; + } async get() { - if (this.cachedVersionNumber) { - return this.cachedVersionNumber; + if (this._cachedVersionNumber) { + return this._cachedVersionNumber; } const status = await this.kibanaStatus.get(); if (status && status.version && status.version.number) { - this.cachedVersionNumber = - status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : ''); - return this.cachedVersionNumber; + this._cachedVersionNumber = status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : ''); + return this._cachedVersionNumber; } throw new Error(`Unable to fetch Kibana Server status, received ${JSON.stringify(status)}`); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts index 4280e85376201..294f119881b70 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts @@ -17,7 +17,6 @@ import { export default function pagerdutyTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); describe('pagerduty action', () => { let simulatedActionId = ''; @@ -25,9 +24,11 @@ export default function pagerdutyTest({ getService }: FtrProviderContext) { // need to wait for kibanaServer to settle ... before(() => { - pagerdutySimulatorURL = kibanaServer.resolveUrl( - getExternalServiceSimulatorPath(ExternalServiceSimulator.PAGERDUTY) - ); + const kibanaServer = getService('kibanaServer'); + const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; + pagerdutySimulatorURL = `${kibanaUrl}${getExternalServiceSimulatorPath( + ExternalServiceSimulator.PAGERDUTY + )}`; }); after(() => esArchiver.unload('empty_kibana')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts index 595058e72af0b..aa678ca910559 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts @@ -17,7 +17,6 @@ import { export default function slackTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); describe('slack action', () => { let simulatedActionId = ''; @@ -25,9 +24,11 @@ export default function slackTest({ getService }: FtrProviderContext) { // need to wait for kibanaServer to settle ... before(() => { - slackSimulatorURL = kibanaServer.resolveUrl( - getExternalServiceSimulatorPath(ExternalServiceSimulator.SLACK) - ); + const kibanaServer = getService('kibanaServer'); + const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; + slackSimulatorURL = `${kibanaUrl}${getExternalServiceSimulatorPath( + ExternalServiceSimulator.SLACK + )}`; }); after(() => esArchiver.unload('empty_kibana')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts index 0f17019518824..89fc986fd0255 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts @@ -28,7 +28,6 @@ function parsePort(url: Record): Record { - webhookSimulatorURL = kibanaServer.resolveUrl( - getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK) - ); + const kibanaServer = getService('kibanaServer'); + const kibanaUrl = kibanaServer.status && kibanaServer.status.kibanaServerUrl; + const webhookServiceUrl = getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK); + webhookSimulatorURL = `${kibanaUrl}${webhookServiceUrl}`; }); after(() => esArchiver.unload('empty_kibana'));