diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 5347f0b55e19b..98d7b0610abea 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -153,6 +153,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectMigrationMap](./kibana-plugin-core-server.savedobjectmigrationmap.md) | A map of [migration functions](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used for a given type. The map's keys must be valid semver versions.For a given document, only migrations with a higher version number than that of the document will be applied. Migrations are executed in order, starting from the lowest version and ending with the highest one. | | [SavedObjectReference](./kibana-plugin-core-server.savedobjectreference.md) | A reference to another saved object. | | [SavedObjectsAddToNamespacesOptions](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md) | | +| [SavedObjectsAddToNamespacesResponse](./kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md) | | | [SavedObjectsBaseOptions](./kibana-plugin-core-server.savedobjectsbaseoptions.md) | | | [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) | | | [SavedObjectsBulkGetObject](./kibana-plugin-core-server.savedobjectsbulkgetobject.md) | | @@ -167,6 +168,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md) | | | [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-core-server.savedobjectsdeletebynamespaceoptions.md) | | | [SavedObjectsDeleteFromNamespacesOptions](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md) | | +| [SavedObjectsDeleteFromNamespacesResponse](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md) | | | [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | | [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) | Options controlling the export operation. | | [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md new file mode 100644 index 0000000000000..306f502f0b0b3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsAddToNamespacesResponse](./kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md) + +## SavedObjectsAddToNamespacesResponse interface + + +Signature: + +```typescript +export interface SavedObjectsAddToNamespacesResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespaces](./kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.namespaces.md) | string[] | The namespaces the object exists in after this operation is complete. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.namespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.namespaces.md new file mode 100644 index 0000000000000..4fc2e376304d4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.namespaces.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsAddToNamespacesResponse](./kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.md) > [namespaces](./kibana-plugin-core-server.savedobjectsaddtonamespacesresponse.namespaces.md) + +## SavedObjectsAddToNamespacesResponse.namespaces property + +The namespaces the object exists in after this operation is complete. + +Signature: + +```typescript +namespaces: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md index 45c9c39f9626a..567390faba9b2 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md @@ -9,7 +9,7 @@ Adds namespaces to a SavedObject Signature: ```typescript -addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; +addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise; ``` ## Parameters @@ -23,5 +23,5 @@ addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedO Returns: -`Promise<{}>` +`Promise` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md index 80b58d29d393b..18ef5c3e6350c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md @@ -9,7 +9,7 @@ Removes namespaces from a SavedObject Signature: ```typescript -deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; +deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise; ``` ## Parameters @@ -23,5 +23,5 @@ deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: S Returns: -`Promise<{}>` +`Promise` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md new file mode 100644 index 0000000000000..6021c8866f018 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsDeleteFromNamespacesResponse](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md) + +## SavedObjectsDeleteFromNamespacesResponse interface + + +Signature: + +```typescript +export interface SavedObjectsDeleteFromNamespacesResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [namespaces](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.namespaces.md) | string[] | The namespaces the object exists in after this operation is complete. An empty array indicates the object was deleted. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.namespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.namespaces.md new file mode 100644 index 0000000000000..9600a9e891380 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.namespaces.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsDeleteFromNamespacesResponse](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md) > [namespaces](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.namespaces.md) + +## SavedObjectsDeleteFromNamespacesResponse.namespaces property + +The namespaces the object exists in after this operation is complete. An empty array indicates the object was deleted. + +Signature: + +```typescript +namespaces: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md index bbb20d2bc3b96..4b69b10318ed3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md @@ -9,7 +9,7 @@ Adds one or more namespaces to a given multi-namespace saved object. This method Signature: ```typescript -addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; +addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise; ``` ## Parameters @@ -23,5 +23,5 @@ addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedO Returns: -`Promise<{}>` +`Promise` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md index 471c3e3c5092d..d5ffb6d9ff9d8 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md @@ -9,7 +9,7 @@ Removes one or more namespaces from a given multi-namespace saved object. If no Signature: ```typescript -deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; +deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise; ``` ## Parameters @@ -23,5 +23,5 @@ deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: S Returns: -`Promise<{}>` +`Promise` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md index 4233eea42cded..c54e549c42a44 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md @@ -7,5 +7,5 @@ Signature: ```typescript -export declare type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +export declare type FieldFormatsGetConfigFn = GetConfigFn; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md index 5bd1694cbeea3..337b4b3302cc3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md @@ -4,12 +4,13 @@ ## getSearchParamsFromRequest() function + Signature: ```typescript export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - injectedMetadata: CoreStart['injectedMetadata']; - uiSettings: IUiSettingsClient; + esShardTimeout: number; + getConfig: GetConfigFn; }): ISearchRequestParams; ``` @@ -18,7 +19,7 @@ export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, | Parameter | Type | Description | | --- | --- | --- | | searchRequest | SearchRequest | | -| dependencies | {
injectedMetadata: CoreStart['injectedMetadata'];
uiSettings: IUiSettingsClient;
} | | +| dependencies | {
esShardTimeout: number;
getConfig: GetConfigFn;
} | | Returns: diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md index c8815ed42d3b3..a3f6c709246ea 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md @@ -7,5 +7,5 @@ Signature: ```typescript -export declare type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +export declare type FieldFormatsGetConfigFn = GetConfigFn; ``` diff --git a/package.json b/package.json index 7d12af2eb5066..23fc31f369b8d 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "dependencies": { "@babel/core": "^7.11.1", "@babel/register": "^7.10.5", - "@elastic/apm-rum": "^5.4.0", + "@elastic/apm-rum": "^5.5.0", "@elastic/charts": "19.8.1", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "7.9.0-rc.2", diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 382318ea86a34..76bcf5f7df665 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -274,7 +274,9 @@ export { SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, SavedObjectsAddToNamespacesOptions, + SavedObjectsAddToNamespacesResponse, SavedObjectsDeleteFromNamespacesOptions, + SavedObjectsDeleteFromNamespacesResponse, SavedObjectsServiceStart, SavedObjectsServiceSetup, SavedObjectStatusMeta, diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 941c4091a66a7..6d85223d1fc88 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -393,14 +393,14 @@ describe('SavedObjectsRepository', () => { }); describe('returns', () => { - it(`returns an empty object on success`, async () => { + it(`returns all existing and new namespaces on success`, async () => { const result = await addToNamespacesSuccess(type, id, [newNs1, newNs2]); - expect(result).toEqual({}); + expect(result).toEqual({ namespaces: [currentNs1, currentNs2, newNs1, newNs2] }); }); it(`succeeds when adding existing namespaces`, async () => { const result = await addToNamespacesSuccess(type, id, [currentNs1]); - expect(result).toEqual({}); + expect(result).toEqual({ namespaces: [currentNs1, currentNs2] }); }); }); }); @@ -3102,17 +3102,17 @@ describe('SavedObjectsRepository', () => { }); describe('returns', () => { - it(`returns an empty object on success (delete)`, async () => { + it(`returns an empty namespaces array on success (delete)`, async () => { const test = async (namespaces) => { const result = await deleteFromNamespacesSuccess(type, id, namespaces, namespaces); - expect(result).toEqual({}); + expect(result).toEqual({ namespaces: [] }); client.delete.mockClear(); }; await test([namespace1]); await test([namespace1, namespace2]); }); - it(`returns an empty object on success (update)`, async () => { + it(`returns remaining namespaces on success (update)`, async () => { const test = async (remaining) => { const currentNamespaces = [namespace1].concat(remaining); const result = await deleteFromNamespacesSuccess( @@ -3121,7 +3121,7 @@ describe('SavedObjectsRepository', () => { [namespace1], currentNamespaces ); - expect(result).toEqual({}); + expect(result).toEqual({ namespaces: remaining }); client.delete.mockClear(); }; await test([namespace2]); @@ -3132,7 +3132,7 @@ describe('SavedObjectsRepository', () => { const namespaces = [namespace2]; const currentNamespaces = [namespace1]; const result = await deleteFromNamespacesSuccess(type, id, namespaces, currentNamespaces); - expect(result).toEqual({}); + expect(result).toEqual({ namespaces: currentNamespaces }); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 9f6db446ea195..28d409f7b65bb 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -52,7 +52,9 @@ import { SavedObjectsBulkUpdateOptions, SavedObjectsDeleteOptions, SavedObjectsAddToNamespacesOptions, + SavedObjectsAddToNamespacesResponse, SavedObjectsDeleteFromNamespacesOptions, + SavedObjectsDeleteFromNamespacesResponse, } from '../saved_objects_client'; import { SavedObject, @@ -947,7 +949,7 @@ export class SavedObjectsRepository { id: string, namespaces: string[], options: SavedObjectsAddToNamespacesOptions = {} - ): Promise<{}> { + ): Promise { if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } @@ -996,7 +998,7 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - return {}; + return { namespaces: doc.namespaces }; } /** @@ -1009,7 +1011,7 @@ export class SavedObjectsRepository { id: string, namespaces: string[], options: SavedObjectsDeleteFromNamespacesOptions = {} - ): Promise<{}> { + ): Promise { if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } @@ -1063,7 +1065,7 @@ export class SavedObjectsRepository { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - return {}; + return { namespaces: doc.namespaces }; } else { // if there are no namespaces remaining, delete the saved object const { body, statusCode } = await this.client.delete( @@ -1080,7 +1082,7 @@ export class SavedObjectsRepository { const deleted = body.result === 'deleted'; if (deleted) { - return {}; + return { namespaces: [] }; } const deleteDocNotFound = body.result === 'not_found'; diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index 6a9f4f5143e84..812669ee108a2 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -135,6 +135,15 @@ export interface SavedObjectsAddToNamespacesOptions extends SavedObjectsBaseOpti refresh?: MutatingOperationRefreshSetting; } +/** + * + * @public + */ +export interface SavedObjectsAddToNamespacesResponse { + /** The namespaces the object exists in after this operation is complete. */ + namespaces: string[]; +} + /** * * @public @@ -144,6 +153,15 @@ export interface SavedObjectsDeleteFromNamespacesOptions extends SavedObjectsBas refresh?: MutatingOperationRefreshSetting; } +/** + * + * @public + */ +export interface SavedObjectsDeleteFromNamespacesResponse { + /** The namespaces the object exists in after this operation is complete. An empty array indicates the object was deleted. */ + namespaces: string[]; +} + /** * * @public @@ -320,7 +338,7 @@ export class SavedObjectsClient { id: string, namespaces: string[], options: SavedObjectsAddToNamespacesOptions = {} - ): Promise<{}> { + ): Promise { return await this._repository.addToNamespaces(type, id, namespaces, options); } @@ -337,7 +355,7 @@ export class SavedObjectsClient { id: string, namespaces: string[], options: SavedObjectsDeleteFromNamespacesOptions = {} - ): Promise<{}> { + ): Promise { return await this._repository.deleteFromNamespaces(type, id, namespaces, options); } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ff178e236a12f..772be68f507d5 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2023,6 +2023,11 @@ export interface SavedObjectsAddToNamespacesOptions extends SavedObjectsBaseOpti version?: string; } +// @public (undocumented) +export interface SavedObjectsAddToNamespacesResponse { + namespaces: string[]; +} + // Warning: (ae-forgotten-export) The symbol "SavedObjectDoc" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Referencable" needs to be exported by the entry point index.d.ts // @@ -2092,13 +2097,13 @@ export interface SavedObjectsBulkUpdateResponse { export class SavedObjectsClient { // @internal constructor(repository: ISavedObjectsRepository); - addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; + addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise; bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; - deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; + deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise; // (undocumented) static errors: typeof SavedObjectsErrorHelpers; // (undocumented) @@ -2194,6 +2199,11 @@ export interface SavedObjectsDeleteFromNamespacesOptions extends SavedObjectsBas refresh?: MutatingOperationRefreshSetting; } +// @public (undocumented) +export interface SavedObjectsDeleteFromNamespacesResponse { + namespaces: string[]; +} + // @public (undocumented) export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { refresh?: MutatingOperationRefreshSetting; @@ -2492,7 +2502,7 @@ export interface SavedObjectsRawDoc { // @public (undocumented) export class SavedObjectsRepository { - addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; + addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise; bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; @@ -2503,7 +2513,7 @@ export class SavedObjectsRepository { static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, client: ElasticsearchClient, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; - deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; + deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise; // (undocumented) find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, }: SavedObjectsFindOptions): Promise>; get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; diff --git a/src/legacy/ui/public/new_platform/set_services.ts b/src/legacy/ui/public/new_platform/set_services.ts index ee92eda064aa8..036157a9f3fbc 100644 --- a/src/legacy/ui/public/new_platform/set_services.ts +++ b/src/legacy/ui/public/new_platform/set_services.ts @@ -41,7 +41,6 @@ interface NpStart { export function setSetupServices(npSetup: NpSetup) { // Services that need to be set in the legacy platform since the legacy data plugin // which previously provided them has been removed. - dataServices.setInjectedMetadata(npSetup.core.injectedMetadata); visualizationsServices.setUISettings(npSetup.core.uiSettings); visualizationsServices.setUsageCollector(npSetup.plugins.usageCollection); } @@ -49,7 +48,6 @@ export function setSetupServices(npSetup: NpSetup) { export function setStartServices(npStart: NpStart) { // Services that need to be set in the legacy platform since the legacy data plugin // which previously provided them has been removed. - dataServices.setHttp(npStart.core.http); dataServices.setNotifications(npStart.core.notifications); dataServices.setOverlays(npStart.core.overlays); dataServices.setUiSettings(npStart.core.uiSettings); diff --git a/src/plugins/data/common/es_query/es_query/get_es_query_config.ts b/src/plugins/data/common/es_query/es_query/get_es_query_config.ts index ff8fc5b11b26e..87dbbcee03b81 100644 --- a/src/plugins/data/common/es_query/es_query/get_es_query_config.ts +++ b/src/plugins/data/common/es_query/es_query/get_es_query_config.ts @@ -18,10 +18,10 @@ */ import { EsQueryConfig } from './build_es_query'; -import { UI_SETTINGS } from '../../'; +import { GetConfigFn, UI_SETTINGS } from '../../'; interface KibanaConfig { - get(key: string): T; + get: GetConfigFn; } export function getEsQueryConfig(config: KibanaConfig) { diff --git a/src/plugins/data/common/field_formats/converters/date_nanos_shared.ts b/src/plugins/data/common/field_formats/converters/date_nanos_shared.ts index 89a63243c76f0..7a225cd7d1ae7 100644 --- a/src/plugins/data/common/field_formats/converters/date_nanos_shared.ts +++ b/src/plugins/data/common/field_formats/converters/date_nanos_shared.ts @@ -20,7 +20,8 @@ import { i18n } from '@kbn/i18n'; import { memoize, noop } from 'lodash'; import moment, { Moment } from 'moment'; -import { FieldFormat, FIELD_FORMAT_IDS, KBN_FIELD_TYPES, TextContextTypeConvert } from '../../'; +import { FieldFormat, FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../'; +import { TextContextTypeConvert } from '../types'; /** * Analyse the given moment.js format pattern for the fractional sec part (S,SS,SSS...) diff --git a/src/plugins/data/common/field_formats/field_formats_registry.ts b/src/plugins/data/common/field_formats/field_formats_registry.ts index 4b847ebc358d7..32f9f37b9ba53 100644 --- a/src/plugins/data/common/field_formats/field_formats_registry.ts +++ b/src/plugins/data/common/field_formats/field_formats_registry.ts @@ -32,7 +32,7 @@ import { import { baseFormatters } from './constants/base_formatters'; import { FieldFormat } from './field_format'; import { SerializedFieldFormat } from '../../../expressions/common/types'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../types'; +import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../kbn_field_types/types'; import { UI_SETTINGS } from '../constants'; export class FieldFormatsRegistry { diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts index 6f773378de08d..daa44b2b0f85b 100644 --- a/src/plugins/data/common/field_formats/types.ts +++ b/src/plugins/data/common/field_formats/types.ts @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +import { GetConfigFn } from '../types'; import { FieldFormat } from './field_format'; import { FieldFormatsRegistry } from './field_formats_registry'; @@ -72,7 +74,7 @@ export interface FieldFormatConfig { es?: boolean; } -export type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +export type FieldFormatsGetConfigFn = GetConfigFn; export type IFieldFormat = PublicMethodsOf; diff --git a/src/plugins/data/common/search/aggs/aggs_service.ts b/src/plugins/data/common/search/aggs/aggs_service.ts index 59c54fcce6838..6f3e3904dbbd5 100644 --- a/src/plugins/data/common/search/aggs/aggs_service.ts +++ b/src/plugins/data/common/search/aggs/aggs_service.ts @@ -19,6 +19,7 @@ import { ExpressionsServiceSetup } from 'src/plugins/expressions/common'; import { UI_SETTINGS } from '../../../common'; +import { GetConfigFn } from '../../types'; import { AggConfigs, AggTypesRegistry, @@ -48,7 +49,7 @@ export interface AggsCommonSetupDependencies { /** @internal */ export interface AggsCommonStartDependencies { - getConfig: (key: string) => T; + getConfig: GetConfigFn; } /** diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index e2ec1a031b0ca..a1e1252b3112f 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -20,4 +20,15 @@ export * from './query/types'; export * from './kbn_field_types/types'; export * from './index_patterns/types'; -export { TextContextTypeConvert, IFieldFormatMetaParams } from './field_formats/types'; + +/** + * If a service is being shared on both the client and the server, and + * the client code requires synchronous access to uiSettings, both client + * and server should wrap the core uiSettings services in a function + * matching this signature. + * + * This matches the signature of the public `core.uiSettings.get`, and + * should only be used in scenarios where async access to uiSettings is + * not possible. + */ +export type GetConfigFn = (key: string, defaultOverride?: T) => T; diff --git a/src/plugins/data/public/field_formats/converters/date.ts b/src/plugins/data/public/field_formats/converters/date.ts index 78ef8b293e8b9..8070633ef2dfe 100644 --- a/src/plugins/data/public/field_formats/converters/date.ts +++ b/src/plugins/data/public/field_formats/converters/date.ts @@ -20,12 +20,8 @@ import { i18n } from '@kbn/i18n'; import { memoize, noop } from 'lodash'; import moment from 'moment'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, - FIELD_FORMAT_IDS, -} from '../../../common'; +import { FieldFormat, KBN_FIELD_TYPES, FIELD_FORMAT_IDS } from '../../../common'; +import { TextContextTypeConvert } from '../../../common/field_formats/types'; export class DateFormat extends FieldFormat { static id = FIELD_FORMAT_IDS.DATE; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 564c571b6ccd6..ee0b0714febc0 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -48,9 +48,7 @@ import { } from './index_patterns'; import { setFieldFormats, - setHttp, setIndexPatterns, - setInjectedMetadata, setNotifications, setOverlays, setQueryService, @@ -164,11 +162,9 @@ export class DataPublicPlugin public start(core: CoreStart, { uiActions }: DataStartDependencies): DataPublicPluginStart { const { uiSettings, http, notifications, savedObjects, overlays, application } = core; - setHttp(http); setNotifications(notifications); setOverlays(overlays); setUiSettings(uiSettings); - setInjectedMetadata(core.injectedMetadata); const fieldFormats = this.fieldFormatsService.start(); setFieldFormats(fieldFormats); diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 7041bcdfa4221..7defddb8f570a 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -34,7 +34,6 @@ import { InjectedIntl } from '@kbn/i18n/react'; import { ISearchSource as ISearchSource_2 } from 'src/plugins/data/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IUiSettingsClient } from 'src/core/public'; -import { IUiSettingsClient as IUiSettingsClient_3 } from 'kibana/public'; import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { KibanaConfigType } from 'src/core/server/kibana_config'; import { Location } from 'history'; @@ -594,10 +593,11 @@ export const fieldFormats: { // @public (undocumented) export type FieldFormatsContentType = 'html' | 'text'; +// Warning: (ae-forgotten-export) The symbol "GetConfigFn" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "FieldFormatsGetConfigFn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +export type FieldFormatsGetConfigFn = GetConfigFn; // Warning: (ae-missing-release-tag) "FieldList" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -727,12 +727,11 @@ export function getEsPreference(uiSettings: IUiSettingsClient_2, sessionId?: str export const getKbnTypeNames: () => string[]; // Warning: (ae-forgotten-export) The symbol "ISearchRequestParams" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "getSearchParamsFromRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - injectedMetadata: CoreStart['injectedMetadata']; - uiSettings: IUiSettingsClient_3; + esShardTimeout: number; + getConfig: GetConfigFn; }): ISearchRequestParams; // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts index aaaac5ae6ff7c..315d4678cabf1 100644 --- a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts +++ b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts @@ -42,7 +42,7 @@ describe('Search Usage Collector', () => { {} as any, ]); mockUsageCollectionSetup = usageCollectionPluginMock.createSetupContract(); - usageCollector = createUsageCollector(mockCoreSetup, mockUsageCollectionSetup); + usageCollector = createUsageCollector(mockCoreSetup.getStartServices, mockUsageCollectionSetup); }); test('tracks query timeouts', async () => { diff --git a/src/plugins/data/public/search/collectors/create_usage_collector.ts b/src/plugins/data/public/search/collectors/create_usage_collector.ts index 7adb0c3caa675..321b2c5b99049 100644 --- a/src/plugins/data/public/search/collectors/create_usage_collector.ts +++ b/src/plugins/data/public/search/collectors/create_usage_collector.ts @@ -18,16 +18,16 @@ */ import { first } from 'rxjs/operators'; -import { CoreSetup } from '../../../../../core/public'; +import { StartServicesAccessor } from '../../../../../core/public'; import { METRIC_TYPE, UsageCollectionSetup } from '../../../../usage_collection/public'; import { SEARCH_EVENT_TYPE, SearchUsageCollector } from './types'; export const createUsageCollector = ( - core: CoreSetup, + getStartServices: StartServicesAccessor, usageCollection?: UsageCollectionSetup ): SearchUsageCollector => { const getCurrentApp = async () => { - const [{ application }] = await core.getStartServices(); + const [{ application }] = await getStartServices(); return application.currentAppId$.pipe(first()).toPromise(); }; diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index f9b62fdd4fc61..1ecb879b1602d 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -18,13 +18,10 @@ */ import { getSearchParams } from './get_search_params'; -import { IUiSettingsClient } from 'kibana/public'; -import { UI_SETTINGS } from '../../../common'; +import { GetConfigFn, UI_SETTINGS } from '../../../common'; -function getConfigStub(config: any = {}) { - return { - get: (key) => config[key], - } as IUiSettingsClient; +function getConfigStub(config: any = {}): GetConfigFn { + return (key) => config[key]; } describe('getSearchParams', () => { diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 3246156b6b37e..5e0395189f647 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -17,37 +17,36 @@ * under the License. */ -import { IUiSettingsClient, CoreStart } from 'kibana/public'; -import { UI_SETTINGS, ISearchRequestParams } from '../../../common'; +import { UI_SETTINGS, ISearchRequestParams, GetConfigFn } from '../../../common'; import { SearchRequest } from './types'; const sessionId = Date.now(); -export function getSearchParams(config: IUiSettingsClient, esShardTimeout: number = 0) { +export function getSearchParams(getConfig: GetConfigFn, esShardTimeout: number = 0) { return { rest_total_hits_as_int: true, ignore_unavailable: true, - ignore_throttled: getIgnoreThrottled(config), - max_concurrent_shard_requests: getMaxConcurrentShardRequests(config), - preference: getPreference(config), + ignore_throttled: getIgnoreThrottled(getConfig), + max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), + preference: getPreference(getConfig), timeout: getTimeout(esShardTimeout), }; } -export function getIgnoreThrottled(config: IUiSettingsClient) { - return !config.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); +export function getIgnoreThrottled(getConfig: GetConfigFn) { + return !getConfig(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); } -export function getMaxConcurrentShardRequests(config: IUiSettingsClient) { - const maxConcurrentShardRequests = config.get(UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS); +export function getMaxConcurrentShardRequests(getConfig: GetConfigFn) { + const maxConcurrentShardRequests = getConfig(UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS); return maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined; } -export function getPreference(config: IUiSettingsClient) { - const setRequestPreference = config.get(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE); +export function getPreference(getConfig: GetConfigFn) { + const setRequestPreference = getConfig(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE); if (setRequestPreference === 'sessionId') return sessionId; return setRequestPreference === 'custom' - ? config.get(UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE) + ? getConfig(UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE) : undefined; } @@ -55,13 +54,15 @@ export function getTimeout(esShardTimeout: number) { return esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined; } +/** @public */ +// TODO: Could provide this on runtime contract with dependencies +// already wired up. export function getSearchParamsFromRequest( searchRequest: SearchRequest, - dependencies: { injectedMetadata: CoreStart['injectedMetadata']; uiSettings: IUiSettingsClient } + dependencies: { esShardTimeout: number; getConfig: GetConfigFn } ): ISearchRequestParams { - const { injectedMetadata, uiSettings } = dependencies; - const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number; - const searchParams = getSearchParams(uiSettings, esShardTimeout); + const { esShardTimeout, getConfig } = dependencies; + const searchParams = getSearchParams(getConfig, esShardTimeout); return { index: searchRequest.index.title || searchRequest.index, diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index dda66d6b5238d..18d277204815b 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IUiSettingsClient } from '../../../../../core/public'; +import { GetConfigFn } from '../../../common'; import { ISearchStartLegacy } from '../types'; export type SearchRequest = any; @@ -30,7 +30,7 @@ export interface FetchOptions { export interface FetchHandlers { legacySearchService: ISearchStartLegacy; - config: IUiSettingsClient; + config: { get: GetConfigFn }; esShardTimeout: number; } diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index 284768bc5a1cc..6ccb0a01cf898 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -42,7 +42,7 @@ function msearch({ index: index.title || index, search_type: searchType, ignore_unavailable: true, - preference: getPreference(config), + preference: getPreference(config.get), }; const inlineBody = { ...body, @@ -52,7 +52,7 @@ function msearch({ }); const searching = es.msearch({ - ...getMSearchParams(config), + ...getMSearchParams(config.get), body: `${inlineRequests.join('\n')}\n`, }); diff --git a/src/plugins/data/public/search/legacy/es_client/get_es_client.ts b/src/plugins/data/public/search/legacy/es_client/get_es_client.ts index 93d9d24920271..4367544ad9ff4 100644 --- a/src/plugins/data/public/search/legacy/es_client/get_es_client.ts +++ b/src/plugins/data/public/search/legacy/es_client/get_es_client.ts @@ -22,17 +22,20 @@ import { default as es } from 'elasticsearch-browser/elasticsearch'; import { CoreStart, PackageInfo } from 'kibana/public'; import { BehaviorSubject } from 'rxjs'; -export function getEsClient( - injectedMetadata: CoreStart['injectedMetadata'], - http: CoreStart['http'], - packageInfo: PackageInfo -) { - const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; - const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; - +export function getEsClient({ + esRequestTimeout, + esApiVersion, + http, + packageVersion, +}: { + esRequestTimeout: number; + esApiVersion: string; + http: CoreStart['http']; + packageVersion: PackageInfo['version']; +}) { // Use legacy es client for msearch. const client = es.Client({ - host: getEsUrl(http, packageInfo), + host: getEsUrl(http, packageVersion), log: 'info', requestTimeout: esRequestTimeout, apiVersion: esApiVersion, @@ -78,7 +81,7 @@ function wrapEsClientMethod(esClient: any, method: string, loadingCount$: Behavi }; } -function getEsUrl(http: CoreStart['http'], packageInfo: PackageInfo) { +function getEsUrl(http: CoreStart['http'], packageVersion: PackageInfo['version']) { const a = document.createElement('a'); a.href = http.basePath.prepend('/elasticsearch'); const protocolPort = /https/.test(a.protocol) ? 443 : 80; @@ -89,7 +92,7 @@ function getEsUrl(http: CoreStart['http'], packageInfo: PackageInfo) { protocol: a.protocol, pathname: a.pathname, headers: { - 'kbn-version': packageInfo.version, + 'kbn-version': packageVersion, }, }; } diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts index 61d3568350b6b..d375398af1add 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts @@ -19,15 +19,12 @@ import { fetchSoon } from './fetch_soon'; import { callClient } from './call_client'; -import { IUiSettingsClient } from 'kibana/public'; import { FetchHandlers, FetchOptions } from '../fetch/types'; import { SearchRequest, SearchResponse } from '../index'; -import { UI_SETTINGS } from '../../../common'; +import { GetConfigFn, UI_SETTINGS } from '../../../common'; -function getConfigStub(config: any = {}) { - return { - get: (key) => config[key], - } as IUiSettingsClient; +function getConfigStub(config: any = {}): GetConfigFn { + return (key) => config[key]; } const mockResponses: Record = { @@ -60,9 +57,9 @@ describe('fetchSoon', () => { }); test('should execute asap if config is set to not batch searches', () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false, - }); + const config = { + get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }), + }; const request = {}; const options = {}; @@ -72,9 +69,9 @@ describe('fetchSoon', () => { }); test('should delay by 50ms if config is set to batch searches', () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - }); + const config = { + get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), + }; const request = {}; const options = {}; @@ -88,9 +85,9 @@ describe('fetchSoon', () => { }); test('should send a batch of requests to callClient', () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - }); + const config = { + get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), + }; const requests = [{ foo: 1 }, { foo: 2 }]; const options = [{ bar: 1 }, { bar: 2 }]; @@ -105,9 +102,9 @@ describe('fetchSoon', () => { }); test('should return the response to the corresponding call for multiple batched requests', async () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - }); + const config = { + get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), + }; const requests = [{ _mockResponseId: 'foo' }, { _mockResponseId: 'bar' }]; const promises = requests.map((request) => { @@ -120,9 +117,9 @@ describe('fetchSoon', () => { }); test('should wait for the previous batch to start before starting a new batch', () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - }); + const config = { + get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), + }; const firstBatch = [{ foo: 1 }, { foo: 2 }]; const secondBatch = [{ bar: 1 }, { bar: 2 }]; diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts index dc61e19406631..d3206950174c8 100644 --- a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts +++ b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts @@ -18,13 +18,10 @@ */ import { getMSearchParams } from './get_msearch_params'; -import { IUiSettingsClient } from '../../../../../core/public'; -import { UI_SETTINGS } from '../../../common'; +import { GetConfigFn, UI_SETTINGS } from '../../../common'; -function getConfigStub(config: any = {}) { - return { - get: (key) => config[key], - } as IUiSettingsClient; +function getConfigStub(config: any = {}): GetConfigFn { + return (key) => config[key]; } describe('getMSearchParams', () => { diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.ts b/src/plugins/data/public/search/legacy/get_msearch_params.ts index 48d13903c972f..c4f77b25078cd 100644 --- a/src/plugins/data/public/search/legacy/get_msearch_params.ts +++ b/src/plugins/data/public/search/legacy/get_msearch_params.ts @@ -17,13 +17,13 @@ * under the License. */ -import { IUiSettingsClient } from 'kibana/public'; +import { GetConfigFn } from '../../../common'; import { getIgnoreThrottled, getMaxConcurrentShardRequests } from '../fetch'; -export function getMSearchParams(config: IUiSettingsClient) { +export function getMSearchParams(getConfig: GetConfigFn) { return { rest_total_hits_as_int: true, - ignore_throttled: getIgnoreThrottled(config), - max_concurrent_shard_requests: getMaxConcurrentShardRequests(config), + ignore_throttled: getIgnoreThrottled(getConfig), + max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), }; } diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 4360a0caa7cde..738f1e8ffbca0 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -52,6 +52,7 @@ describe('Search service', () => { } as any); expect(start).toHaveProperty('aggs'); expect(start).toHaveProperty('search'); + expect(start).toHaveProperty('searchSource'); }); }); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 04e1a46c84652..a65b2b4b71f20 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -51,11 +51,22 @@ export class SearchService implements Plugin { private usageCollector?: SearchUsageCollector; public setup( - core: CoreSetup, - { packageInfo, usageCollection, expressions }: SearchServiceSetupDependencies + { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, + { expressions, packageInfo, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { - this.usageCollector = createUsageCollector(core, usageCollection); - this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo); + const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; + const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; + const packageVersion = packageInfo.version; + + this.usageCollector = createUsageCollector(getStartServices, usageCollection); + + this.esClient = getEsClient({ + esRequestTimeout, + esApiVersion, + http, + packageVersion, + }); + /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -64,13 +75,13 @@ export class SearchService implements Plugin { */ this.searchInterceptor = new SearchInterceptor( { - toasts: core.notifications.toasts, - http: core.http, - uiSettings: core.uiSettings, - startServices: core.getStartServices(), + toasts: notifications.toasts, + http, + uiSettings, + startServices: getStartServices(), usageCollector: this.usageCollector!, }, - core.injectedMetadata.getInjectedVar('esRequestTimeout') as number + esRequestTimeout ); expressions.registerFunction(esdsl); @@ -79,7 +90,7 @@ export class SearchService implements Plugin { return { aggs: this.aggsService.setup({ registerFunction: expressions.registerFunction, - uiSettings: core.uiSettings, + uiSettings, }), usageCollector: this.usageCollector!, __enhance: (enhancements: SearchEnhancements) => { @@ -101,8 +112,8 @@ export class SearchService implements Plugin { }; const searchSourceDependencies: SearchSourceDependencies = { - uiSettings, - injectedMetadata, + getConfig: uiSettings.get.bind(uiSettings), + esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, legacySearch, }; diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index 23ab5979595af..56f6ca6c56270 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -16,27 +16,28 @@ * specific language governing permissions and limitations * under the License. */ + import { createSearchSource as createSearchSourceFactory } from './create_search_source'; +import { SearchSourceDependencies } from './search_source'; import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; -import { coreMock } from '../../../../../core/public/mocks'; import { dataPluginMock } from '../../mocks'; describe('createSearchSource', () => { const indexPatternMock: IIndexPattern = {} as IIndexPattern; let indexPatternContractMock: jest.Mocked; - let dependencies: any; + let dependencies: SearchSourceDependencies; let createSearchSource: ReturnType; beforeEach(() => { - const core = coreMock.createStart(); const data = dataPluginMock.createStartContract(); dependencies = { - searchService: data.search, - uiSettings: core.uiSettings, - injectedMetadata: core.injectedMetadata, + getConfig: jest.fn(), + search: jest.fn(), + legacySearch: data.search.__LEGACY, + esShardTimeout: 30000, }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index cf2d009e41b54..4e1c35557ffa6 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,10 +17,7 @@ * under the License. */ -import { - injectedMetadataServiceMock, - uiSettingsServiceMock, -} from '../../../../../core/public/mocks'; +import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; import { SearchSourceFields } from './types'; @@ -54,6 +51,8 @@ export const searchSourceMock = { export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { + getConfig: uiSettingsServiceMock.createStartContract().get, + esShardTimeout: 30000, search: jest.fn(), legacySearch: { esClient: { @@ -61,6 +60,4 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => msearch: jest.fn(), }, }, - uiSettings: uiSettingsServiceMock.createStartContract(), - injectedMetadata: injectedMetadataServiceMock.createStartContract(), }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index 6d53b8dfc4b4e..2f0fa0765e25a 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + import { Observable } from 'rxjs'; -import { SearchSource } from './search_source'; +import { GetConfigFn } from 'src/plugins/data/common'; +import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; import { fetchSoon } from '../legacy'; -import { IUiSettingsClient } from '../../../../../core/public'; import { dataPluginMock } from '../../../../data/public/mocks'; -import { coreMock } from '../../../../../core/public/mocks'; jest.mock('../legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), @@ -51,10 +51,9 @@ const indexPattern2 = ({ describe('SearchSource', () => { let mockSearchMethod: any; - let searchSourceDependencies: any; + let searchSourceDependencies: SearchSourceDependencies; beforeEach(() => { - const core = coreMock.createStart(); const data = dataPluginMock.createStartContract(); mockSearchMethod = jest.fn(() => { @@ -69,10 +68,10 @@ describe('SearchSource', () => { }); searchSourceDependencies = { + getConfig: jest.fn(), search: mockSearchMethod, legacySearch: data.search.__LEGACY, - injectedMetadata: core.injectedMetadata, - uiSettings: core.uiSettings, + esShardTimeout: 30000, }; }); @@ -184,16 +183,11 @@ describe('SearchSource', () => { describe('#legacy fetch()', () => { beforeEach(() => { - const core = coreMock.createStart(); - searchSourceDependencies = { ...searchSourceDependencies, - uiSettings: { - ...core.uiSettings, - get: jest.fn(() => { - return true; // batchSearches = true - }), - } as IUiSettingsClient, + getConfig: jest.fn(() => { + return true; // batchSearches = true + }) as GetConfigFn, }; }); diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index 847dc8853d6ba..06ad13bfcfdf5 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -72,7 +72,6 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; -import { CoreStart } from 'kibana/public'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; @@ -82,15 +81,32 @@ import { FetchOptions, RequestFailure, handleResponse, getSearchParamsFromReques import { getEsQueryConfig, buildEsQuery, Filter, UI_SETTINGS } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; +import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; import { ISearchStartLegacy } from '../types'; +/** @internal */ +export const searchSourceRequiredUiSettings = [ + 'dateFormat:tz', + UI_SETTINGS.COURIER_BATCH_SEARCHES, + UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE, + UI_SETTINGS.COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX, + UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS, + UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE, + UI_SETTINGS.DOC_HIGHLIGHT, + UI_SETTINGS.META_FIELDS, + UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS, + UI_SETTINGS.QUERY_STRING_OPTIONS, + UI_SETTINGS.SEARCH_INCLUDE_FROZEN, + UI_SETTINGS.SORT_OPTIONS, +]; + export interface SearchSourceDependencies { - uiSettings: CoreStart['uiSettings']; + getConfig: GetConfigFn; search: ISearchGeneric; legacySearch: ISearchStartLegacy; - injectedMetadata: CoreStart['injectedMetadata']; + esShardTimeout: number; } /** @public **/ @@ -204,11 +220,11 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, signal?: AbortSignal) { - const { search, injectedMetadata, uiSettings } = this.dependencies; + const { search, esShardTimeout, getConfig } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { - injectedMetadata, - uiSettings, + esShardTimeout, + getConfig, }); return search({ params, indexType: searchRequest.indexType }, { signal }).pipe( @@ -221,8 +237,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) { - const { injectedMetadata, legacySearch, uiSettings } = this.dependencies; - const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number; + const { esShardTimeout, legacySearch, getConfig } = this.dependencies; return await fetchSoon( searchRequest, @@ -232,7 +247,7 @@ export class SearchSource { }, { legacySearchService: legacySearch, - config: uiSettings, + config: { get: getConfig }, esShardTimeout, } ); @@ -243,14 +258,14 @@ export class SearchSource { * @async */ async fetch(options: FetchOptions = {}) { - const { uiSettings } = this.dependencies; + const { getConfig } = this.dependencies; await this.requestIsStarting(options); const searchRequest = await this.flatten(); this.history = [searchRequest]; let response; - if (uiSettings.get(UI_SETTINGS.COURIER_BATCH_SEARCHES)) { + if (getConfig(UI_SETTINGS.COURIER_BATCH_SEARCHES)) { response = await this.legacyFetch(searchRequest, options); } else { response = this.fetch$(searchRequest, options.abortSignal).toPromise(); @@ -342,7 +357,7 @@ export class SearchSource { } }; - const { uiSettings } = this.dependencies; + const { getConfig } = this.dependencies; switch (key) { case 'filter': @@ -364,7 +379,7 @@ export class SearchSource { const sort = normalizeSortRequest( val, this.getField('index'), - uiSettings.get(UI_SETTINGS.SORT_OPTIONS) + getConfig(UI_SETTINGS.SORT_OPTIONS) ); return addToBody(key, sort); default: @@ -418,14 +433,11 @@ export class SearchSource { body._source = index.getSourceFiltering(); } - const { uiSettings } = this.dependencies; + const { getConfig } = this.dependencies; if (body._source) { // exclude source fields for this index pattern specified by the user - const filter = fieldWildcardFilter( - body._source.excludes, - uiSettings.get(UI_SETTINGS.META_FIELDS) - ); + const filter = fieldWildcardFilter(body._source.excludes, getConfig(UI_SETTINGS.META_FIELDS)); body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) => filter(docvalueField.field) ); @@ -445,11 +457,11 @@ export class SearchSource { ); } - const esQueryConfigs = getEsQueryConfig(uiSettings); + const esQueryConfigs = getEsQueryConfig({ get: getConfig }); body.query = buildEsQuery(index, query, filters, esQueryConfigs); if (highlightAll && body.query) { - body.highlight = getHighlightRequest(body.query, uiSettings.get(UI_SETTINGS.DOC_HIGHLIGHT)); + body.highlight = getHighlightRequest(body.query, getConfig(UI_SETTINGS.DOC_HIGHLIGHT)); delete searchRequest.highlightAll; } diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index ba0b2de393bde..032bce6d8d2aa 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -31,8 +31,6 @@ export const [getUiSettings, setUiSettings] = createGetterSetter('Http'); - export const [getFieldFormats, setFieldFormats] = createGetterSetter( 'FieldFormats' ); @@ -47,10 +45,6 @@ export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] >('Query'); -export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< - CoreStart['injectedMetadata'] ->('InjectedMetadata'); - export const [getSearchService, setSearchService] = createGetterSetter< DataPublicPluginStart['search'] >('Search'); diff --git a/src/plugins/data/server/field_formats/converters/date_nanos_server.ts b/src/plugins/data/server/field_formats/converters/date_nanos_server.ts index 299b2aac93d49..b99febf0c7e73 100644 --- a/src/plugins/data/server/field_formats/converters/date_nanos_server.ts +++ b/src/plugins/data/server/field_formats/converters/date_nanos_server.ts @@ -24,7 +24,7 @@ import { DateNanosFormat, formatWithNanos, } from '../../../common/field_formats/converters/date_nanos_shared'; -import { TextContextTypeConvert } from '../../../common'; +import { TextContextTypeConvert } from '../../../common/field_formats/types'; class DateNanosFormatServer extends DateNanosFormat { textConvert: TextContextTypeConvert = (val) => { diff --git a/src/plugins/data/server/field_formats/converters/date_server.ts b/src/plugins/data/server/field_formats/converters/date_server.ts index 85eb65dfc6a8d..19c4adc90bade 100644 --- a/src/plugins/data/server/field_formats/converters/date_server.ts +++ b/src/plugins/data/server/field_formats/converters/date_server.ts @@ -23,11 +23,13 @@ import moment from 'moment-timezone'; import { FieldFormat, KBN_FIELD_TYPES, - TextContextTypeConvert, FIELD_FORMAT_IDS, FieldFormatsGetConfigFn, - IFieldFormatMetaParams, } from '../../../common'; +import { + IFieldFormatMetaParams, + TextContextTypeConvert, +} from '../../../common/field_formats/types'; export class DateFormat extends FieldFormat { static id = FIELD_FORMAT_IDS.DATE; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index e259a7878398d..f0a0d2763ff23 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -419,10 +419,11 @@ export const fieldFormats: { TruncateFormat: typeof TruncateFormat; }; +// Warning: (ae-forgotten-export) The symbol "GetConfigFn" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "FieldFormatsGetConfigFn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type FieldFormatsGetConfigFn = (key: string, defaultOverride?: T) => T; +export type FieldFormatsGetConfigFn = GetConfigFn; // Warning: (ae-missing-release-tag) "Filter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/src/plugins/discover/public/application/angular/directives/render_complete.ts b/src/plugins/discover/public/application/angular/directives/render_complete.ts index 635cf68f12fcb..72f97138790b2 100644 --- a/src/plugins/discover/public/application/angular/directives/render_complete.ts +++ b/src/plugins/discover/public/application/angular/directives/render_complete.ts @@ -17,14 +17,14 @@ * under the License. */ import { IScope } from 'angular'; -import { RenderCompleteHelper } from '../../../../../kibana_utils/public'; +import { RenderCompleteListener } from '../../../../../kibana_utils/public'; export function createRenderCompleteDirective() { return { controller($scope: IScope, $element: JQLite) { const el = $element[0]; - const renderCompleteHelper = new RenderCompleteHelper(el); - $scope.$on('$destroy', renderCompleteHelper.destroy); + const renderCompleteListener = new RenderCompleteListener(el); + $scope.$on('$destroy', renderCompleteListener.destroy); }, }; } diff --git a/src/plugins/embeddable/kibana.json b/src/plugins/embeddable/kibana.json index c9694ad7b9423..6a8e6079232aa 100644 --- a/src/plugins/embeddable/kibana.json +++ b/src/plugins/embeddable/kibana.json @@ -12,6 +12,7 @@ ], "requiredBundles": [ "savedObjects", - "kibanaReact" + "kibanaReact", + "kibanaUtils" ] } diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index fcecf117d7d52..ffe8a5bf6e7dc 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -19,6 +19,8 @@ import { cloneDeep, isEqual } from 'lodash'; import * as Rx from 'rxjs'; +import { distinctUntilChanged, map } from 'rxjs/operators'; +import { RenderCompleteDispatcher } from '../../../../kibana_utils/public'; import { Adapters, ViewMode } from '../types'; import { IContainer } from '../containers'; import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable'; @@ -47,6 +49,8 @@ export abstract class Embeddable< private readonly input$: Rx.BehaviorSubject; private readonly output$: Rx.BehaviorSubject; + protected renderComplete = new RenderCompleteDispatcher(); + // Listener to parent changes, if this embeddable exists in a parent, in order // to update input when the parent changes. private parentSubscription?: Rx.Subscription; @@ -77,6 +81,15 @@ export abstract class Embeddable< this.onResetInput(newInput); }); } + + this.getOutput$() + .pipe( + map(({ title }) => title || ''), + distinctUntilChanged() + ) + .subscribe((title) => { + this.renderComplete.setTitle(title); + }); } public getIsContainer(): this is IContainer { @@ -105,8 +118,8 @@ export abstract class Embeddable< return this.input; } - public getTitle() { - return this.output.title; + public getTitle(): string { + return this.output.title || ''; } /** @@ -133,7 +146,10 @@ export abstract class Embeddable< } } - public render(domNode: HTMLElement | Element): void { + public render(el: HTMLElement): void { + this.renderComplete.setEl(el); + this.renderComplete.setTitle(this.output.title || ''); + if (this.destroyed) { throw new Error('Embeddable has been destroyed'); } diff --git a/src/plugins/kibana_utils/public/render_complete/index.ts b/src/plugins/kibana_utils/public/render_complete/index.ts index ec86144f65a35..8f14b6ca8f0ab 100644 --- a/src/plugins/kibana_utils/public/render_complete/index.ts +++ b/src/plugins/kibana_utils/public/render_complete/index.ts @@ -17,19 +17,5 @@ * under the License. */ -const dispatchCustomEvent = (el: HTMLElement, eventName: string) => { - // we're using the native events so that we aren't tied to the jQuery custom events, - // otherwise we have to use jQuery(element).on(...) because jQuery's events sit on top - // of the native events per https://github.com/jquery/jquery/issues/2476 - el.dispatchEvent(new CustomEvent(eventName, { bubbles: true })); -}; - -export function dispatchRenderComplete(el: HTMLElement) { - dispatchCustomEvent(el, 'renderComplete'); -} - -export function dispatchRenderStart(el: HTMLElement) { - dispatchCustomEvent(el, 'renderStart'); -} - -export * from './render_complete_helper'; +export * from './render_complete_listener'; +export * from './render_complete_dispatcher'; diff --git a/src/plugins/kibana_utils/public/render_complete/render_complete_dispatcher.ts b/src/plugins/kibana_utils/public/render_complete/render_complete_dispatcher.ts new file mode 100644 index 0000000000000..386bf1eb62568 --- /dev/null +++ b/src/plugins/kibana_utils/public/render_complete/render_complete_dispatcher.ts @@ -0,0 +1,83 @@ +/* + * 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. + */ + +const dispatchEvent = (el: HTMLElement, eventName: string) => { + el.dispatchEvent(new CustomEvent(eventName, { bubbles: true })); +}; + +export function dispatchRenderComplete(el: HTMLElement) { + dispatchEvent(el, 'renderComplete'); +} + +export function dispatchRenderStart(el: HTMLElement) { + dispatchEvent(el, 'renderStart'); +} + +/** + * Should call `dispatchComplete()` when UI block has finished loading its data and has + * completely rendered. Should `dispatchInProgress()` every time UI block + * starts loading data again. At the start it is assumed that UI block is loading + * so it dispatches "in progress" automatically, so you need to call `setRenderComplete` + * at least once. + * + * This is used for reporting to know that UI block is ready, so + * it can take a screenshot. It is also used in functional tests to know that + * page has stabilized. + */ +export class RenderCompleteDispatcher { + private count: number = 0; + private el?: HTMLElement; + + constructor(el?: HTMLElement) { + this.setEl(el); + } + + public setEl(el?: HTMLElement) { + this.el = el; + this.count = 0; + if (el) this.dispatchInProgress(); + } + + public dispatchInProgress() { + if (!this.el) return; + this.el.setAttribute('data-render-complete', 'false'); + this.el.setAttribute('data-rendering-count', String(this.count)); + dispatchRenderStart(this.el); + } + + public dispatchComplete() { + if (!this.el) return; + this.count++; + this.el.setAttribute('data-render-complete', 'true'); + this.el.setAttribute('data-rendering-count', String(this.count)); + dispatchRenderComplete(this.el); + } + + public dispatchError() { + if (!this.el) return; + this.count++; + this.el.setAttribute('data-render-complete', 'false'); + this.el.setAttribute('data-rendering-count', String(this.count)); + } + + public setTitle(title: string) { + if (!this.el) return; + this.el.setAttribute('data-title', title); + } +} diff --git a/src/plugins/kibana_utils/public/render_complete/render_complete_helper.ts b/src/plugins/kibana_utils/public/render_complete/render_complete_listener.ts similarity index 80% rename from src/plugins/kibana_utils/public/render_complete/render_complete_helper.ts rename to src/plugins/kibana_utils/public/render_complete/render_complete_listener.ts index 1230638a1d709..d9289b20d4bfa 100644 --- a/src/plugins/kibana_utils/public/render_complete/render_complete_helper.ts +++ b/src/plugins/kibana_utils/public/render_complete/render_complete_listener.ts @@ -17,9 +17,9 @@ * under the License. */ -const attributeName = 'data-render-complete'; +export class RenderCompleteListener { + private readonly attributeName = 'data-render-complete'; -export class RenderCompleteHelper { constructor(private readonly element: HTMLElement) { this.setup(); } @@ -30,23 +30,23 @@ export class RenderCompleteHelper { }; public setup = () => { - this.element.setAttribute(attributeName, 'false'); + this.element.setAttribute(this.attributeName, 'false'); this.element.addEventListener('renderStart', this.start); this.element.addEventListener('renderComplete', this.complete); }; public disable = () => { - this.element.setAttribute(attributeName, 'disabled'); + this.element.setAttribute(this.attributeName, 'disabled'); this.destroy(); }; private start = () => { - this.element.setAttribute(attributeName, 'false'); + this.element.setAttribute(this.attributeName, 'false'); return true; }; private complete = () => { - this.element.setAttribute(attributeName, 'true'); + this.element.setAttribute(this.attributeName, 'true'); return true; }; } diff --git a/src/plugins/vis_type_vega/public/data_model/search_api.ts b/src/plugins/vis_type_vega/public/data_model/search_api.ts index a213b59be2ad0..d2ce8c95b9f90 100644 --- a/src/plugins/vis_type_vega/public/data_model/search_api.ts +++ b/src/plugins/vis_type_vega/public/data_model/search_api.ts @@ -51,8 +51,10 @@ export class SearchAPI { searchRequests.map((request) => { const requestId = request.name; const params = getSearchParamsFromRequest(request, { - uiSettings: this.dependencies.uiSettings, - injectedMetadata: this.dependencies.injectedMetadata, + esShardTimeout: this.dependencies.injectedMetadata.getInjectedVar( + 'esShardTimeout' + ) as number, + getConfig: this.dependencies.uiSettings.get.bind(this.dependencies.uiSettings), }); if (this.inspectorAdapters) { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index c4d5f5206ee90..a434bf9756b64 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -36,7 +36,6 @@ import { IContainer, Adapters, } from '../../../../plugins/embeddable/public'; -import { dispatchRenderComplete } from '../../../../plugins/kibana_utils/public'; import { IExpressionLoaderParams, ExpressionsStart, @@ -85,7 +84,6 @@ export class VisualizeEmbeddable extends Embeddable; private subscriptions: Subscription[] = []; @@ -158,7 +156,7 @@ export class VisualizeEmbeddable extends Embeddable Boolean(this.getInspectorAdapters()); onContainerLoading = () => { - this.domNode.setAttribute('data-render-complete', 'false'); + this.renderComplete.dispatchInProgress(); this.updateOutput({ loading: true, error: undefined }); }; - onContainerRender = (count: number) => { - this.domNode.setAttribute('data-render-complete', 'true'); - this.domNode.setAttribute('data-rendering-count', count.toString()); + onContainerRender = () => { + this.renderComplete.dispatchComplete(); this.updateOutput({ loading: false, error: undefined }); - dispatchRenderComplete(this.domNode); }; onContainerError = (error: ExpressionRenderError) => { if (this.abortController) { this.abortController.abort(); } - this.domNode.setAttribute( - 'data-rendering-count', - this.domNode.getAttribute('data-rendering-count') + 1 - ); - this.domNode.setAttribute('data-render-complete', 'false'); + this.renderComplete.dispatchError(); this.updateOutput({ loading: false, error }); }; @@ -274,7 +256,6 @@ export class VisualizeEmbeddable extends Embeddable { - return { - SPATIAL_FILTER_TYPE: 'spatial_filter', - }; -}); - import { hitsToGeoJson, geoPointToGeometry, @@ -22,7 +14,7 @@ import { makeESBbox, scaleBounds, } from './elasticsearch_geo_utils'; -import { indexPatterns } from '../../../../src/plugins/data/public'; +import _ from 'lodash'; const geoFieldName = 'location'; @@ -173,19 +165,14 @@ describe('hitsToGeoJson', () => { }); describe('dot in geoFieldName', () => { - const indexPatternMock = { - fields: { - getByName: (name) => { - const fields = { - ['my.location']: { - type: 'geo_point', - }, - }; - return fields[name]; - }, - }, + // This essentially should test the implmentation of index-pattern.flattenHit, rather than anything in geo_utils. + // Leaving this here for reference. + const geoFieldName = 'my.location'; + const indexPatternFlattenHit = (hit) => { + return { + [geoFieldName]: _.get(hit._source, geoFieldName), + }; }; - const indexPatternFlattenHit = indexPatterns.flattenHitWrapper(indexPatternMock); it('Should handle geoField being an object', () => { const hits = [ diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index a22e8d582bc5e..6f5ed680ac64f 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -41,7 +41,7 @@ import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; -import { scaleBounds, turfBboxToBounds } from '../elasticsearch_geo_utils'; +import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_geo_utils'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts index 7ba58307e1952..f408896853155 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.ts @@ -54,7 +54,7 @@ import { MapRefreshConfig, } from '../../common/descriptor_types'; import { INITIAL_LOCATION } from '../../common/constants'; -import { scaleBounds } from '../elasticsearch_geo_utils'; +import { scaleBounds } from '../../common/elasticsearch_geo_utils'; export function setMapInitError(errorMessage: string) { return { diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js index a95a8be4b24c8..35dbebdfd3c8a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js @@ -8,7 +8,7 @@ import _ from 'lodash'; import { RENDER_AS } from '../../../../common/constants'; import { getTileBoundingBox } from './geo_tile_utils'; import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; -import { clamp } from '../../../elasticsearch_geo_utils'; +import { clamp } from '../../../../common/elasticsearch_geo_utils'; const GRID_BUCKET_KEYS_TO_IGNORE = ['key', 'gridCentroid']; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index a4dba71307b71..a6322ff3ba784 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -21,7 +21,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { DataRequestAbortError } from '../../util/data_request'; import { registerSource } from '../source_registry'; -import { makeESBbox } from '../../../elasticsearch_geo_utils'; +import { makeESBbox } from '../../../../common/elasticsearch_geo_utils'; export const MAX_GEOTILE_LEVEL = 29; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js index 251e33b9579cb..89b24522e4275 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js @@ -6,7 +6,7 @@ import _ from 'lodash'; import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants'; -import { clampToLatBounds } from '../../../elasticsearch_geo_utils'; +import { clampToLatBounds } from '../../../../common/elasticsearch_geo_utils'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js index 79eccf09b2888..92b0c717f6724 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js @@ -16,7 +16,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { registerSource } from '../source_registry'; -import { turfBboxToBounds } from '../../../elasticsearch_geo_utils'; +import { turfBboxToBounds } from '../../../../common/elasticsearch_geo_utils'; import { DataRequestAbortError } from '../../util/data_request'; const MAX_GEOTILE_LEVEL = 29; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js index 256becf70ffb0..6d61c4a7455b2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js @@ -9,7 +9,7 @@ import React from 'react'; import { AbstractESSource } from '../es_source'; import { getSearchService } from '../../../kibana_services'; -import { hitsToGeoJson } from '../../../elasticsearch_geo_utils'; +import { hitsToGeoJson } from '../../../../common/elasticsearch_geo_utils'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index 866e3c76c2a3f..8cc2aa018979b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -11,7 +11,7 @@ import { getTimeFilter, getSearchService, } from '../../../kibana_services'; -import { createExtentFilter } from '../../../elasticsearch_geo_utils'; +import { createExtentFilter } from '../../../../common/elasticsearch_geo_utils'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js index e1779c1afbf47..b0ce52b4db7ab 100644 --- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js +++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js @@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { URL_MAX_LENGTH } from '../../../../../../../src/core/public'; -import { createSpatialFilterWithGeometry } from '../../../elasticsearch_geo_utils'; +import { createSpatialFilterWithGeometry } from '../../../../common/elasticsearch_geo_utils'; import { GEO_JSON_TYPE } from '../../../../common/constants'; import { GeometryFilterForm } from '../../../components/geometry_filter_form'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js index 2daa4b2c900f5..6de936fa4a8f1 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js @@ -15,7 +15,7 @@ import { createSpatialFilterWithGeometry, getBoundingBoxGeometry, roundCoordinates, -} from '../../../../elasticsearch_geo_utils'; +} from '../../../../../common/elasticsearch_geo_utils'; import { DrawTooltip } from './draw_tooltip'; const DRAW_RECTANGLE = 'draw_rectangle'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js index d85959c3a08a4..5a38f6039ae4b 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js @@ -19,7 +19,7 @@ import sprites1 from '@elastic/maki/dist/sprite@1.png'; import sprites2 from '@elastic/maki/dist/sprite@2.png'; import { DrawControl } from './draw_control'; import { TooltipControl } from './tooltip_control'; -import { clampToLatBounds, clampToLonBounds } from '../../../elasticsearch_geo_utils'; +import { clampToLatBounds, clampToLonBounds } from '../../../../common/elasticsearch_geo_utils'; import { getInitialView } from './get_initial_view'; import { getPreserveDrawingBuffer } from '../../../kibana_services'; diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index f8f89ebaed102..239a2898a06fc 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -5,14 +5,11 @@ */ import _ from 'lodash'; -import { esFilters } from '../../../../src/plugins/data/public'; import { MapsLegacyConfigType } from '../../../../src/plugins/maps_legacy/public'; import { MapsConfigType } from '../config'; import { MapsPluginStartDependencies } from './plugin'; import { CoreStart } from '../../../../src/core/public'; -export const SPATIAL_FILTER_TYPE = esFilters.FILTERS.SPATIAL_FILTER; - let licenseId: string | undefined; export const setLicenseId = (latestLicenseId: string | undefined) => (licenseId = latestLicenseId); export const getLicenseId = () => licenseId; diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 40ffda3f31c26..d48ee24027561 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -32,7 +32,7 @@ import { SPATIAL_FILTERS_LAYER_ID, } from '../../common/constants'; // @ts-ignore -import { extractFeaturesFromFilters } from '../elasticsearch_geo_utils'; +import { extractFeaturesFromFilters } from '../../common/elasticsearch_geo_utils'; import { MapStoreState } from '../reducers/store'; import { DataRequestDescriptor, diff --git a/x-pack/plugins/monitoring/server/license_service.ts b/x-pack/plugins/monitoring/server/license_service.ts index fb45abc22afa4..ecadf9d2d85db 100644 --- a/x-pack/plugins/monitoring/server/license_service.ts +++ b/x-pack/plugins/monitoring/server/license_service.ts @@ -33,14 +33,13 @@ export class LicenseService { let rawLicense: Readonly | undefined; let licenseSubscription: Subscription | undefined = license$.subscribe((nextRawLicense) => { rawLicense = nextRawLicense; + if (!rawLicense?.isAvailable) { + log.warn( + `X-Pack Monitoring Cluster Alerts will not be available: ${rawLicense?.getUnavailableReason()}` + ); + } }); - if (!rawLicense?.isAvailable) { - log.warn( - `X-Pack Monitoring Cluster Alerts will not be available: ${rawLicense?.getUnavailableReason()}` - ); - } - return { refresh, license$, diff --git a/x-pack/plugins/monitoring/server/plugin.test.ts b/x-pack/plugins/monitoring/server/plugin.test.ts new file mode 100644 index 0000000000000..13da0a3c9242e --- /dev/null +++ b/x-pack/plugins/monitoring/server/plugin.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Plugin } from './plugin'; +import { combineLatest } from 'rxjs'; +// @ts-ignore +import { initBulkUploader } from './kibana_monitoring'; +import { AlertsFactory } from './alerts'; + +jest.mock('rxjs', () => ({ + // @ts-ignore + ...jest.requireActual('rxjs'), + combineLatest: jest.fn(), +})); + +jest.mock('./es_client/instantiate_client', () => ({ + instantiateClient: jest.fn(), +})); + +jest.mock('./license_service', () => ({ + LicenseService: jest.fn().mockImplementation(() => ({ + setup: jest.fn().mockImplementation(() => ({ + refresh: jest.fn(), + })), + })), +})); + +jest.mock('./kibana_monitoring', () => ({ + initBulkUploader: jest.fn(), +})); + +describe('Monitoring plugin', () => { + const initializerContext = { + logger: { + get: jest.fn().mockImplementation(() => ({ + info: jest.fn(), + })), + }, + config: { + create: jest.fn().mockImplementation(() => ({ + pipe: jest.fn().mockImplementation(() => ({ + toPromise: jest.fn(), + })), + })), + legacy: { + globalConfig$: {}, + }, + }, + env: { + packageInfo: { + version: '1.0.0', + }, + }, + }; + + const coreSetup = { + http: { + createRouter: jest.fn(), + getServerInfo: jest.fn().mockImplementation(() => ({ + port: 5601, + })), + basePath: { + serverBasePath: '', + }, + }, + uuid: { + getInstanceUuid: jest.fn(), + }, + elasticsearch: { + legacy: { + client: {}, + createClient: jest.fn(), + }, + }, + }; + + const setupPlugins = { + usageCollection: { + getCollectorByType: jest.fn(), + makeStatsCollector: jest.fn(), + registerCollector: jest.fn(), + }, + alerts: { + registerType: jest.fn(), + }, + }; + + let config = {}; + const defaultConfig = { + ui: { + elasticsearch: {}, + }, + kibana: { + collection: { + interval: 30000, + }, + }, + }; + + beforeEach(() => { + config = defaultConfig; + (combineLatest as jest.Mock).mockImplementation(() => { + return { + pipe: jest.fn().mockImplementation(() => { + return { + toPromise: jest.fn().mockImplementation(() => { + return [config, 2]; + }), + }; + }), + }; + }); + }); + + afterEach(() => { + (setupPlugins.alerts.registerType as jest.Mock).mockReset(); + }); + + it('always create the bulk uploader', async () => { + const setKibanaStatusGetter = jest.fn(); + (initBulkUploader as jest.Mock).mockImplementation(() => { + return { + setKibanaStatusGetter, + }; + }); + const plugin = new Plugin(initializerContext as any); + const contract = await plugin.setup(coreSetup as any, setupPlugins as any); + contract.registerLegacyAPI(null as any); + expect(setKibanaStatusGetter).toHaveBeenCalled(); + }); + + it('should register all alerts', async () => { + const alerts = AlertsFactory.getAll(); + const plugin = new Plugin(initializerContext as any); + await plugin.setup(coreSetup as any, setupPlugins as any); + expect(setupPlugins.alerts.registerType).toHaveBeenCalledTimes(alerts.length); + }); +}); diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 3aedb6831e7ab..043435c48a211 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -71,7 +71,7 @@ export class Plugin { private licenseService = {} as MonitoringLicenseService; private monitoringCore = {} as MonitoringCore; private legacyShimDependencies = {} as LegacyShimDependencies; - private bulkUploader = {} as IBulkUploader; + private bulkUploader: IBulkUploader = {} as IBulkUploader; constructor(initializerContext: PluginInitializerContext) { this.initializerContext = initializerContext; @@ -152,28 +152,28 @@ export class Plugin { registerCollectors(plugins.usageCollection, config); } - // If collection is enabled, create the bulk uploader + // Always create the bulk uploader const kibanaMonitoringLog = this.getLogger(KIBANA_MONITORING_LOGGING_TAG); + const bulkUploader = (this.bulkUploader = initBulkUploader({ + elasticsearch: core.elasticsearch, + config, + log: kibanaMonitoringLog, + kibanaStats: { + uuid: core.uuid.getInstanceUuid(), + name: serverInfo.name, + index: get(legacyConfig, 'kibana.index'), + host: serverInfo.hostname, + locale: i18n.getLocale(), + port: serverInfo.port.toString(), + transport_address: `${serverInfo.hostname}:${serverInfo.port}`, + version: this.initializerContext.env.packageInfo.version, + snapshot: snapshotRegex.test(this.initializerContext.env.packageInfo.version), + }, + })); + + // If collection is enabled, start it const kibanaCollectionEnabled = config.kibana.collection.enabled; if (kibanaCollectionEnabled) { - // Start kibana internal collection - const bulkUploader = (this.bulkUploader = initBulkUploader({ - elasticsearch: core.elasticsearch, - config, - log: kibanaMonitoringLog, - kibanaStats: { - uuid: core.uuid.getInstanceUuid(), - name: serverInfo.name, - index: get(legacyConfig, 'kibana.index'), - host: serverInfo.hostname, - locale: i18n.getLocale(), - port: serverInfo.port.toString(), - transport_address: `${serverInfo.hostname}:${serverInfo.port}`, - version: this.initializerContext.env.packageInfo.version, - snapshot: snapshotRegex.test(this.initializerContext.env.packageInfo.version), - }, - })); - // Do not use `this.licenseService` as that looks at the monitoring cluster // whereas we want to check the production cluster here if (plugins.licensing) { @@ -188,6 +188,10 @@ export class Plugin { bulkUploader.handleNotEnabled(); } }); + } else { + kibanaMonitoringLog.warn( + 'Internal collection for Kibana monitoring is disabled due to missing license information.' + ); } } else { kibanaMonitoringLog.info( diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts index 1cf879adc5415..ca191602dcf44 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts @@ -135,26 +135,36 @@ const expectPrivilegeCheck = async (fn: Function, args: Record) => ); }; -const expectObjectNamespaceFiltering = async (fn: Function, args: Record) => { - clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( - getMockCheckPrivilegesSuccess // privilege check for authorization - ); +const expectObjectNamespaceFiltering = async ( + fn: Function, + args: Record, + privilegeChecks = 1 +) => { + for (let i = 0; i < privilegeChecks; i++) { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( + getMockCheckPrivilegesSuccess // privilege check for authorization + ); + } clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( getMockCheckPrivilegesFailure // privilege check for namespace filtering ); - const authorizedNamespace = args.options.namespace || 'default'; + const authorizedNamespace = args.options?.namespace || 'default'; const namespaces = ['some-other-namespace', authorizedNamespace]; const returnValue = { namespaces, foo: 'bar' }; // we don't know which base client method will be called; mock them all clientOpts.baseClient.create.mockReturnValue(returnValue as any); clientOpts.baseClient.get.mockReturnValue(returnValue as any); clientOpts.baseClient.update.mockReturnValue(returnValue as any); + clientOpts.baseClient.addToNamespaces.mockReturnValue(returnValue as any); + clientOpts.baseClient.deleteFromNamespaces.mockReturnValue(returnValue as any); const result = await fn.bind(client)(...Object.values(args)); expect(result).toEqual(expect.objectContaining({ namespaces: [authorizedNamespace, '?'] })); - expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(2); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes( + privilegeChecks + 1 + ); expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenLastCalledWith( 'login:', namespaces @@ -369,6 +379,11 @@ describe('#addToNamespaces', () => { undefined // default namespace ); }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + // this operation is unique because it requires two privilege checks before it executes + await expectObjectNamespaceFiltering(client.addToNamespaces, { type, id, namespaces }, 2); + }); }); describe('#bulkCreate', () => { @@ -682,6 +697,10 @@ describe('#deleteFromNamespaces', () => { namespaces ); }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + await expectObjectNamespaceFiltering(client.deleteFromNamespaces, { type, id, namespaces }); + }); }); describe('#update', () => { diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts index 621299a0f025e..9fd8a732c4eab 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts @@ -164,7 +164,8 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra // result in a 404 error. await this.ensureAuthorized(type, 'update', namespace, args, 'addToNamespacesUpdate'); - return await this.baseClient.addToNamespaces(type, id, namespaces, options); + const result = await this.baseClient.addToNamespaces(type, id, namespaces, options); + return await this.redactSavedObjectNamespaces(result); } public async deleteFromNamespaces( @@ -177,7 +178,8 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra // To un-share an object, the user must have the "delete" permission in each of the target namespaces. await this.ensureAuthorized(type, 'delete', namespaces, args, 'deleteFromNamespaces'); - return await this.baseClient.deleteFromNamespaces(type, id, namespaces, options); + const result = await this.baseClient.deleteFromNamespaces(type, id, namespaces, options); + return await this.redactSavedObjectNamespaces(result); } public async bulkUpdate( diff --git a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts index 4d0d75cd4595c..51c59212bef16 100644 --- a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts +++ b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts @@ -423,7 +423,7 @@ const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces'; test(`supplements options with the current namespace`, async () => { const { client, baseClient } = await createSpacesSavedObjectsClient(); - const expectedReturnValue = createMockResponse(); + const expectedReturnValue = { namespaces: ['foo', 'bar'] }; baseClient.addToNamespaces.mockReturnValue(Promise.resolve(expectedReturnValue)); const type = Symbol(); @@ -453,7 +453,7 @@ const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces'; test(`supplements options with the current namespace`, async () => { const { client, baseClient } = await createSpacesSavedObjectsClient(); - const expectedReturnValue = createMockResponse(); + const expectedReturnValue = { namespaces: ['foo', 'bar'] }; baseClient.deleteFromNamespaces.mockReturnValue(Promise.resolve(expectedReturnValue)); const type = Symbol(); diff --git a/x-pack/test/api_integration/apis/ml/results/get_categorizer_stats.ts b/x-pack/test/api_integration/apis/ml/results/get_categorizer_stats.ts index a9d863b7526f9..d2a0625cf4e24 100644 --- a/x-pack/test/api_integration/apis/ml/results/get_categorizer_stats.ts +++ b/x-pack/test/api_integration/apis/ml/results/get_categorizer_stats.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/ml/security_common'; -import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; import { Datafeed } from '../../../../../plugins/ml/common/types/anomaly_detection_jobs'; import { AnomalyCategorizerStatsDoc } from '../../../../../plugins/ml/common/types/anomalies'; diff --git a/x-pack/test/api_integration/apis/ml/results/get_stopped_partitions.ts b/x-pack/test/api_integration/apis/ml/results/get_stopped_partitions.ts index 424bc8c333aab..a46c8861258e9 100644 --- a/x-pack/test/api_integration/apis/ml/results/get_stopped_partitions.ts +++ b/x-pack/test/api_integration/apis/ml/results/get_stopped_partitions.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { Datafeed, Job } from '../../../../../plugins/ml/common/types/anomaly_detection_jobs'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/ml/security_common'; -import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); diff --git a/yarn.lock b/yarn.lock index 0bc1ef72651e3..d13db64ad8b79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1120,29 +1120,29 @@ enabled "2.0.x" kuler "^2.0.0" -"@elastic/apm-rum-core@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.5.0.tgz#e05ffd87b95420c788ed3be7cfbbbce1ff54bcf5" - integrity sha512-fPx65oZD495WdHQ3YA8TnzqmjqlvSxoXm0tZqXQKzKVv7CMsNkolnEPSAXFl0W5pmAVRvw6T+vMmxcVIGsCD4Q== +"@elastic/apm-rum-core@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.6.0.tgz#d1f643eb00e590d5884598a20bb54efb1490ee13" + integrity sha512-hG+lITWBQd0mw00BQ1zYVRKDCh5b9FKFiht9fMXcT0SENOsT5J37RIbQHPdVawluT7/mhDF07t4fR8V0xRB1/g== dependencies: error-stack-parser "^1.3.5" opentracing "^0.14.3" promise-polyfill "^8.1.3" -"@elastic/apm-rum-react@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-1.2.2.tgz#b92f1491bae62de0b4296264afe73171f17af022" - integrity sha512-KXM2qxG4p1GeDoud9jpmUA19uuQxW4M+CgtrNIXuNwITMIw46qRLyl5zOIvy9dqHodvLIvZ7RWsFtSZH4kZnAQ== +"@elastic/apm-rum-react@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum-react/-/apm-rum-react-1.2.3.tgz#fdf28492daca0ee6aa67c53a457eea1f16739e1e" + integrity sha512-oCjF/L46OYDRLHKt60l7aU+DFE484dwb/kKN12VZCOgueDZm4BCJd7yaosBtWDhnw0tl0Iqc0X3r4U7pQ+g9aA== dependencies: - "@elastic/apm-rum" "^5.4.0" + "@elastic/apm-rum" "^5.5.0" hoist-non-react-statics "^3.3.0" -"@elastic/apm-rum@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-5.4.0.tgz#2d87d5ca19f7f4a021c03f075d9d767894e88b3c" - integrity sha512-X4uaJlM28pyDOsD06serggspbTyz7Za0zFr+OWUntI6tQKu++Tn8yGsr6L2WuXhKNGhyJmrAfh13pmy9ZGyFcg== +"@elastic/apm-rum@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@elastic/apm-rum/-/apm-rum-5.5.0.tgz#24a8b4db0fa328c1e54710d18837e1adba7e51e0" + integrity sha512-uEOJG7Lm0CLtGfXOLXSsiPLpTPvrNUqlWQEKf/D77lpHRVWxBb56xa4X4CK2on8V1XzHDufcYBPcBcKSGozTLw== dependencies: - "@elastic/apm-rum-core" "^5.5.0" + "@elastic/apm-rum-core" "^5.6.0" "@elastic/charts@19.8.1": version "19.8.1"