Skip to content

Commit

Permalink
Merge branch 'master' into dev/config-disable-url-drilldown
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticmachine committed Sep 22, 2020
2 parents b6f6f15 + f412971 commit 122804a
Show file tree
Hide file tree
Showing 174 changed files with 4,982 additions and 1,778 deletions.
5 changes: 0 additions & 5 deletions docs/apm/service-maps.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
[[service-maps]]
=== Service maps

beta::[]

WARNING: Service map support for Internet Explorer 11 is extremely limited.
Please use Chrome or Firefox if available.

A service map is a real-time visual representation of the instrumented services in your application's architecture.
It shows you how these services are connected, along with high-level metrics like average transaction duration,
requests per minute, and errors per minute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ export interface SavedObjectsFindOptions
| [sortField](./kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md) | <code>string</code> | |
| [sortOrder](./kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md) | <code>string</code> | |
| [type](./kibana-plugin-core-public.savedobjectsfindoptions.type.md) | <code>string &#124; string[]</code> | |
| [typeToNamespacesMap](./kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md) | <code>Map&lt;string, string[] &#124; undefined&gt;</code> | This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the <code>type</code> and <code>namespaces</code> fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-public](./kibana-plugin-core-public.md) &gt; [SavedObjectsFindOptions](./kibana-plugin-core-public.savedobjectsfindoptions.md) &gt; [typeToNamespacesMap](./kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md)

## SavedObjectsFindOptions.typeToNamespacesMap property

This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the `type` and `namespaces` fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace.

<b>Signature:</b>

```typescript
typeToNamespacesMap?: Map<string, string[] | undefined>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ export interface SavedObjectsFindOptions
| [sortField](./kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md) | <code>string</code> | |
| [sortOrder](./kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md) | <code>string</code> | |
| [type](./kibana-plugin-core-server.savedobjectsfindoptions.type.md) | <code>string &#124; string[]</code> | |
| [typeToNamespacesMap](./kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md) | <code>Map&lt;string, string[] &#124; undefined&gt;</code> | This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the <code>type</code> and <code>namespaces</code> fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) &gt; [typeToNamespacesMap](./kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md)

## SavedObjectsFindOptions.typeToNamespacesMap property

This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the `type` and `namespaces` fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace.

<b>Signature:</b>

```typescript
typeToNamespacesMap?: Map<string, string[] | undefined>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
<b>Signature:</b>

```typescript
find<T = unknown>({ search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, }: SavedObjectsFindOptions): Promise<SavedObjectsFindResponse<T>>;
find<T = unknown>(options: SavedObjectsFindOptions): Promise<SavedObjectsFindResponse<T>>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| { search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, } | <code>SavedObjectsFindOptions</code> | |
| options | <code>SavedObjectsFindOptions</code> | |
<b>Returns:</b>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export declare class SavedObjectsRepository
| [delete(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.delete.md) | | Deletes an object |
| [deleteByNamespace(namespace, options)](./kibana-plugin-core-server.savedobjectsrepository.deletebynamespace.md) | | Deletes all objects from the provided namespace. |
| [deleteFromNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) | | Removes one or more namespaces from a given multi-namespace saved object. If no namespaces remain, the saved object is deleted entirely. This method and \[<code>addToNamespaces</code>\][SavedObjectsRepository.addToNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. |
| [find({ search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, })](./kibana-plugin-core-server.savedobjectsrepository.find.md) | | |
| [find(options)](./kibana-plugin-core-server.savedobjectsrepository.find.md) | | |
| [get(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.get.md) | | Gets a single object |
| [incrementCounter(type, id, counterFieldName, options)](./kibana-plugin-core-server.savedobjectsrepository.incrementcounter.md) | | Increases a counter field by one. Creates the document if one doesn't exist for the given id. |
| [update(type, id, attributes, options)](./kibana-plugin-core-server.savedobjectsrepository.update.md) | | Updates an object |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) &gt; [createEmptyFindResponse](./kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md)

## SavedObjectsUtils.createEmptyFindResponse property

Creates an empty response for a find operation. This is only intended to be used by saved objects client wrappers.

<b>Signature:</b>

```typescript
static createEmptyFindResponse: <T>({ page, perPage, }: SavedObjectsFindOptions) => SavedObjectsFindResponse<T>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export declare class SavedObjectsUtils

| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [createEmptyFindResponse](./kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md) | <code>static</code> | <code>&lt;T&gt;({ page, perPage, }: SavedObjectsFindOptions) =&gt; SavedObjectsFindResponse&lt;T&gt;</code> | Creates an empty response for a find operation. This is only intended to be used by saved objects client wrappers. |
| [namespaceIdToString](./kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md) | <code>static</code> | <code>(namespace?: string &#124; undefined) =&gt; string</code> | Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the <code>undefined</code> namespace ID (which has a namespace string of <code>'default'</code>). |
| [namespaceStringToId](./kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md) | <code>static</code> | <code>(namespace: string) =&gt; string &#124; undefined</code> | Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the <code>'default'</code> namespace string (which has a namespace ID of <code>undefined</code>). |

14 changes: 10 additions & 4 deletions docs/user/monitoring/viewing-metrics.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ At a minimum, you must have monitoring data for the {es} production cluster.
Once that data exists, {kib} can display monitoring data for other products in
the cluster.

TIP: If you use a separate monitoring cluster to store the monitoring data, it
is strongly recommended that you use a separate {kib} instance to view it. If
you log in to {kib} using SAML, Kerberos, PKI, OpenID Connect, or token
authentication providers, a dedicated {kib} instance is *required*. The security
tokens that are used in these contexts are cluster-specific, therefore you
cannot use a single {kib} instance to connect to both production and monitoring
clusters. For more information about the recommended configuration, see
{ref}/monitoring-overview.html[Monitoring overview].

. Identify where to retrieve monitoring data from.
+
--
The cluster that contains the monitoring data is referred to
as the _monitoring cluster_.

TIP: If the monitoring data is stored on a *dedicated* monitoring cluster, it is
If the monitoring data is stored on a dedicated monitoring cluster, it is
accessible even when the cluster you're monitoring is not. If you have at least
a gold license, you can send data from multiple clusters to the same monitoring
cluster and view them all through the same instance of {kib}.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@
"babel-eslint": "^10.0.3",
"babel-jest": "^25.5.1",
"babel-plugin-istanbul": "^6.0.0",
"backport": "5.5.1",
"backport": "5.6.0",
"brace": "0.11.1",
"chai": "3.5.0",
"chance": "1.0.18",
Expand Down
1 change: 1 addition & 0 deletions src/core/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,7 @@ export interface SavedObjectsFindOptions {
sortOrder?: string;
// (undocumented)
type: string | string[];
typeToNamespacesMap?: Map<string, string[] | undefined>;
}

// @public
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/saved_objects/saved_objects_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { HttpFetchOptions, HttpSetup } from '../http';

type SavedObjectsFindOptions = Omit<
SavedObjectFindOptionsServer,
'namespace' | 'sortOrder' | 'rootSearchFields'
'sortOrder' | 'rootSearchFields' | 'typeToNamespacesMap'
>;

type PromiseType<T extends Promise<any>> = T extends Promise<infer U> ? U : never;
Expand Down
93 changes: 76 additions & 17 deletions src/core/server/saved_objects/service/lib/repository.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2477,6 +2477,33 @@ describe('SavedObjectsRepository', () => {
expect(client.search).not.toHaveBeenCalled();
});

it(`throws when namespaces is an empty array`, async () => {
await expect(
savedObjectsRepository.find({ type: 'foo', namespaces: [] })
).rejects.toThrowError('options.namespaces cannot be an empty array');
expect(client.search).not.toHaveBeenCalled();
});

it(`throws when type is not falsy and typeToNamespacesMap is defined`, async () => {
await expect(
savedObjectsRepository.find({ type: 'foo', typeToNamespacesMap: new Map() })
).rejects.toThrowError(
'options.type must be an empty string when options.typeToNamespacesMap is used'
);
expect(client.search).not.toHaveBeenCalled();
});

it(`throws when type is not an empty array and typeToNamespacesMap is defined`, async () => {
const test = async (args) => {
await expect(savedObjectsRepository.find(args)).rejects.toThrowError(
'options.namespaces must be an empty array when options.typeToNamespacesMap is used'
);
expect(client.search).not.toHaveBeenCalled();
};
await test({ type: '', typeToNamespacesMap: new Map() });
await test({ type: '', namespaces: ['some-ns'], typeToNamespacesMap: new Map() });
});

it(`throws when searchFields is defined but not an array`, async () => {
await expect(
savedObjectsRepository.find({ type, searchFields: 'string' })
Expand All @@ -2493,7 +2520,7 @@ describe('SavedObjectsRepository', () => {

it(`throws when KQL filter syntax is invalid`, async () => {
const findOpts = {
namespace,
namespaces: [namespace],
search: 'foo*',
searchFields: ['foo'],
type: ['dashboard'],
Expand Down Expand Up @@ -2577,38 +2604,70 @@ describe('SavedObjectsRepository', () => {
const test = async (types) => {
const result = await savedObjectsRepository.find({ type: types });
expect(result).toEqual(expect.objectContaining({ saved_objects: [] }));
expect(client.search).not.toHaveBeenCalled();
};

await test('unknownType');
await test(HIDDEN_TYPE);
await test(['unknownType', HIDDEN_TYPE]);
});

it(`should return empty results when attempting to find only invalid or hidden types using typeToNamespacesMap`, async () => {
const test = async (types) => {
const result = await savedObjectsRepository.find({
typeToNamespacesMap: new Map(types.map((x) => [x, undefined])),
type: '',
namespaces: [],
});
expect(result).toEqual(expect.objectContaining({ saved_objects: [] }));
expect(client.search).not.toHaveBeenCalled();
};

await test(['unknownType']);
await test([HIDDEN_TYPE]);
await test(['unknownType', HIDDEN_TYPE]);
});
});

describe('search dsl', () => {
it(`passes mappings, registry, search, defaultSearchOperator, searchFields, type, sortField, sortOrder and hasReference to getSearchDsl`, async () => {
const commonOptions = {
type: [type], // cannot be used when `typeToNamespacesMap` is present
namespaces: [namespace], // cannot be used when `typeToNamespacesMap` is present
search: 'foo*',
searchFields: ['foo'],
sortField: 'name',
sortOrder: 'desc',
defaultSearchOperator: 'AND',
hasReference: {
type: 'foo',
id: '1',
},
kueryNode: undefined,
};

it(`passes mappings, registry, and search options to getSearchDsl`, async () => {
await findSuccess(commonOptions, namespace);
expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, commonOptions);
});

it(`accepts typeToNamespacesMap`, async () => {
const relevantOpts = {
namespaces: [namespace],
search: 'foo*',
searchFields: ['foo'],
type: [type],
sortField: 'name',
sortOrder: 'desc',
defaultSearchOperator: 'AND',
hasReference: {
type: 'foo',
id: '1',
},
kueryNode: undefined,
...commonOptions,
type: '',
namespaces: [],
typeToNamespacesMap: new Map([[type, [namespace]]]), // can only be used when `type` is falsy and `namespaces` is an empty array
};

await findSuccess(relevantOpts, namespace);
expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, relevantOpts);
expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, {
...relevantOpts,
type: [type],
});
});

it(`accepts KQL expression filter and passes KueryNode to getSearchDsl`, async () => {
const findOpts = {
namespace,
namespaces: [namespace],
search: 'foo*',
searchFields: ['foo'],
type: ['dashboard'],
Expand Down Expand Up @@ -2649,7 +2708,7 @@ describe('SavedObjectsRepository', () => {

it(`accepts KQL KueryNode filter and passes KueryNode to getSearchDsl`, async () => {
const findOpts = {
namespace,
namespaces: [namespace],
search: 'foo*',
searchFields: ['foo'],
type: ['dashboard'],
Expand Down
65 changes: 40 additions & 25 deletions src/core/server/saved_objects/service/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import {
} from '../../types';
import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry';
import { validateConvertFilterToKueryNode } from './filter_utils';
import { SavedObjectsUtils } from './utils';
import { FIND_DEFAULT_PAGE, FIND_DEFAULT_PER_PAGE, SavedObjectsUtils } from './utils';

// BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository
// so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient.
Expand Down Expand Up @@ -693,37 +693,51 @@ export class SavedObjectsRepository {
* @property {string} [options.preference]
* @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page }
*/
async find<T = unknown>({
search,
defaultSearchOperator = 'OR',
searchFields,
rootSearchFields,
hasReference,
page = 1,
perPage = 20,
sortField,
sortOrder,
fields,
namespaces,
type,
filter,
preference,
}: SavedObjectsFindOptions): Promise<SavedObjectsFindResponse<T>> {
if (!type) {
async find<T = unknown>(options: SavedObjectsFindOptions): Promise<SavedObjectsFindResponse<T>> {
const {
search,
defaultSearchOperator = 'OR',
searchFields,
rootSearchFields,
hasReference,
page = FIND_DEFAULT_PAGE,
perPage = FIND_DEFAULT_PER_PAGE,
sortField,
sortOrder,
fields,
namespaces,
type,
typeToNamespacesMap,
filter,
preference,
} = options;

if (!type && !typeToNamespacesMap) {
throw SavedObjectsErrorHelpers.createBadRequestError(
'options.type must be a string or an array of strings'
);
} else if (namespaces?.length === 0 && !typeToNamespacesMap) {
throw SavedObjectsErrorHelpers.createBadRequestError(
'options.namespaces cannot be an empty array'
);
} else if (type && typeToNamespacesMap) {
throw SavedObjectsErrorHelpers.createBadRequestError(
'options.type must be an empty string when options.typeToNamespacesMap is used'
);
} else if ((!namespaces || namespaces?.length) && typeToNamespacesMap) {
throw SavedObjectsErrorHelpers.createBadRequestError(
'options.namespaces must be an empty array when options.typeToNamespacesMap is used'
);
}

const types = Array.isArray(type) ? type : [type];
const types = type
? Array.isArray(type)
? type
: [type]
: Array.from(typeToNamespacesMap!.keys());
const allowedTypes = types.filter((t) => this._allowedTypes.includes(t));
if (allowedTypes.length === 0) {
return {
page,
per_page: perPage,
total: 0,
saved_objects: [],
};
return SavedObjectsUtils.createEmptyFindResponse<T>(options);
}

if (searchFields && !Array.isArray(searchFields)) {
Expand Down Expand Up @@ -766,6 +780,7 @@ export class SavedObjectsRepository {
sortField,
sortOrder,
namespaces,
typeToNamespacesMap,
hasReference,
kueryNode,
}),
Expand Down
Loading

0 comments on commit 122804a

Please sign in to comment.