Skip to content

Commit

Permalink
Merge branch 'main' into siem-explore-cell-actions-150347-bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
machadoum authored Jul 3, 2023
2 parents f6bc536 + e9a9f03 commit a668cd4
Show file tree
Hide file tree
Showing 177 changed files with 3,503 additions and 1,228 deletions.
13 changes: 0 additions & 13 deletions .buildkite/pipelines/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,6 @@ steps:
- exit_status: '-1'
limit: 3

- command: SERVERLESS_ENVIRONMENT=common .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Common Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
retry:
automatic:
- exit_status: '-1'
limit: 3
- exit_status: '*'
limit: 1

- command: SERVERLESS_ENVIRONMENT=observability .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Observability Tests'
agents:
Expand Down
2 changes: 1 addition & 1 deletion fleet_packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@
},
{
"name": "security_detection_engine",
"version": "8.8.6"
"version": "8.9.1"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import type { Request, ResponseToolkit } from '@hapi/hapi';
import apm from 'elastic-apm-node';
import { isConfigSchema } from '@kbn/config-schema';
import type { Logger } from '@kbn/logging';
import {
Expand Down Expand Up @@ -206,18 +207,24 @@ export class Router<Context extends RequestHandlerContextBase = RequestHandlerCo
const kibanaResponse = await handler(kibanaRequest, kibanaResponseFactory);
return hapiResponseAdapter.handle(kibanaResponse);
} catch (e) {
// log and capture error
this.log.error(e);
apm.captureError(e);

// forward 401 errors from ES client
if (isElasticsearchUnauthorizedError(e)) {
return hapiResponseAdapter.handle(
kibanaResponseFactory.unauthorized(convertEsUnauthorized(e))
);
}

// return a generic 500 to avoid error info / stack trace surfacing
return hapiResponseAdapter.toInternalError();
}
}

private versionedRouter: undefined | VersionedRouter<Context> = undefined;

