Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional tests for execution context propagation in alerting and task manager plugins #111179

Merged
Merged
1 change: 0 additions & 1 deletion scripts/functional_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const onlyNotInCoverageTests = [
require.resolve('../test/api_integration/config.js'),
require.resolve('../test/interpreter_functional/config.ts'),
require.resolve('../test/examples/config.js'),
require.resolve('../test/functional_execution_context/config.ts'),
];

require('../src/setup_node_env');
Expand Down
1 change: 1 addition & 0 deletions x-pack/scripts/functional_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const onlyNotInCoverageTests = [
require.resolve('../test/saved_object_tagging/api_integration/tagging_api/config.ts'),
require.resolve('../test/examples/config.ts'),
require.resolve('../test/performance/config.ts'),
require.resolve('../test/functional_execution_context/config.ts'),
];

require('../../src/setup_node_env');
Expand Down
60 changes: 60 additions & 0 deletions x-pack/test/functional_execution_context/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import Path from 'path';
import { CA_CERT_PATH } from '@kbn/dev-utils';
import { FtrConfigProviderContext } from '@kbn/test';
import { logFilePath } from './test_utils';

const alertTestPlugin = Path.resolve(__dirname, './fixtures/plugins/alerts');

export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../../test/functional/config'));

const servers = {
...functionalConfig.get('servers'),
elasticsearch: {
...functionalConfig.get('servers.elasticsearch'),
protocol: 'https',
},
};

return {
...functionalConfig.getAll(),
rootTags: ['skipCloud'],
testFiles: [require.resolve('./tests/')],
junit: {
reportName: 'Execution Context Functional Tests',
},
servers,
esTestCluster: {
...functionalConfig.get('esTestCluster'),
ssl: true,
},
kbnTestServer: {
...functionalConfig.get('kbnTestServer'),
serverArgs: [
...functionalConfig.get('kbnTestServer.serverArgs'),
`--plugin-path=${alertTestPlugin}`,
`--elasticsearch.hosts=${servers.elasticsearch.protocol}://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`,
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,

'--execution_context.enabled=true',
'--logging.appenders.file.type=file',
`--logging.appenders.file.fileName=${logFilePath}`,
'--logging.appenders.file.layout.type=json',

'--logging.loggers[0].name=elasticsearch.query',
'--logging.loggers[0].level=all',
`--logging.loggers[0].appenders=${JSON.stringify(['file'])}`,

'--logging.loggers[1].name=execution_context',
'--logging.loggers[1].level=debug',
`--logging.loggers[1].appenders=${JSON.stringify(['file'])}`,
],
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"id": "alertsFixtures",
"owner": {
"name": "Core team",
"githubTeam": "kibana-core"
},
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack"],
"requiredPlugins": ["features", "alerting"],
"server": true,
"ui": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "alerts-fixtures",
"version": "1.0.0",
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"scripts": {
"kbn": "node ../../../../../../scripts/kbn.js",
"build": "rm -rf './target' && ../../../../../../node_modules/.bin/tsc"
},
"license": "Elastic License 2.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { FixturePlugin } from './plugin';

export const plugin = () => new FixturePlugin();
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { Plugin, CoreSetup } from 'kibana/server';
import { PluginSetupContract as AlertingPluginSetup } from '../../../../../../plugins/alerting/server/plugin';
import { EncryptedSavedObjectsPluginStart } from '../../../../../../plugins/encrypted_saved_objects/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../plugins/features/server';
import { SpacesPluginStart } from '../../../../../../plugins/spaces/server';
import { SecurityPluginStart } from '../../../../../../plugins/security/server';

export interface FixtureSetupDeps {
features: FeaturesPluginSetup;
alerting: AlertingPluginSetup;
}

export interface FixtureStartDeps {
encryptedSavedObjects: EncryptedSavedObjectsPluginStart;
security?: SecurityPluginStart;
spaces?: SpacesPluginStart;
}

export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, FixtureStartDeps> {
constructor() {}

public setup(core: CoreSetup<FixtureStartDeps>, { features, alerting }: FixtureSetupDeps) {
features.registerKibanaFeature({
id: 'alertsFixture',
name: 'Alerts',
app: ['alerts', 'kibana'],
category: { id: 'foo', label: 'foo' },
alerting: ['test.executionContext'],
privileges: {
all: {
app: ['alerts', 'kibana'],
savedObject: {
all: ['alert'],
read: [],
},
alerting: {
rule: {
all: ['test.executionContext'],
},
},
ui: [],
},
read: {
app: ['alerts', 'kibana'],
savedObject: {
all: [],
read: ['alert'],
},
alerting: {
rule: {
read: ['test.executionContext'],
},
},
ui: [],
},
},
});

alerting.registerType({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin registers a custom alert. Test suit will create an instance of this alert.

id: 'test.executionContext',
name: 'Test: Query Elasticsearch server',
actionGroups: [
{
id: 'default',
name: 'Default',
},
],
producer: 'alertsFixture',
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
async executor() {
const [coreStart] = await core.getStartServices();
await coreStart.elasticsearch.client.asInternalUser.ping();
},
});
}

public start() {}
public stop() {}
}
13 changes: 13 additions & 0 deletions x-pack/test/functional_execution_context/ftr_provider_context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { GenericFtrProviderContext } from '@kbn/test';
import { pageObjects } from '../../test/functional/page_objects';
import { services } from './services';

export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;
export { pageObjects };
10 changes: 10 additions & 0 deletions x-pack/test/functional_execution_context/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { services as functionalServices } from '../../test/functional/services';

export const services = functionalServices;
52 changes: 52 additions & 0 deletions x-pack/test/functional_execution_context/test_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import Fs from 'fs/promises';
import Path from 'path';
import { isEqualWith } from 'lodash';
import type { Ecs, KibanaExecutionContext } from 'kibana/server';
import type { RetryService } from '../../../test/common/services/retry';

export const logFilePath = Path.resolve(__dirname, './kibana.log');
export const ANY = Symbol('any');

export function isExecutionContextLog(
record: string | undefined,
executionContext: KibanaExecutionContext
) {
if (!record) return false;
try {
const object = JSON.parse(record);
return isEqualWith(object, executionContext, function customizer(obj1: any, obj2: any) {
if (obj2 === ANY) return true;
});
} catch (e) {
return false;
}
}

// to avoid splitting log record containing \n symbol
const endOfLine = /(?<=})\s*\n/;
export async function assertLogContains({
description,
predicate,
retry,
}: {
description: string;
predicate: (record: Ecs) => boolean;
retry: RetryService;
}): Promise<void> {
// logs are written to disk asynchronously. I sacrificed performance to reduce flakiness.
await retry.waitFor(description, async () => {
const logsStr = await Fs.readFile(logFilePath, 'utf-8');
const normalizedRecords = logsStr
.split(endOfLine)
.filter(Boolean)
.map((s) => JSON.parse(s));

return normalizedRecords.some(predicate);
});
}
Loading