Skip to content

Commit fd4ef5f

Browse files
[8.6] [kbn-journeys] add optional beforeSteps hook (#151717) (#151917)
# Backport This will backport the following commits from `main` to `8.6`: - [[kbn-journeys] add optional beforeSteps hook (#151717)](#151717) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Dzmitry Lemechko","email":"dzmitry.lemechko@elastic.co"},"sourceCommit":{"committedDate":"2023-02-22T17:53:00Z","message":"[kbn-journeys] add optional beforeSteps hook (#151717)\n\n## Summary\r\n\r\nRelated to #151613\r\n\r\nThere might be cases when we need to add extra wait for Kibana plugin to\r\nbe ready before starting loading test data with `esArchiver` /\r\n`kbnArchiver`.\r\n\r\nCurrently journey lifecycle looks like this:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - in parallel \r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n- steps execution (each step wrapped with mocha `it` function)\r\n- `onTeardown` wrapped with mocha `after` hook\r\n - `tearDownBrowserAndPage` (including closing EBT tracker)\r\n - `teardownApm`\r\n - load ES data / Kibana saved objects\r\n\r\nbeforeSteps hook purpose is to make sure Kibana/ES state is ready for\r\njourney execution and not load test data, since it won't be unloaded\r\nduring `after` hook:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n- run beforeSteps hook -> prepare Kibana/ES for data ingestion / steps\r\nexecution\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n\r\nHow to use:\r\n\r\n```\r\nexport const journey = new Journey({\r\n beforeSteps: async ({ kibanaServer, retry }) => {\r\n retry.try(async () => {\r\n const response = await kibanaServer.request({\r\n path: '/internal/cloud_security_posture/status?check=init',\r\n method: 'GET',\r\n });\r\n return response.status === 200;\r\n });\r\n },\r\n esArchives: [...],\r\n kbnArchives: [...],\r\n})\r\n .step({...})\r\n .step({...})\r\n```","sha":"6c33644b5324df412acd71d2a6433e93c6e17904","branchLabelMapping":{"^v8.8.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","wg:performance","v8.7.0","v8.8.0","v8.6.3"],"number":151717,"url":"https://github.com/elastic/kibana/pull/151717","mergeCommit":{"message":"[kbn-journeys] add optional beforeSteps hook (#151717)\n\n## Summary\r\n\r\nRelated to #151613\r\n\r\nThere might be cases when we need to add extra wait for Kibana plugin to\r\nbe ready before starting loading test data with `esArchiver` /\r\n`kbnArchiver`.\r\n\r\nCurrently journey lifecycle looks like this:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - in parallel \r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n- steps execution (each step wrapped with mocha `it` function)\r\n- `onTeardown` wrapped with mocha `after` hook\r\n - `tearDownBrowserAndPage` (including closing EBT tracker)\r\n - `teardownApm`\r\n - load ES data / Kibana saved objects\r\n\r\nbeforeSteps hook purpose is to make sure Kibana/ES state is ready for\r\njourney execution and not load test data, since it won't be unloaded\r\nduring `after` hook:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n- run beforeSteps hook -> prepare Kibana/ES for data ingestion / steps\r\nexecution\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n\r\nHow to use:\r\n\r\n```\r\nexport const journey = new Journey({\r\n beforeSteps: async ({ kibanaServer, retry }) => {\r\n retry.try(async () => {\r\n const response = await kibanaServer.request({\r\n path: '/internal/cloud_security_posture/status?check=init',\r\n method: 'GET',\r\n });\r\n return response.status === 200;\r\n });\r\n },\r\n esArchives: [...],\r\n kbnArchives: [...],\r\n})\r\n .step({...})\r\n .step({...})\r\n```","sha":"6c33644b5324df412acd71d2a6433e93c6e17904"}},"sourceBranch":"main","suggestedTargetBranches":["8.7","8.6"],"targetPullRequestStates":[{"branch":"8.7","label":"v8.7.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.8.0","labelRegex":"^v8.8.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/151717","number":151717,"mergeCommit":{"message":"[kbn-journeys] add optional beforeSteps hook (#151717)\n\n## Summary\r\n\r\nRelated to #151613\r\n\r\nThere might be cases when we need to add extra wait for Kibana plugin to\r\nbe ready before starting loading test data with `esArchiver` /\r\n`kbnArchiver`.\r\n\r\nCurrently journey lifecycle looks like this:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - in parallel \r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n- steps execution (each step wrapped with mocha `it` function)\r\n- `onTeardown` wrapped with mocha `after` hook\r\n - `tearDownBrowserAndPage` (including closing EBT tracker)\r\n - `teardownApm`\r\n - load ES data / Kibana saved objects\r\n\r\nbeforeSteps hook purpose is to make sure Kibana/ES state is ready for\r\njourney execution and not load test data, since it won't be unloaded\r\nduring `after` hook:\r\n\r\n- `onSetup` wrapped with mocha `before` hook\r\n - `setupBrowserAndPage` (including EBT tracker setup)\r\n- run beforeSteps hook -> prepare Kibana/ES for data ingestion / steps\r\nexecution\r\n - load ES data / Kibana saved objects\r\n - `setupApm`\r\n\r\nHow to use:\r\n\r\n```\r\nexport const journey = new Journey({\r\n beforeSteps: async ({ kibanaServer, retry }) => {\r\n retry.try(async () => {\r\n const response = await kibanaServer.request({\r\n path: '/internal/cloud_security_posture/status?check=init',\r\n method: 'GET',\r\n });\r\n return response.status === 200;\r\n });\r\n },\r\n esArchives: [...],\r\n kbnArchives: [...],\r\n})\r\n .step({...})\r\n .step({...})\r\n```","sha":"6c33644b5324df412acd71d2a6433e93c6e17904"}},{"branch":"8.6","label":"v8.6.3","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>
1 parent cd1a7b7 commit fd4ef5f

3 files changed

Lines changed: 43 additions & 4 deletions

File tree

packages/kbn-journeys/journey/journey.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ import { Page } from 'playwright';
1212
import callsites from 'callsites';
1313
import { ToolingLog } from '@kbn/tooling-log';
1414
import { FtrConfigProvider } from '@kbn/test';
15-
import { FtrProviderContext, KibanaServer } from '@kbn/ftr-common-functional-services';
15+
import {
16+
FtrProviderContext,
17+
KibanaServer,
18+
Es,
19+
RetryService,
20+
} from '@kbn/ftr-common-functional-services';
1621

1722
import { Auth } from '../services/auth';
1823
import { InputDelays } from '../services/input_delays';
@@ -28,6 +33,8 @@ export interface BaseStepCtx {
2833
inputDelays: InputDelays;
2934
kbnUrl: KibanaUrl;
3035
kibanaServer: KibanaServer;
36+
es: Es;
37+
retry: RetryService;
3138
}
3239

3340
export type AnyStep = Step<{}>;
@@ -96,7 +103,16 @@ export class Journey<CtxExt extends object> {
96103

97104
/**
98105
* Define a step of this Journey. Steps are only separated from each other
99-
* to aid in reading/debuging the journey and reading it's logging output.
106+
* to aid in reading/debugging the journey and reading it's logging output.
107+
* These services might be helpful:
108+
*
109+
* page: methods to interact with a single tab in a browser
110+
*
111+
* kbnUrl: get the URL for a Kibana plugin
112+
*
113+
* kibanaServer: basic Kibana server client
114+
*
115+
* es: basic Elasticsearch client
100116
*
101117
* If a journey fails, a failure report will be created with a screenshot
102118
* at the point of failure as well as a screenshot at the end of every
@@ -119,6 +135,8 @@ export class Journey<CtxExt extends object> {
119135
getService('config'),
120136
getService('esArchiver'),
121137
getService('kibanaServer'),
138+
getService('es'),
139+
getService('retry'),
122140
new Auth(getService('config'), getService('log'), getService('kibanaServer')),
123141
this.config
124142
).initMochaSuite(this.#steps);

packages/kbn-journeys/journey/journey_config.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ export interface JourneyConfigOptions<CtxExt> {
9696
* be merged with the default context provided to each step function.
9797
*/
9898
extendContext?: (ctx: BaseStepCtx) => CtxExt;
99+
/**
100+
* Use this to define actions that will be executed after Kibana & ES were started,
101+
* but before archives are loaded. APM traces are not collected for this hook.
102+
*/
103+
beforeSteps?: (ctx: BaseStepCtx & CtxExt) => Promise<void>;
99104
}
100105

101106
export class JourneyConfig<CtxExt extends object> {
@@ -161,4 +166,12 @@ export class JourneyConfig<CtxExt extends object> {
161166
...ext(ctx),
162167
};
163168
}
169+
170+
async getBeforeStepsFn(ctx: BaseStepCtx & CtxExt) {
171+
if (this.#opts.beforeSteps) {
172+
await this.#opts.beforeSteps(ctx);
173+
} else {
174+
new Promise<void>((resolve) => resolve());
175+
}
176+
}
164177
}