public get versioned(): VersionedRouter<Context> {
if (this.versionedRouter === undefined) {
this.versionedRouter = CoreVersionedRouter.from({
Expand Down
6 changes: 5 additions & 1 deletion packages/deeplinks/management/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ export type ManagementDeepLinkId = MonitoringAppId | `${ManagementAppId}:${Manag
// Combined
export type AppId = MonitoringAppId | IntegrationsAppId | ManagementAppId;
export type LinkId = ManagementId;
export type DeepLinkId = MonitoringDeepLinkId | IntegrationsDeepLinkId | ManagementDeepLinkId;
export type DeepLinkId =
| AppId
| MonitoringDeepLinkId
| IntegrationsDeepLinkId
| ManagementDeepLinkId;
12 changes: 12 additions & 0 deletions packages/kbn-es/src/utils/extract_config_files.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ jest.mock('fs', () => ({
readFileSync: jest.fn(),
existsSync: jest.fn().mockImplementation(() => true),
writeFileSync: jest.fn(),
statSync: jest.fn((fileName) => {
return {
isFile: () => fileName.endsWith('.yml'),
};
}),
}));

const { extractConfigFiles } = require('./extract_config_files');
Expand Down Expand Up @@ -63,3 +68,10 @@ test('ignores directories', () => {

expect(config).toEqual(['path=foo.yml', 'foo.bar=/data/bar']);
});

test('ignores directories with dots in their names', () => {
fs.existsSync = () => true;
const config = extractConfigFiles(['path=/data/foo.yml', 'foo.bar=/data/ba/r.baz'], '/es');

expect(config).toEqual(['path=foo.yml', 'foo.bar=/data/ba/r.baz']);
});
3 changes: 2 additions & 1 deletion packages/kbn-es/src/utils/extract_config_files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function extractConfigFiles(
if (isFile(value)) {
const filename = path.basename(value);
const destPath = path.resolve(dest, 'config', filename);

copyFileSync(value, destPath);

options?.log.info('moved %s in config to %s', value, destPath);
Expand All @@ -43,7 +44,7 @@ export function extractConfigFiles(
}

function isFile(dest = '') {
return path.isAbsolute(dest) && path.extname(dest).length > 0 && fs.existsSync(dest);
return fs.existsSync(dest) && fs.statSync(dest).isFile();
}

function copyFileSync(src: string, dest: string) {
Expand Down
17 changes: 17 additions & 0 deletions src/core/server/integration_tests/http/router.test.mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export const captureErrorMock = jest.fn();

jest.doMock('elastic-apm-node', () => {
const real = jest.requireActual('elastic-apm-node');
return {
...real,
captureError: captureErrorMock,
};
});
20 changes: 20 additions & 0 deletions src/core/server/integration_tests/http/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Side Public License, v 1.
*/

import { captureErrorMock } from './router.test.mocks';

import { Stream } from 'stream';
import Boom from '@hapi/boom';
import supertest from 'supertest';
Expand Down Expand Up @@ -35,6 +37,7 @@ beforeEach(async () => {
});

afterEach(async () => {
captureErrorMock.mockReset();
await server.stop();
});

Expand Down Expand Up @@ -581,6 +584,22 @@ describe('Handler', () => {
`);
});

it('captures the error if handler throws', async () => {
const { server: innerServer, createRouter } = await server.setup(setupDeps);
const router = createRouter('/');

const error = new Error(`some error`);
router.get({ path: '/', validate: false }, (context, req, res) => {
throw error;
});
await server.start();

await supertest(innerServer.listener).get('/').expect(500);

expect(captureErrorMock).toHaveBeenCalledTimes(1);
expect(captureErrorMock).toHaveBeenCalledWith(error);
});

it('returns 500 Server error if handler throws Boom error', async () => {
const { server: innerServer, createRouter } = await server.setup(setupDeps);
const router = createRouter('/');
Expand All @@ -602,6 +621,7 @@ describe('Handler', () => {
],
]
`);
expect(captureErrorMock).toHaveBeenCalledTimes(1);
});

it('returns 500 Server error if handler returns unexpected result', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export const captureErrorMock = jest.fn();

jest.doMock('elastic-apm-node', () => {
const real = jest.requireActual('elastic-apm-node');
return {
...real,
captureError: captureErrorMock,
};
});
23 changes: 23 additions & 0 deletions src/core/server/integration_tests/http/versioned_router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Side Public License, v 1.
*/

import { captureErrorMock } from './versioned_router.test.mocks';

import Supertest from 'supertest';
import { createTestEnv, getEnvOptions } from '@kbn/config-mocks';
import { schema } from '@kbn/config-schema';
Expand Down Expand Up @@ -59,6 +61,7 @@ describe('Routing versioned requests', () => {
});

afterEach(async () => {
captureErrorMock.mockReset();
await server.stop();
});

Expand Down Expand Up @@ -167,6 +170,7 @@ describe('Routing versioned requests', () => {
message: expect.stringMatching(/expected value of type/),
})
);
expect(captureErrorMock).not.toHaveBeenCalled();
});

it('returns the version in response headers', async () => {
Expand Down Expand Up @@ -210,6 +214,7 @@ describe('Routing versioned requests', () => {
message: expect.stringMatching(/Failed output validation/),
})
);
expect(captureErrorMock).not.toHaveBeenCalled();
});

it('does not run response validation in prod', async () => {
Expand Down Expand Up @@ -295,6 +300,7 @@ describe('Routing versioned requests', () => {
).resolves.toEqual(
expect.objectContaining({ message: expect.stringMatching(/No handlers registered/) })
);
expect(captureErrorMock).not.toHaveBeenCalled();
});

it('resolves the newest handler on serverless', async () => {
Expand Down Expand Up @@ -340,4 +346,21 @@ describe('Routing versioned requests', () => {
.then(({ body }) => body.v)
).resolves.toEqual('oldest');
});

it('captures the error if handler throws', async () => {
const error = new Error(`some error`);

router.versioned
.get({ path: '/my-path', access: 'internal' })
.addVersion({ validate: false, version: '1' }, async (ctx, req, res) => {
throw error;
});

await server.start();

await supertest.get('/my-path').set('Elastic-Api-Version', '1').expect(500);

expect(captureErrorMock).toHaveBeenCalledTimes(1);
expect(captureErrorMock).toHaveBeenCalledWith(error);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,8 @@ describe('split .kibana index into multiple system indices', () => {
});
});

// FLAKY: https://github.com/elastic/kibana/issues/157510
// This test takes too long. Can be manually executed to verify the correct behavior.
describe.skip('when multiple Kibana migrators run in parallel', () => {
describe('when multiple Kibana migrators run in parallel', () => {
jest.setTimeout(1200000);
it('correctly migrates 7.7.2_xpack_100k_obj.zip archive', async () => {
esServer = await startElasticsearch({
dataArchive: Path.join(__dirname, '..', 'archives', '7.7.2_xpack_100k_obj.zip'),
Expand Down Expand Up @@ -491,7 +490,7 @@ describe('split .kibana index into multiple system indices', () => {
task: 5,
},
});
}, 1200000);
});

afterEach(async () => {
await esServer?.stop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,21 @@ describe('Test createSearchSessionRestorationDataProvider', () => {
let mockSavedSearch: SavedSearch = {} as unknown as SavedSearch;
const history = createBrowserHistory();
const mockDataPlugin = dataPluginMock.createStartContract();
const discoverStateContainer = getDiscoverStateContainer({
services: discoverServiceMock,
history,
});
discoverStateContainer.appState.update({
index: savedSearchMock.searchSource.getField('index')!.id,
});
const searchSessionInfoProvider = createSearchSessionRestorationDataProvider({
data: mockDataPlugin,
appStateContainer: getDiscoverStateContainer({
savedSearch: savedSearchMock,
services: discoverServiceMock,
history,
}).appState,
appStateContainer: discoverStateContainer.appState,
getSavedSearch: () => mockSavedSearch,
});

describe('session name', () => {
test('No saved search returns default name', async () => {
test('No persisted saved search returns default name', async () => {
expect(await searchSessionInfoProvider.getName()).toBe('Discover');
});

Expand All @@ -211,6 +214,7 @@ describe('Test createSearchSessionRestorationDataProvider', () => {

describe('session state', () => {
test('restoreState has sessionId and initialState has not', async () => {
mockSavedSearch = savedSearchMock;
const searchSessionId = 'id';
(mockDataPlugin.search.session.getSessionId as jest.Mock).mockImplementation(
() => searchSessionId
Expand All @@ -221,6 +225,7 @@ describe('Test createSearchSessionRestorationDataProvider', () => {
});

test('restoreState has absoluteTimeRange', async () => {
mockSavedSearch = savedSearchMock;
const relativeTime = 'relativeTime';
const absoluteTime = 'absoluteTime';
(mockDataPlugin.query.timefilter.timefilter.getTime as jest.Mock).mockImplementation(
Expand All @@ -235,13 +240,29 @@ describe('Test createSearchSessionRestorationDataProvider', () => {
});

test('restoreState has paused autoRefresh', async () => {
mockSavedSearch = savedSearchMock;
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.refreshInterval).toBe(undefined);
expect(restoreState.refreshInterval).toEqual({
pause: true,
value: 0,
});
});

test('restoreState has persisted data view', async () => {
mockSavedSearch = savedSearchMock;
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.dataViewSpec).toEqual(undefined);
expect(restoreState.dataViewSpec).toEqual(undefined);
expect(initialState.dataViewId).toEqual(savedSearchMock.searchSource.getField('index')?.id);
});

test('restoreState has temporary data view', async () => {
mockSavedSearch = savedSearchAdHoc;
const { initialState, restoreState } = await searchSessionInfoProvider.getLocatorData();
expect(initialState.dataViewSpec).toEqual({});
expect(restoreState.dataViewSpec).toEqual({});
});
});
});

Expand Down
Loading

0 comments on commit a668cd4

Please sign in to comment.