Skip to content

Commit 964bd49

Browse files
committed
Merge branch 'master' of github.com:elastic/kibana into override-fixes
2 parents cbc9428 + 9656cbc commit 964bd49

File tree

50 files changed

+2397
-1806
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2397
-1806
lines changed

docs/developer/advanced/running-elasticsearch.asciidoc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ This will run a snapshot of {es} that is usually built nightly. Read more about
1313
----
1414
yarn es snapshot
1515
----
16+
By default, two users are added to Elasticsearch:
17+
18+
- A superuser with username: `elastic` and password: `changeme`, which can be used to log into Kibana with.
19+
- A user with username: `kibana_system` and password `changeme`. This account is used by the Kibana server to authenticate itself to Elasticsearch, and to perform certain actions on behalf of the end user. These credentials should be specified in your kibana.yml as described in <<using-kibana-with-security>>
1620

1721
See all available options, like how to specify a specific license, with the `--help` flag.
1822

@@ -115,4 +119,4 @@ PUT _cluster/settings
115119
}
116120
----
117121

118-
Follow the cross-cluster search instructions for setting up index patterns to search across clusters (<<management-cross-cluster-search>>).
122+
Follow the cross-cluster search instructions for setting up index patterns to search across clusters (<<management-cross-cluster-search>>).

packages/kbn-spec-to-console/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ At the root of the Kibana repository, run the following commands:
2323

2424
```sh
2525
# OSS
26-
yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/rest-api-spec/src/main/resources/rest-api-spec/api/*" -d "src/plugins/console/server/lib/spec_definitions/json"
26+
yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/rest-api-spec/src/main/resources/rest-api-spec/api/*" -d "src/plugins/console/server/lib/spec_definitions/json/generated"
2727

2828
# X-pack
29-
yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/x-pack/plugin/src/test/resources/rest-api-spec/api/*" -d "x-pack/plugins/console_extensions/server/lib/spec_definitions/json"
29+
yarn spec_to_console -g "<ELASTICSEARCH-REPO-FOLDER>/x-pack/plugin/src/test/resources/rest-api-spec/api/*" -d "x-pack/plugins/console_extensions/server/lib/spec_definitions/json/generated"
3030
```
3131

3232
### Information used in Console that is not available in the REST spec

src/core/server/elasticsearch/client/configure_client.test.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,26 +118,40 @@ describe('configureClient', () => {
118118
});
119119