packages/kbn-journeys/journey/journey_ftr_harness.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import playwright, { ChromiumBrowser, Page, BrowserContext, CDPSession, Request
1616
import { asyncMap, asyncForEach } from '@kbn/std';
1717
import { ToolingLog } from '@kbn/tooling-log';
1818
import { Config } from '@kbn/test';
19-
import { EsArchiver, KibanaServer } from '@kbn/ftr-common-functional-services';
19+
import { EsArchiver, KibanaServer, Es, RetryService } from '@kbn/ftr-common-functional-services';
2020

2121
import { Auth } from '../services/auth';
2222
import { getInputDelays } from '../services/input_delays';
@@ -34,6 +34,8 @@ export class JourneyFtrHarness {
3434
private readonly config: Config,
3535
private readonly esArchiver: EsArchiver,
3636
private readonly kibanaServer: KibanaServer,
37+
private readonly es: Es,
38+
private readonly retry: RetryService,
3739
private readonly auth: Auth,
3840
private readonly journeyConfig: JourneyConfig<any>
3941
) {
@@ -117,8 +119,12 @@ export class JourneyFtrHarness {
117119
}
118120

119121
private async onSetup() {
122+
// We start browser and init page in the first place
123+
await this.setupBrowserAndPage();
124+
// We allow opt-in beforeSteps hook to manage Kibana/ES state
125+
await this.journeyConfig.getBeforeStepsFn(this.getCtx());
126+
// Loading test data
120127
await Promise.all([
121-
this.setupBrowserAndPage(),
122128
asyncForEach(this.journeyConfig.getEsArchives(), async (esArchive) => {
123129
await this.esArchiver.load(esArchive);
124130
}),
@@ -365,6 +371,8 @@ export class JourneyFtrHarness {
365371
)
366372
),
367373
kibanaServer: this.kibanaServer,
374+
es: this.es,
375+
retry: this.retry,
368376
});
369377

370378
return this.#_ctx;

0 commit comments

Comments
 (0)