120120
describe('Client logging', () => {
121-
it('logs error when the client emits an error', () => {
121+
it('logs error when the client emits an @elastic/elasticsearch error', () => {
122+
const client = configureClient(config, { logger, scoped: false });
123+
124+
const response = createApiResponse({ body: {} });
125+
client.emit('response', new errors.TimeoutError('message', response), response);
126+
127+
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(`
128+
Array [
129+
Array [
130+
"[TimeoutError]: message",
131+
],
132+
]
133+
`);
134+
});
135+
136+
it('logs error when the client emits an ResponseError returned by elasticsearch', () => {
122137
const client = configureClient(config, { logger, scoped: false });
123138

124139
const response = createApiResponse({
140+
statusCode: 400,
141+
headers: {},
125142
body: {
126143
error: {
127-
type: 'error message',
144+
type: 'illegal_argument_exception',
145+
reason: 'request [/_path] contains unrecognized parameter: [name]',
128146
},
129147
},
130148
});
131-
client.emit('response', new errors.ResponseError(response), null);
132-
client.emit('response', new Error('some error'), null);
149+
client.emit('response', new errors.ResponseError(response), response);
133150

134151
expect(loggingSystemMock.collect(logger).error).toMatchInlineSnapshot(`
135152
Array [
136153
Array [
137-
"ResponseError: error message",
138-
],
139-
Array [
140-
"Error: some error",
154+
"[illegal_argument_exception]: request [/_path] contains unrecognized parameter: [name]",
141155
],
142156
]
143157
`);

src/core/server/elasticsearch/client/configure_client.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { stringify } from 'querystring';
2121
import { Client } from '@elastic/elasticsearch';
2222
import { Logger } from '../../logging';
2323
import { parseClientOptions, ElasticsearchClientConfig } from './client_config';
24+
import { isResponseError } from './errors';
2425

2526
export const configureClient = (
2627
config: ElasticsearchClientConfig,
@@ -35,9 +36,15 @@ export const configureClient = (
3536
};
3637

3738
const addLogging = (client: Client, logger: Logger, logQueries: boolean) => {
38-
client.on('response', (err, event) => {
39-
if (err) {
40-
logger.error(`${err.name}: ${err.message}`);
39+
client.on('response', (error, event) => {
40+
if (error) {
41+
const errorMessage =
42+
// error details for response errors provided by elasticsearch
43+
isResponseError(error)
44+
? `[${event.body.error.type}]: ${event.body.error.reason}`
45+
: `[${error.name}]: ${error.message}`;
46+
47+
logger.error(errorMessage);
4148
}
4249
if (event && logQueries) {
4350
const params = event.meta.request.params;

src/core/server/elasticsearch/client/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* under the License.
1818
*/
1919

20-
export { ElasticsearchClient } from './types';
20+
export * from './types';
2121
export { IScopedClusterClient, ScopedClusterClient } from './scoped_cluster_client';
2222
export { ElasticsearchClientConfig } from './client_config';
2323
export { IClusterClient, ICustomClusterClient, ClusterClient } from './cluster_client';

src/core/server/elasticsearch/client/mocks.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const createInternalClientMock = (): DeeplyMockedKeys<Client> => {
4545
.forEach((key) => {
4646
const propType = typeof obj[key];
4747
if (propType === 'function') {
48-
obj[key] = jest.fn();
48+
obj[key] = jest.fn(() => createSuccessTransportRequestPromise({}));
4949
} else if (propType === 'object' && obj[key] != null) {
5050
mockify(obj[key]);
5151
}
@@ -70,6 +70,7 @@ const createInternalClientMock = (): DeeplyMockedKeys<Client> => {
7070
return (mock as unknown) as DeeplyMockedKeys<Client>;
7171
};
7272

73+
// TODO fix naming ElasticsearchClientMock
7374
export type ElasticSearchClientMock = DeeplyMockedKeys<ElasticsearchClient>;
7475

7576
const createClientMock = (): ElasticSearchClientMock =>
@@ -124,32 +125,41 @@ export type MockedTransportRequestPromise<T> = TransportRequestPromise<T> & {
124125
abort: jest.MockedFunction<() => undefined>;
125126
};
126127

127-
const createMockedClientResponse = <T>(body: T): MockedTransportRequestPromise<ApiResponse<T>> => {
128-
const response: ApiResponse<T> = {
129-
body,
130-
statusCode: 200,
131-
warnings: [],
132-
headers: {},
133-
meta: {} as any,
134-
};
128+
const createSuccessTransportRequestPromise = <T>(
129+
body: T,
130+
{ statusCode = 200 }: { statusCode?: number } = {}
131+
): MockedTransportRequestPromise<ApiResponse<T>> => {
132+
const response = createApiResponse({ body, statusCode });
135133
const promise = Promise.resolve(response);
136134
(promise as MockedTransportRequestPromise<ApiResponse<T>>).abort = jest.fn();
137135

138136
return promise as MockedTransportRequestPromise<ApiResponse<T>>;
139137
};
140138

141-
const createMockedClientError = (err: any): MockedTransportRequestPromise<never> => {
139+
const createErrorTransportRequestPromise = (err: any): MockedTransportRequestPromise<never> => {
142140
const promise = Promise.reject(err);
143141
(promise as MockedTransportRequestPromise<never>).abort = jest.fn();
144142
return promise as MockedTransportRequestPromise<never>;
145143
};
146144

145+
function createApiResponse(opts: Partial<ApiResponse> = {}): ApiResponse {
146+
return {
147+
body: {},
148+
statusCode: 200,
149+
headers: {},
150+
warnings: [],
151+
meta: {} as any,
152+
...opts,
153+
};
154+
}
155+
147156
export const elasticsearchClientMock = {
148157
createClusterClient: createClusterClientMock,
149158
createCustomClusterClient: createCustomClusterClientMock,
150159
createScopedClusterClient: createScopedClusterClientMock,
151160
createElasticSearchClient: createClientMock,
152161
createInternalClient: createInternalClientMock,
153-
createClientResponse: createMockedClientResponse,
154-
createClientError: createMockedClientError,
162+
createSuccessTransportRequestPromise,
163+
createErrorTransportRequestPromise,
164+
createApiResponse,
155165
};

src/core/server/elasticsearch/client/retry_call_cluster.test.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import { loggingSystemMock } from '../../logging/logging_system.mock';
2323
import { retryCallCluster, migrationRetryCallCluster } from './retry_call_cluster';
2424

2525
const dummyBody = { foo: 'bar' };
26-
const createErrorReturn = (err: any) => elasticsearchClientMock.createClientError(err);
26+
const createErrorReturn = (err: any) =>
27+
elasticsearchClientMock.createErrorTransportRequestPromise(err);
2728

2829
describe('retryCallCluster', () => {
2930
let client: ReturnType<typeof elasticsearchClientMock.createElasticSearchClient>;
@@ -33,7 +34,9 @@ describe('retryCallCluster', () => {
3334
});
3435

3536
it('returns response from ES API call in case of success', async () => {
36-
const successReturn = elasticsearchClientMock.createClientResponse({ ...dummyBody });
37+
const successReturn = elasticsearchClientMock.createSuccessTransportRequestPromise({
38+
...dummyBody,
39+
});
3740

3841
client.asyncSearch.get.mockReturnValue(successReturn);
3942

@@ -42,7 +45,9 @@ describe('retryCallCluster', () => {
4245
});
4346

4447
it('retries ES API calls that rejects with `NoLivingConnectionsError`', async () => {
45-
const successReturn = elasticsearchClientMock.createClientResponse({ ...dummyBody });
48+
const successReturn = elasticsearchClientMock.createSuccessTransportRequestPromise({
49+
...dummyBody,
50+
});
4651

4752
client.asyncSearch.get
4853
.mockImplementationOnce(() =>
@@ -57,7 +62,9 @@ describe('retryCallCluster', () => {
5762
it('rejects when ES API calls reject with other errors', async () => {
5863
client.ping
5964
.mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
60-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
65+
.mockImplementationOnce(() =>
66+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
67+
);
6168

6269
await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot(
6370
`[Error: unknown error]`
@@ -73,7 +80,9 @@ describe('retryCallCluster', () => {
7380
createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any))
7481
)
7582
.mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
76-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
83+
.mockImplementationOnce(() =>
84+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
85+
);
7786

7887
await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot(
7988
`[Error: unknown error]`
@@ -94,7 +103,9 @@ describe('migrationRetryCallCluster', () => {
94103
client.ping
95104
.mockImplementationOnce(() => createErrorReturn(error))
96105
.mockImplementationOnce(() => createErrorReturn(error))
97-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
106+
.mockImplementationOnce(() =>
107+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
108+
);
98109
};
99110

100111
it('retries ES API calls that rejects with `NoLivingConnectionsError`', async () => {
@@ -225,7 +236,9 @@ describe('migrationRetryCallCluster', () => {
225236
} as any)
226237
)
227238
)
228-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
239+
.mockImplementationOnce(() =>
240+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
241+
);
229242

230243
await migrationRetryCallCluster(() => client.ping(), logger, 1);
231244

@@ -258,7 +271,9 @@ describe('migrationRetryCallCluster', () => {
258271
} as any)
259272
)
260273
)
261-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
274+
.mockImplementationOnce(() =>
275+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
276+
);
262277

263278
await expect(
264279
migrationRetryCallCluster(() => client.ping(), logger, 1)
@@ -274,7 +289,9 @@ describe('migrationRetryCallCluster', () => {
274289
createErrorReturn(new errors.TimeoutError('timeout error', {} as any))
275290
)
276291
.mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
277-
.mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
292+
.mockImplementationOnce(() =>
293+
elasticsearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody })
294+
);
278295

279296
await expect(
280297
migrationRetryCallCluster(() => client.ping(), logger, 1)

src/core/server/elasticsearch/client/retry_call_cluster.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const retryResponseStatuses = [
2727
403, // AuthenticationException
2828
408, // RequestTimeout
2929
410, // Gone
30-
];
30+
] as const;
3131

3232
/**
3333
* Retries the provided Elasticsearch API call when a `NoLivingConnectionsError` error is

src/core/server/elasticsearch/client/types.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,83 @@ export type ElasticsearchClient = Omit<
4141
): TransportRequestPromise<ApiResponse>;
4242
};
4343
};
44+
45+
interface ShardsResponse {
46+
total: number;
47+
successful: number;
48+
failed: number;
49+
skipped: number;
50+
}
51+
52+
interface Explanation {
53+
value: number;
54+
description: string;
55+
details: Explanation[];
56+
}
57+
58+
interface ShardsInfo {
59+
total: number;
60+
successful: number;
61+
skipped: number;
62+
failed: number;
63+
}
64+
65+
export interface CountResponse {
66+
_shards: ShardsInfo;
67+
count: number;
68+
}
69+
70+
/**
71+
* Maintained until elasticsearch provides response typings out of the box
72+
* https://github.com/elastic/elasticsearch-js/pull/970
73+
*/
74+
export interface SearchResponse<T = unknown> {
75+
took: number;
76+
timed_out: boolean;
77+
_scroll_id?: string;
78+
_shards: ShardsResponse;
79+
hits: {
80+
total: number;
81+
max_score: number;
82+
hits: Array<{
83+
_index: string;
84+
_type: string;
85+
_id: string;
86+
_score: number;
87+
_source: T;
88+
_version?: number;
89+
_explanation?: Explanation;
90+
fields?: any;
91+
highlight?: any;
92+
inner_hits?: any;
93+
matched_queries?: string[];
94+
sort?: string[];
95+
}>;
96+
};
97+
aggregations?: any;
98+
}
99+
100+
export interface GetResponse<T> {
101+
_index: string;
102+
_type: string;
103+
_id: string;
104+
_version: number;
105+
_routing?: string;
106+
found: boolean;
107+
_source: T;
108+
_seq_no: number;
109+
_primary_term: number;
110+
}
111+
112+
export interface DeleteDocumentResponse {
113+
_shards: ShardsResponse;
114+
found: boolean;
115+
_index: string;
116+
_type: string;
117+
_id: string;
118+
_version: number;
119+
result: string;
120+
error?: {
121+
type: string;
122+
};
123+
}

0 commit comments

Comments
 (0)