From f49593639714d4da6380ff38485c185c86d80157 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Wed, 10 Jul 2024 01:11:12 +0200 Subject: [PATCH 01/28] deployment agnostic slo burn rate rule tests --- .buildkite/ftr_configs.yml | 6 + .eslintrc.js | 2 + .../api_integration/services/alerting_api.ts | 46 +-- x-pack/test/api_integration/services/index.ts | 4 + .../test/api_integration/services/slo_api.ts | 283 ++++++++++++++++++ .../README.md | 80 +++++ .../config/ess/config.base.ts | 44 +++ .../config/serverless/config.base.ts | 39 +++ .../ftr_provider_context.d.ts | 9 + .../package.json | 17 ++ .../alerting/burn_rate}/burn_rate_rule.ts | 90 +++--- .../alerting/burn_rate/configs/ess.config.ts | 15 + .../burn_rate/configs/serverless.config.ts | 15 + .../test_suites/alerting/burn_rate/index.ts | 15 + .../tsconfig.json | 29 ++ x-pack/test/tsconfig.json | 3 +- .../api_integration/services/index.ts | 4 - .../api_integration/services/slo_api.ts | 213 ------------- .../test_suites/observability/index.ts | 1 - .../services/deployment_agnostic_services.ts | 2 + 20 files changed, 618 insertions(+), 299 deletions(-) rename x-pack/{test_serverless => test}/api_integration/services/alerting_api.ts (77%) create mode 100644 x-pack/test/api_integration/services/slo_api.ts create mode 100644 x-pack/test/observability_solution_api_integration/README.md create mode 100644 x-pack/test/observability_solution_api_integration/config/ess/config.base.ts create mode 100644 x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts create mode 100644 x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts create mode 100644 x-pack/test/observability_solution_api_integration/package.json rename x-pack/{test_serverless/api_integration/test_suites/observability/burn_rate_rule => test/observability_solution_api_integration/test_suites/alerting/burn_rate}/burn_rate_rule.ts (79%) create mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts create mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts create mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts create mode 100644 x-pack/test/observability_solution_api_integration/tsconfig.json delete mode 100644 x-pack/test_serverless/api_integration/services/slo_api.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index e0faadd77091c..4ad3c1aea3423 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -17,6 +17,8 @@ disabled: - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint_api_int/configs/config.base.ts - x-pack/test/security_solution_endpoint/config.base.ts - x-pack/test/security_solution_endpoint_api_int/config.base.ts + - x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts + - x-pack/test/observability_solution_api_integration/config/ess/config.base.ts # QA suites that are run out-of-band - x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js @@ -584,3 +586,7 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/serverless.endpoint.config.ts - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/integrations.config.ts - x-pack/test/security_solution_api_integration/test_suites/security_solution_endpoint/configs/serverless.integrations.config.ts + - x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts + - x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts + - x-pack/test/observability_solution_api_integration/test_suites/alerting/custom_threshold/configs/serverless.config.ts + - x-pack/test/observability_solution_api_integration/test_suites/alerting/custom_threshold/configs/ess.config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 853b1549d2b93..560bfc5a337f3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -629,6 +629,8 @@ module.exports = { 'x-pack/test/profiling_api_integration/**/*.ts', 'x-pack/test/security_solution_api_integration/*/test_suites/**/*', 'x-pack/test/security_solution_api_integration/**/config*.ts', + 'x-pack/test/observability_solution_api_integration/*/test_suites/**/*', + 'x-pack/test/observability_solution_api_integration/**/config*.ts', ], rules: { 'import/no-default-export': 'off', diff --git a/x-pack/test_serverless/api_integration/services/alerting_api.ts b/x-pack/test/api_integration/services/alerting_api.ts similarity index 77% rename from x-pack/test_serverless/api_integration/services/alerting_api.ts rename to x-pack/test/api_integration/services/alerting_api.ts index 6000e9d8bdc88..534d8bf156a87 100644 --- a/x-pack/test_serverless/api_integration/services/alerting_api.ts +++ b/x-pack/test/api_integration/services/alerting_api.ts @@ -12,26 +12,22 @@ import type { import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; -import { RoleCredentials } from '../../shared/services'; import { SloBurnRateRuleParams } from './slo_api'; import { FtrProviderContext } from '../ftr_provider_context'; export function AlertingApiProvider({ getService }: FtrProviderContext) { const retry = getService('retry'); + const supertest = getService('supertest'); const es = getService('es'); const requestTimeout = 30 * 1000; const retryTimeout = 120 * 1000; const logger = getService('log'); - const svlCommonApi = getService('svlCommonApi'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); return { async waitForRuleStatus({ - roleAuthc, ruleId, expectedStatus, }: { - roleAuthc: RoleCredentials; ruleId: string; expectedStatus: string; }) { @@ -39,10 +35,10 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { throw new Error(`'ruleId' is undefined`); } return await retry.tryForTime(retryTimeout, async () => { - const response = await supertestWithoutAuth + const response = await supertest .get(`/api/alerting/rule/${ruleId}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') .timeout(requestTimeout); const { execution_status: executionStatus } = response.body || {}; const { status } = executionStatus || {}; @@ -66,7 +62,7 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { rest_total_hits_as_int: true, }); logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); - if (!response.hits.total || (response.hits.total as number) < docCountTarget) { + if (!response.hits.total || response.hits.total < docCountTarget) { throw new Error('No hits found'); } return response; @@ -101,19 +97,11 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { }); }, - async createIndexConnector({ - roleAuthc, - name, - indexName, - }: { - roleAuthc: RoleCredentials; - name: string; - indexName: string; - }) { - const { body } = await supertestWithoutAuth + async createIndexConnector({ name, indexName }: { name: string; indexName: string }) { + const { body } = await supertest .post(`/api/actions/connector`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') .send({ name, config: { @@ -126,7 +114,6 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { }, async createRule({ - roleAuthc, name, ruleTypeId, params, @@ -135,7 +122,6 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { schedule, consumer, }: { - roleAuthc: RoleCredentials; ruleTypeId: string; name: string; params: MetricThresholdParams | ThresholdParams | SloBurnRateRuleParams; @@ -144,10 +130,10 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { schedule?: { interval: string }; consumer: string; }) { - const { body } = await supertestWithoutAuth + const { body } = await supertest .post(`/api/alerting/rule`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') .send({ params, consumer, @@ -162,14 +148,14 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { return body; }, - async findRule(roleAuthc: RoleCredentials, ruleId: string) { + async findRule(ruleId: string) { if (!ruleId) { throw new Error(`'ruleId' is undefined`); } - const response = await supertestWithoutAuth + const response = await supertest .get('/api/alerting/rules/_find') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); return response.body.data.find((obj: any) => obj.id === ruleId); }, }; diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 5d2508ee627c7..c07477425036d 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -24,6 +24,8 @@ import { IngestPipelinesProvider } from './ingest_pipelines'; import { IndexManagementProvider } from './index_management'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo'; +import { SloApiProvider as SloApiProviderNew } from './slo_api'; +import { AlertingApiProvider } from './alerting_api'; import { SecuritySolutionApiProvider } from './security_solution_api.gen'; export const services = { @@ -45,4 +47,6 @@ export const services = { indexManagement: IndexManagementProvider, slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, + alertingApi: AlertingApiProvider, + sloApi: SloApiProviderNew, // TODO: There was already an slo service here for the slo api tests. Unify SloApiProvider and SloApiProviderNew as part of the slo API migration issue https://github.com/elastic/kibana/issues/183397 }; diff --git a/x-pack/test/api_integration/services/slo_api.ts b/x-pack/test/api_integration/services/slo_api.ts new file mode 100644 index 0000000000000..e147e57361ab8 --- /dev/null +++ b/x-pack/test/api_integration/services/slo_api.ts @@ -0,0 +1,283 @@ +/* + * 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 { + fetchHistoricalSummaryParamsSchema, + FetchHistoricalSummaryResponse, +} from '@kbn/slo-schema'; +import * as t from 'io-ts'; +import { FtrProviderContext } from '../../functional/ftr_provider_context'; +import { RoleCredentials } from '../../../test_serverless/shared/services'; + +type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; + +interface Duration { + value: number; + unit: DurationUnit; +} + +interface WindowSchema { + id: string; + burnRateThreshold: number; + maxBurnRateThreshold: number; + longWindow: Duration; + shortWindow: Duration; + actionGroup: string; +} + +interface Dependency { + ruleId: string; + actionGroupsToSuppressOn: string[]; +} + +export interface SloBurnRateRuleParams { + sloId: string; + windows: WindowSchema[]; + dependencies?: Dependency[]; +} + +interface SloParams { + id?: string; + name: string; + description: string; + indicator: { + type: 'sli.kql.custom'; + params: { + index: string; + good: string; + total: string; + timestampField: string; + }; + }; + timeWindow: { + duration: string; + type: string; + }; + budgetingMethod: string; + objective: { + target: number; + }; + groupBy: string; +} + +type FetchHistoricalSummaryParams = t.OutputOf< + typeof fetchHistoricalSummaryParamsSchema.props.body +>; + +export function SloApiProvider({ getService }: FtrProviderContext) { + const es = getService('es'); + const supertest = getService('supertest'); + const retry = getService('retry'); + const config = getService('config'); + const isServerless = config.get('serverless'); + let svlUserManager; + if (isServerless) { + svlUserManager = getService('svlUserManager'); + } + + const requestTimeout = 30 * 1000; + const retryTimeout = 180 * 1000; + + return { + async create(slo: SloParams) { + let roleAuthc: RoleCredentials; + if (isServerless) { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + const { body } = await supertest + .post(`/api/observability/slos`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .send(slo); + + return body; + } else { + const { body } = await supertest + .post(`/api/observability/slos`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send(slo); + + return body; + } + }, + + async delete(sloId: string) { + let roleAuthc: RoleCredentials; + if (isServerless) { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader); + return response; + } else { + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + return response; + } + }, + + async fetchHistoricalSummary( + params: FetchHistoricalSummaryParams + ): Promise { + let roleAuthc: RoleCredentials; + if (isServerless) { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + const { body } = await supertest + .post(`/internal/observability/slos/_historical_summary`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .send(params); + + return body; + } else { + const { body } = await supertest + .post(`/internal/observability/slos/_historical_summary`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send(params); + + return body; + } + }, + + async waitForSloToBeDeleted(sloId: string) { + if (!sloId) { + throw new Error(`sloId is undefined`); + } + let roleAuthc: RoleCredentials; + + return await retry.tryForTime(retryTimeout, async () => { + if (isServerless) { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + if (!response.ok) { + throw new Error(`slodId [${sloId}] was not deleted`); + } + return response; + } else { + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .timeout(requestTimeout); + if (!response.ok) { + throw new Error(`slodId [${sloId}] was not deleted`); + } + return response; + } + }); + }, + + async waitForSloCreated({ sloId }: { sloId: string }) { + if (!sloId) { + throw new Error(`'sloId is undefined`); + } + let roleAuthc: RoleCredentials; + + return await retry.tryForTime(retryTimeout, async () => { + if (isServerless) { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + const response = await supertest + .get(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + if (response.body.id === undefined) { + throw new Error(`No slo with id ${sloId} found`); + } + return response.body; + } else { + const response = await supertest + .get(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .timeout(requestTimeout); + if (response.body.id === undefined) { + throw new Error(`No slo with id ${sloId} found`); + } + return response.body; + } + }); + }, + + async waitForSloSummaryTempIndexToExist(index: string) { + if (!index) { + throw new Error(`index is undefined`); + } + + return await retry.tryForTime(retryTimeout, async () => { + const indexExists = await es.indices.exists({ index, allow_no_indices: false }); + if (!indexExists) { + throw new Error(`index ${index} should exist`); + } + return indexExists; + }); + }, + + async getSloData({ sloId, indexName }: { sloId: string; indexName: string }) { + const response = await es.search({ + index: indexName, + body: { + query: { + bool: { + filter: [{ term: { 'slo.id': sloId } }], + }, + }, + }, + }); + return response; + }, + async waitForSloData({ sloId, indexName }: { sloId: string; indexName: string }) { + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + body: { + query: { + bool: { + filter: [{ term: { 'slo.id': sloId } }], + }, + }, + }, + }); + if (response.hits.hits.length === 0) { + throw new Error(`No hits found at index [${indexName}] for slo [${sloId}] `); + } + return response; + }); + }, + async deleteAllSLOs() { + const response = await supertest + .get(`/api/observability/slos/_definitions`) + .set('kbn-xsrf', 'true') + .set('x-elastic-internal-origin', 'foo') + .send() + .expect(200); + await Promise.all( + response.body.results.map(({ id }: { id: string }) => { + return supertest + .delete(`/api/observability/slos/${id}`) + .set('kbn-xsrf', 'true') + .set('x-elastic-internal-origin', 'foo') + .send() + .expect(204); + }) + ); + }, + }; +} diff --git a/x-pack/test/observability_solution_api_integration/README.md b/x-pack/test/observability_solution_api_integration/README.md new file mode 100644 index 0000000000000..dd67f033cc184 --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/README.md @@ -0,0 +1,80 @@ +# observability_solution_api_integration + +This directory serves as a centralized location to place the observability solution tests that run in Serverless and ESS environments + +## Subdirectories + +1. `config` stores base configurations specific to both the Serverless and ESS environments. These configurations build upon the base configuration provided by `x-pack/test_serverless` and `x-pack/test/api_integration`, incorporating additional settings such as environmental variables and tagging options + +2. `test_suites` directory houses all the tests along with the utility functions. + +## Overview + +- In this directory suiteTags is utilized to assign tags to specific test suites. This tagging system enables the ability to selectively apply tags to test suites, facilitating the exclusion of specific test suite as needed. + +- Test suites are prefixed with specific tags to determine their execution in particular environments or to exclude them from specific environments. + +- We are using the following tags: + * `@ess`: Runs in an ESS environment (on-prem installation) as part of the CI validation on PRs. + + * `@serverless`: Runs in the first quality gate and in the periodic pipeline. + + * `@skipInEss`: Skipped for ESS environment. + + * `@skipInServerless`: Skipped for all quality gates, CI and periodic pipeline. + +ex: +``` +describe('SLO - Burn rate rule', function () { + this.tags(['ess', 'serverless']); // tests in this suite will run in both Ess and Serverless +} + +describe('SLO - Burn rate rule', function () { + this.tags(['skipInServerless']); // tests in this suite will be excluded in Serverless +} +``` + +# Adding new observabiluty area's tests + +1. Within the `test_suites` directory, create a new area folder, for example slos, rules, apm etc +2. Introduce `ess.config` and `serverless.config` files to reference the new test files and incorporate any additional custom properties defined in the `CreateTestConfigOptions` interface. +3. In these new configuration files, include references to the base configurations located under the config directory to inherit CI configurations, environment variables, and other settings. +4. Append a new entry in the `ftr_configs.yml` file to enable the execution of the newly added tests within the CI pipeline. + + +# Testing locally + +In the `package.json` file, you'll find commands to configure the server for each environment and to run tests against that specific environment. These commands adhere to the Mocha tagging system, allowing for the inclusion and exclusion of tags, mirroring the setup of the CI pipeline. + +# How to run +You can run various commands with different parameters for the different test worflows. + +The command structure follows this pattern: + +- ``: The test workflow you want to run. +- ``: The type of operation, either "server" or "runner." +- ``: The testing environment, such as "serverless," or "ess", specifies the correct configuration file for the tests. + +Run the server for "alerting_burn_rate" in the "serverless" environment: + +```shell +npm run alerting_burn_rate:server:serverless +``` + +Run tests for "alerting_burn_rate" in the "serverless" environment: + +```shell +npm run alerting_burn_rate:runner:serverless +``` + +Run the server for "alerting_burn_rate" in the "ess" environment: + +```shell +npm run alerting_burn_rate:server:ess +``` + +Run tests for "alerting_burn_rate" in the "ess" environment: + +```shell +npm run alerting_burn_rate:runner:ess +``` \ No newline at end of file diff --git a/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts b/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts new file mode 100644 index 0000000000000..345aa1bf2259a --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts @@ -0,0 +1,44 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; +import { services } from '../../../api_integration/services'; + +export interface CreateTestConfigOptions { + testFiles: string[]; + junit: { reportName: string }; + publicBaseUrl?: boolean; +} + +export function createTestConfig(options: CreateTestConfigOptions) { + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const xPackApiIntegrationTestsConfig = await readConfigFile( + require.resolve('../../../api_integration/config.ts') + ); + + return { + ...xPackApiIntegrationTestsConfig.getAll(), + testFiles: options.testFiles, + services: { + ...services, + }, + junit: { + reportName: 'X-Pack Οbservability Solution API Integration Tests', + }, + suiteTags: { + include: ['serverless'], + exclude: ['skipInServerless'], + }, + kbnTestServer: { + ...xPackApiIntegrationTestsConfig.get('kbnTestServer'), + serverArgs: [ + ...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'), + ...(options.publicBaseUrl ? ['--server.publicBaseUrl=http://localhost:5620'] : []), + ], + }, + }; + }; +} diff --git a/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts b/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts new file mode 100644 index 0000000000000..31f9ae386d170 --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts @@ -0,0 +1,39 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; +import { services } from '../../../../test_serverless/api_integration/services'; + +export interface CreateTestConfigOptions { + testFiles: string[]; + junit: { reportName: string }; +} + +export function createTestConfig(options: CreateTestConfigOptions) { + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const svlSharedConfig = await readConfigFile( + require.resolve('../../../../test_serverless/shared/config.base.ts') + ); + + return { + ...svlSharedConfig.getAll(), + services: { + ...services, + }, + kbnTestServer: { + ...svlSharedConfig.get('kbnTestServer'), + serverArgs: [...svlSharedConfig.get('kbnTestServer.serverArgs'), `--serverless=oblt`], + }, + testFiles: options.testFiles, + junit: options.junit, + suiteTags: { + include: ['ess'], + exclude: ['skipInEss'], + }, + }; + }; +} diff --git a/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts b/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..ed7c5216c803c --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts @@ -0,0 +1,9 @@ +/* + * 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 type { FtrProviderContext } from '../api_integration/ftr_provider_context'; + +export type { FtrProviderContext }; diff --git a/x-pack/test/observability_solution_api_integration/package.json b/x-pack/test/observability_solution_api_integration/package.json new file mode 100644 index 0000000000000..713a729590462 --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/package.json @@ -0,0 +1,17 @@ +{ + "author": "Elastic", + "name": "@kbn/observability_solution_api_integration", + "version": "1.0.0", + "private": true, + "license": "Elastic License 2.0", + "scripts": { + "alerting_burn_rate:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/burn_rate/configs/serverless.config.ts", + "alerting_burn_rate:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/burn_rate/configs/serverless.config.ts", + "alerting_burn_rate:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/burn_rate/configs/ess.config.ts", + "alerting_burn_rate:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/burn_rate/configs/ess.config.ts", + "alerting_custom_threshold:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/custom_threshold/configs/serverless.config.ts", + "alerting_custom_threshold:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/custom_threshold/configs/serverless.config.ts", + "alerting_custom_threshold:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/custom_threshold/configs/ess.config.ts", + "alerting_custom_threshold:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/custom_threshold/configs/ess.config.ts" + } +} \ No newline at end of file diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts similarity index 79% rename from x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts rename to x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts index 1d5dd1de80a9f..c4eb815db5c98 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts +++ b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts @@ -4,17 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -/* - * 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 { cleanup, Dataset, generate, PartialConfig } from '@kbn/data-forge'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); @@ -24,10 +17,9 @@ export default function ({ getService }: FtrProviderContext) { const alertingApi = getService('alertingApi'); const dataViewApi = getService('dataViewApi'); const sloApi = getService('sloApi'); - const svlUserManager = getService('svlUserManager'); - const svlCommonApi = getService('svlCommonApi'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; + const config = getService('config'); + const isServerless = config.get('serverless'); + const expectedConsumer = isServerless ? 'observability' : 'slo'; describe('Burn rate rule', () => { const RULE_TYPE_ID = 'slo.rules.burnRate'; @@ -42,8 +34,6 @@ export default function ({ getService }: FtrProviderContext) { let ruleId: string; before(async () => { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); dataForgeConfig = { schedule: [ { @@ -66,12 +56,17 @@ export default function ({ getService }: FtrProviderContext) { id: DATA_VIEW_ID, title: DATA_VIEW, }); - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); }); after(async () => { - await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader); - await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader); + await supertest + .delete(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + await supertest + .delete(`/api/actions/connector/${actionId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); await esClient.deleteByQuery({ index: '.kibana-event-log-*', query: { term: { 'rule.id': ruleId } }, @@ -80,52 +75,49 @@ export default function ({ getService }: FtrProviderContext) { await dataViewApi.delete({ id: DATA_VIEW_ID, }); - await supertest.delete('/api/observability/slos/my-custom-id').set(internalReqHeader); + await supertest + .delete('/api/observability/slos/my-custom-id') + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); await esDeleteAllIndices([ALERT_ACTION_INDEX, ...dataForgeIndices]); await cleanup({ client: esClient, config: dataForgeConfig, logger }); - await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); describe('Rule creation', () => { it('creates rule successfully', async () => { actionId = await alertingApi.createIndexConnector({ - roleAuthc, name: 'Index Connector: Slo Burn rate API test', indexName: ALERT_ACTION_INDEX, }); - await sloApi.create( - { - id: 'my-custom-id', - name: 'my custom name', - description: 'my custom description', - indicator: { - type: 'sli.kql.custom', - params: { - index: DATA_VIEW, - good: 'system.cpu.total.norm.pct > 1', - total: 'system.cpu.total.norm.pct: *', - timestampField: '@timestamp', - }, - }, - timeWindow: { - duration: '7d', - type: 'rolling', + await sloApi.create({ + id: 'my-custom-id', + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: DATA_VIEW, + good: 'system.cpu.total.norm.pct > 1', + total: 'system.cpu.total.norm.pct: *', + timestampField: '@timestamp', }, - budgetingMethod: 'occurrences', - objective: { - target: 0.999, - }, - groupBy: '*', }, - roleAuthc - ); + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'occurrences', + objective: { + target: 0.999, + }, + groupBy: '*', + }); const dependencyRule = await alertingApi.createRule({ - roleAuthc, tags: ['observability'], - consumer: 'observability', + consumer: expectedConsumer, name: 'SLO Burn Rate rule - Dependency', ruleTypeId: RULE_TYPE_ID, schedule: { @@ -196,9 +188,8 @@ export default function ({ getService }: FtrProviderContext) { }); const createdRule = await alertingApi.createRule({ - roleAuthc, tags: ['observability'], - consumer: 'observability', + consumer: expectedConsumer, name: 'SLO Burn Rate rule', ruleTypeId: RULE_TYPE_ID, schedule: { @@ -279,7 +270,6 @@ export default function ({ getService }: FtrProviderContext) { it('should be active', async () => { const executionStatus = await alertingApi.waitForRuleStatus({ - roleAuthc, ruleId, expectedStatus: 'active', }); @@ -299,9 +289,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should find the created rule with correct information about the consumer', async () => { - const match = await alertingApi.findRule(roleAuthc, ruleId); + const match = await alertingApi.findRule(ruleId); expect(match).not.to.be(undefined); - expect(match.consumer).to.be('observability'); + expect(match.consumer).to.be(expectedConsumer); }); }); }); diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts new file mode 100644 index 0000000000000..faeda1a68fc2e --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts @@ -0,0 +1,15 @@ +/* + * 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 { createTestConfig } from '../../../../config/ess/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'SLO - Burn rate Integration Tests - ESS Env', + }, +}); diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts new file mode 100644 index 0000000000000..21bbb8b63b009 --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts @@ -0,0 +1,15 @@ +/* + * 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 { createTestConfig } from '../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'SLO - Burn rate Integration Tests - Serverless Env', + }, +}); diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts new file mode 100644 index 0000000000000..a4fc8b21753bd --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Slo - Burn rate rule', function () { + this.tags(['ess', 'serverless']); + loadTestFile(require.resolve('./burn_rate_rule')); + }); +} diff --git a/x-pack/test/observability_solution_api_integration/tsconfig.json b/x-pack/test/observability_solution_api_integration/tsconfig.json new file mode 100644 index 0000000000000..183117c4f1336 --- /dev/null +++ b/x-pack/test/observability_solution_api_integration/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["node", "jest","@kbn/ambient-ftr-types"] + }, + "include": [ + "**/*", + "../../../typings/**/*", + "../../../packages/kbn-test/types/ftr_globals/**/*", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + { "path": "../../test_serverless/tsconfig.json" }, + { "path": "../../test_serverless/api_integration/**/*" }, + { "path": "../../test_serverless/shared/**/*" }, + { "path": "../../api_integration/services/**/*" }, + "@kbn/test", + "@kbn/expect", + "@kbn/data-forge", + "@kbn/observability-plugin", + "@kbn/rule-data-utils", + "@kbn/share-plugin", + "@kbn/es-query", + "@kbn/utility-types", + ] +} \ No newline at end of file diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index cda6e59087262..1f91a4c0c7b6e 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -27,7 +27,8 @@ "*/plugins/**/*", "*/packages/**/*", "*/*/packages/**/*", - "security_solution_api_integration/**/*" + "security_solution_api_integration/**/*", + "observability_solution_api_integration/**/*" ], "kbn_references": [ { diff --git a/x-pack/test_serverless/api_integration/services/index.ts b/x-pack/test_serverless/api_integration/services/index.ts index 347fc1f68b0ca..c14a836f79c0b 100644 --- a/x-pack/test_serverless/api_integration/services/index.ts +++ b/x-pack/test_serverless/api_integration/services/index.ts @@ -9,10 +9,8 @@ import { GenericFtrProviderContext } from '@kbn/test'; import { services as deploymentAgnosticSharedServices } from '../../shared/services/deployment_agnostic_services'; import { services as svlSharedServices } from '../../shared/services'; -import { AlertingApiProvider } from './alerting_api'; import { SamlToolsProvider } from './saml_tools'; import { SvlCasesServiceProvider } from './svl_cases'; -import { SloApiProvider } from './slo_api'; import { TransformProvider } from './transform'; import { SvlEnrichPoliciesApi } from './index_management/svl_enrich_policies.api'; @@ -35,10 +33,8 @@ export const services = { // serverless FTR services ...svlSharedServices, - alertingApi: AlertingApiProvider, samlTools: SamlToolsProvider, svlCases: SvlCasesServiceProvider, - sloApi: SloApiProvider, transform: TransformProvider, synthtrace: SynthtraceProvider, svlEnrichPoliciesApi: SvlEnrichPoliciesApi, diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts deleted file mode 100644 index 96b7f9e518f31..0000000000000 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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 { - fetchHistoricalSummaryParamsSchema, - FetchHistoricalSummaryResponse, -} from '@kbn/slo-schema'; -import * as t from 'io-ts'; -import type { RoleCredentials } from '../../shared/services'; -import { FtrProviderContext } from '../ftr_provider_context'; - -type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; - -interface Duration { - value: number; - unit: DurationUnit; -} - -interface WindowSchema { - id: string; - burnRateThreshold: number; - maxBurnRateThreshold: number; - longWindow: Duration; - shortWindow: Duration; - actionGroup: string; -} - -interface Dependency { - ruleId: string; - actionGroupsToSuppressOn: string[]; -} - -export interface SloBurnRateRuleParams { - sloId: string; - windows: WindowSchema[]; - dependencies?: Dependency[]; -} - -interface SloParams { - id?: string; - name: string; - description: string; - indicator: { - type: 'sli.kql.custom'; - params: { - index: string; - good: string; - total: string; - timestampField: string; - }; - }; - timeWindow: { - duration: string; - type: string; - }; - budgetingMethod: string; - objective: { - target: number; - }; - groupBy: string; -} - -type FetchHistoricalSummaryParams = t.OutputOf< - typeof fetchHistoricalSummaryParamsSchema.props.body ->; - -export function SloApiProvider({ getService }: FtrProviderContext) { - const es = getService('es'); - const supertest = getService('supertest'); - const svlCommonApi = getService('svlCommonApi'); - const retry = getService('retry'); - const requestTimeout = 30 * 1000; - const retryTimeout = 180 * 1000; - - return { - async create(slo: SloParams, roleAuthc: RoleCredentials) { - const { body } = await supertest - .post(`/api/observability/slos`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .send(slo); - - return body; - }, - - async delete({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); - return response; - }, - - async fetchHistoricalSummary( - params: FetchHistoricalSummaryParams, - roleAuthc: RoleCredentials - ): Promise { - const { body } = await supertest - .post(`/internal/observability/slos/_historical_summary`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .send(params); - - return body; - }, - - async waitForSloToBeDeleted({ - sloId, - roleAuthc, - }: { - sloId: string; - roleAuthc: RoleCredentials; - }) { - if (!sloId) { - throw new Error(`sloId is undefined`); - } - return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .timeout(requestTimeout); - if (!response.ok) { - throw new Error(`slodId [${sloId}] was not deleted`); - } - return response; - }); - }, - - async waitForSloCreated({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { - if (!sloId) { - throw new Error(`'sloId is undefined`); - } - return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest - .get(`/api/observability/slos/${sloId}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .timeout(requestTimeout); - if (response.body.id === undefined) { - throw new Error(`No slo with id ${sloId} found`); - } - return response.body; - }); - }, - - async waitForSloSummaryTempIndexToExist(index: string) { - if (!index) { - throw new Error(`index is undefined`); - } - - return await retry.tryForTime(retryTimeout, async () => { - const indexExists = await es.indices.exists({ index, allow_no_indices: false }); - if (!indexExists) { - throw new Error(`index ${index} should exist`); - } - return indexExists; - }); - }, - - async getSloData({ sloId, indexName }: { sloId: string; indexName: string }) { - const response = await es.search({ - index: indexName, - body: { - query: { - bool: { - filter: [{ term: { 'slo.id': sloId } }], - }, - }, - }, - }); - return response; - }, - async waitForSloData({ sloId, indexName }: { sloId: string; indexName: string }) { - return await retry.tryForTime(retryTimeout, async () => { - const response = await es.search({ - index: indexName, - body: { - query: { - bool: { - filter: [{ term: { 'slo.id': sloId } }], - }, - }, - }, - }); - if (response.hits.hits.length === 0) { - throw new Error(`No hits found at index [${indexName}] for slo [${sloId}] `); - } - return response; - }); - }, - async deleteAllSLOs() { - const response = await supertest - .get(`/api/observability/slos/_definitions`) - .set(svlCommonApi.getInternalRequestHeader()) - .send() - .expect(200); - await Promise.all( - response.body.results.map(({ id }: { id: string }) => { - return supertest - .delete(`/api/observability/slos/${id}`) - .set(svlCommonApi.getInternalRequestHeader()) - .send() - .expect(204); - }) - ); - }, - }; -} diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/index.ts index c3e9bddc4e95c..a138c768d43d4 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/index.ts @@ -15,7 +15,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./apm_api_integration/service_maps/service_maps')); loadTestFile(require.resolve('./apm_api_integration/traces/critical_path')); loadTestFile(require.resolve('./cases')); - loadTestFile(require.resolve('./burn_rate_rule/burn_rate_rule')); loadTestFile(require.resolve('./es_query_rule/es_query_rule')); loadTestFile(require.resolve('./slos')); loadTestFile(require.resolve('./synthetics')); diff --git a/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts b/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts index 34e6b7d5facd5..f846d6bf2ede5 100644 --- a/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts +++ b/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts @@ -30,6 +30,8 @@ const deploymentAgnosticApiIntegrationServices = _.pick(apiIntegrationServices, 'usageAPI', 'console', 'securitySolutionApi', + 'alertingApi', + 'sloApi', ]); export const services = { From 647e38b212013dfe77671a0b4f94bdc06f6418f5 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 12 Aug 2024 16:17:57 -0400 Subject: [PATCH 02/28] add burn rate tests to agnostic api test directory --- .../observability/alerting}/burn_rate_rule.ts | 68 +++++--- .../apis/observability/alerting/index.ts | 15 ++ .../deployment_agnostic/oblt.index.ts | 1 + .../oblt.stateful.config.ts | 16 ++ .../services/alerting_api.ts | 160 ++++++++++++++++++ .../deployment_agnostic/services/index.ts | 4 + 6 files changed, 238 insertions(+), 26 deletions(-) rename x-pack/test/{observability_solution_api_integration/test_suites/alerting/burn_rate => api_integration/deployment_agnostic/apis/observability/alerting}/burn_rate_rule.ts (86%) create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts similarity index 86% rename from x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index 51f8fcafd4442..49c0f5d8f12c1 100644 --- a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -33,9 +33,14 @@ export default function ({ getService }: FtrProviderContext) { let actionId: string; let ruleId: string; + const samlAuth = getService('samlAuth'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalHeaders: InternalRequestHeader; + before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); + roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin'); + internalHeaders = samlAuth.getInternalRequestHeader(); dataForgeConfig = { schedule: [ { @@ -52,23 +57,29 @@ export default function ({ getService }: FtrProviderContext) { indexing: { dataset: 'fake_hosts' as Dataset, eventsPerCycle: 1, interval: 10000 }, }; dataForgeIndices = await generate({ client: esClient, config: dataForgeConfig, logger }); - await alertingApi.waitForDocumentInIndex({ indexName: DATA_VIEW, docCountTarget: 360 }); + await alertingApi.waitForDocumentInIndex({ + indexName: DATA_VIEW, + docCountTarget: 360, + roleAuthc, + }); await dataViewApi.create({ + roleAuthc, name: DATA_VIEW, id: DATA_VIEW_ID, title: DATA_VIEW, }); - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); }); after(async () => { await supertest .delete(`/api/alerting/rule/${ruleId}`) + .set(roleAuthc.apiKeyHeader) .set('kbn-xsrf', 'foo') .set('x-elastic-internal-origin', 'foo'); await supertest .delete(`/api/actions/connector/${actionId}`) .set('kbn-xsrf', 'foo') + .set(roleAuthc.apiKeyHeader) .set('x-elastic-internal-origin', 'foo'); await esClient.deleteByQuery({ index: '.kibana-event-log-*', @@ -76,6 +87,7 @@ export default function ({ getService }: FtrProviderContext) { conflicts: 'proceed', }); await dataViewApi.delete({ + roleAuthc, id: DATA_VIEW_ID, }); await supertest @@ -85,7 +97,7 @@ export default function ({ getService }: FtrProviderContext) { await esDeleteAllIndices([ALERT_ACTION_INDEX, ...dataForgeIndices]); await cleanup({ client: esClient, config: dataForgeConfig, logger }); - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); describe('Rule creation', () => { @@ -95,29 +107,32 @@ export default function ({ getService }: FtrProviderContext) { indexName: ALERT_ACTION_INDEX, }); - await sloApi.create({ - id: 'my-custom-id', - name: 'my custom name', - description: 'my custom description', - indicator: { - type: 'sli.kql.custom', - params: { - index: DATA_VIEW, - good: 'system.cpu.total.norm.pct > 1', - total: 'system.cpu.total.norm.pct: *', - timestampField: '@timestamp', + await sloApi.create( + { + id: 'my-custom-id', + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: DATA_VIEW, + good: 'system.cpu.total.norm.pct > 1', + total: 'system.cpu.total.norm.pct: *', + timestampField: '@timestamp', + }, }, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'occurrences', + objective: { + target: 0.999, + }, + groupBy: '*', }, - timeWindow: { - duration: '7d', - type: 'rolling', - }, - budgetingMethod: 'occurrences', - objective: { - target: 0.999, - }, - groupBy: '*', - }); + roleAuthc + ); const dependencyRule = await alertingApi.createRule({ tags: ['observability'], @@ -274,6 +289,7 @@ export default function ({ getService }: FtrProviderContext) { it('should be active', async () => { const executionStatus = await alertingApi.waitForRuleStatus({ + roleAuthc, ruleId, expectedStatus: 'active', }); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts new file mode 100644 index 0000000000000..a4fc8b21753bd --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Slo - Burn rate rule', function () { + this.tags(['ess', 'serverless']); + loadTestFile(require.resolve('./burn_rate_rule')); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts b/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts index d81415e0554dd..78885e470fce0 100644 --- a/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts @@ -11,5 +11,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) loadTestFile(require.resolve('./apis/console')); loadTestFile(require.resolve('./apis/core')); loadTestFile(require.resolve('./apis/painless_lab')); + loadTestFile(require.resolve('./apis/observability/alerting')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts b/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts new file mode 100644 index 0000000000000..bbad5fb8c70d7 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts @@ -0,0 +1,16 @@ +/* + * 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 { createStatefulTestConfig } from './default_configs/stateful.config.base'; + +export default createStatefulTestConfig({ + serverlessProject: 'oblt', + testFiles: [require.resolve('./oblt.index.ts')], + junit: { + reportName: 'Stateful Observability - Deployment-agnostic API Integration Tests', + }, +}); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts new file mode 100644 index 0000000000000..7862164f65605 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -0,0 +1,160 @@ +/* + * 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 { RoleCredentials } from '@kbn/ftr-common-functional-services'; +import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; + +export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { + const retry = getService('retry'); + const supertest = getService('supertest'); + const es = getService('es'); + const requestTimeout = 30 * 1000; + const retryTimeout = 120 * 1000; + const logger = getService('log'); + + return { + async waitForRuleStatus({ + ruleId, + expectedStatus, + roleAuthc, + }: { + ruleId: string; + expectedStatus: string; + roleAuthc: RoleCredentials; + }) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .get(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + const { execution_status: executionStatus } = response.body || {}; + const { status } = executionStatus || {}; + if (status !== expectedStatus) { + throw new Error(`waitForStatus(${expectedStatus}): got ${status}`); + } + return executionStatus?.status; + }); + }, + + async waitForDocumentInIndex({ + indexName, + docCountTarget = 1, + roleAuthc, + }: { + indexName: string; + docCountTarget?: number; + roleAuthc: RoleCredentials; + }): Promise>> { + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + rest_total_hits_as_int: true, + }); + logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); + if (!response.hits.total || response.hits.total < docCountTarget) { + throw new Error('No hits found'); + } + return response; + }); + }, + + async waitForAlertInIndex({ + indexName, + ruleId, + }: { + indexName: string; + ruleId: string; + }): Promise>> { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + body: { + query: { + term: { + 'kibana.alert.rule.uuid': ruleId, + }, + }, + }, + }); + if (response.hits.hits.length === 0) { + throw new Error('No hits found'); + } + return response; + }); + }, + + async createIndexConnector({ name, indexName }: { name: string; indexName: string }) { + const { body } = await supertest + .post(`/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send({ + name, + config: { + index: indexName, + refresh: true, + }, + connector_type_id: '.index', + }); + return body.id as string; + }, + + async createRule({ + name, + ruleTypeId, + params, + actions = [], + tags = [], + schedule, + consumer, + }: { + ruleTypeId: string; + name: string; + params: MetricThresholdParams | ThresholdParams | SloBurnRateRuleParams; + actions?: any[]; + tags?: any[]; + schedule?: { interval: string }; + consumer: string; + }) { + const { body } = await supertest + .post(`/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send({ + params, + consumer, + schedule: schedule || { + interval: '5m', + }, + tags, + name, + rule_type_id: ruleTypeId, + actions, + }); + return body; + }, + + async findRule(ruleId: string) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + const response = await supertest + .get('/api/alerting/rules/_find') + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + return response.body.data.find((obj: any) => obj.id === ruleId); + }, + }; +} diff --git a/x-pack/test/api_integration/deployment_agnostic/services/index.ts b/x-pack/test/api_integration/deployment_agnostic/services/index.ts index fcb767cdb2436..270665edcf139 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/index.ts @@ -9,6 +9,8 @@ import { commonFunctionalServices } from '@kbn/ftr-common-functional-services'; import { deploymentAgnosticServices } from './deployment_agnostic_services'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo_api'; +import { AlertingApiProvider } from './alerting_api'; +import { services as commonServices } from '../../../common/services'; export type { InternalRequestHeader, @@ -17,7 +19,9 @@ export type { } from '@kbn/ftr-common-functional-services'; export const services = { + ...commonServices, ...deploymentAgnosticServices, + alertingApi: AlertingApiProvider, supertestWithoutAuth: commonFunctionalServices.supertestWithoutAuth, samlAuth: commonFunctionalServices.samlAuth, dataViewApi: DataViewApiProvider, From 4876a317fe838a55ebd2a048078b9776d8a10ff3 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 12 Aug 2024 16:24:18 -0400 Subject: [PATCH 03/28] add builtkite config --- .buildkite/ftr_oblt_stateful_configs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/ftr_oblt_stateful_configs.yml b/.buildkite/ftr_oblt_stateful_configs.yml index 55f3c1b603fca..43f1032458e24 100644 --- a/.buildkite/ftr_oblt_stateful_configs.yml +++ b/.buildkite/ftr_oblt_stateful_configs.yml @@ -49,3 +49,5 @@ enabled: - x-pack/test/observability_ai_assistant_functional/enterprise/config.ts - x-pack/test/profiling_api_integration/cloud/config.ts - x-pack/test/functional/apps/apm/config.ts + # Stateful configs that run deployment-agnostic tests + - x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts From 2ee040b66762427288cf062c2ca39082e857bc28 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 12 Aug 2024 16:24:37 -0400 Subject: [PATCH 04/28] remove unused directory --- .../README.md | 80 ------------------- .../config/ess/config.base.ts | 44 ---------- .../config/serverless/config.base.ts | 39 --------- .../ftr_provider_context.d.ts | 9 --- .../package.json | 17 ---- .../alerting/burn_rate/configs/ess.config.ts | 15 ---- .../burn_rate/configs/serverless.config.ts | 15 ---- .../test_suites/alerting/burn_rate/index.ts | 15 ---- .../tsconfig.json | 29 ------- 9 files changed, 263 deletions(-) delete mode 100644 x-pack/test/observability_solution_api_integration/README.md delete mode 100644 x-pack/test/observability_solution_api_integration/config/ess/config.base.ts delete mode 100644 x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts delete mode 100644 x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts delete mode 100644 x-pack/test/observability_solution_api_integration/package.json delete mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts delete mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts delete mode 100644 x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts delete mode 100644 x-pack/test/observability_solution_api_integration/tsconfig.json diff --git a/x-pack/test/observability_solution_api_integration/README.md b/x-pack/test/observability_solution_api_integration/README.md deleted file mode 100644 index dd67f033cc184..0000000000000 --- a/x-pack/test/observability_solution_api_integration/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# observability_solution_api_integration - -This directory serves as a centralized location to place the observability solution tests that run in Serverless and ESS environments - -## Subdirectories - -1. `config` stores base configurations specific to both the Serverless and ESS environments. These configurations build upon the base configuration provided by `x-pack/test_serverless` and `x-pack/test/api_integration`, incorporating additional settings such as environmental variables and tagging options - -2. `test_suites` directory houses all the tests along with the utility functions. - -## Overview - -- In this directory suiteTags is utilized to assign tags to specific test suites. This tagging system enables the ability to selectively apply tags to test suites, facilitating the exclusion of specific test suite as needed. - -- Test suites are prefixed with specific tags to determine their execution in particular environments or to exclude them from specific environments. - -- We are using the following tags: - * `@ess`: Runs in an ESS environment (on-prem installation) as part of the CI validation on PRs. - - * `@serverless`: Runs in the first quality gate and in the periodic pipeline. - - * `@skipInEss`: Skipped for ESS environment. - - * `@skipInServerless`: Skipped for all quality gates, CI and periodic pipeline. - -ex: -``` -describe('SLO - Burn rate rule', function () { - this.tags(['ess', 'serverless']); // tests in this suite will run in both Ess and Serverless -} - -describe('SLO - Burn rate rule', function () { - this.tags(['skipInServerless']); // tests in this suite will be excluded in Serverless -} -``` - -# Adding new observabiluty area's tests - -1. Within the `test_suites` directory, create a new area folder, for example slos, rules, apm etc -2. Introduce `ess.config` and `serverless.config` files to reference the new test files and incorporate any additional custom properties defined in the `CreateTestConfigOptions` interface. -3. In these new configuration files, include references to the base configurations located under the config directory to inherit CI configurations, environment variables, and other settings. -4. Append a new entry in the `ftr_configs.yml` file to enable the execution of the newly added tests within the CI pipeline. - - -# Testing locally - -In the `package.json` file, you'll find commands to configure the server for each environment and to run tests against that specific environment. These commands adhere to the Mocha tagging system, allowing for the inclusion and exclusion of tags, mirroring the setup of the CI pipeline. - -# How to run -You can run various commands with different parameters for the different test worflows. - -The command structure follows this pattern: - -- ``: The test workflow you want to run. -- ``: The type of operation, either "server" or "runner." -- ``: The testing environment, such as "serverless," or "ess", specifies the correct configuration file for the tests. - -Run the server for "alerting_burn_rate" in the "serverless" environment: - -```shell -npm run alerting_burn_rate:server:serverless -``` - -Run tests for "alerting_burn_rate" in the "serverless" environment: - -```shell -npm run alerting_burn_rate:runner:serverless -``` - -Run the server for "alerting_burn_rate" in the "ess" environment: - -```shell -npm run alerting_burn_rate:server:ess -``` - -Run tests for "alerting_burn_rate" in the "ess" environment: - -```shell -npm run alerting_burn_rate:runner:ess -``` \ No newline at end of file diff --git a/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts b/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts deleted file mode 100644 index 345aa1bf2259a..0000000000000 --- a/x-pack/test/observability_solution_api_integration/config/ess/config.base.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 { FtrConfigProviderContext } from '@kbn/test'; -import { services } from '../../../api_integration/services'; - -export interface CreateTestConfigOptions { - testFiles: string[]; - junit: { reportName: string }; - publicBaseUrl?: boolean; -} - -export function createTestConfig(options: CreateTestConfigOptions) { - return async ({ readConfigFile }: FtrConfigProviderContext) => { - const xPackApiIntegrationTestsConfig = await readConfigFile( - require.resolve('../../../api_integration/config.ts') - ); - - return { - ...xPackApiIntegrationTestsConfig.getAll(), - testFiles: options.testFiles, - services: { - ...services, - }, - junit: { - reportName: 'X-Pack Οbservability Solution API Integration Tests', - }, - suiteTags: { - include: ['serverless'], - exclude: ['skipInServerless'], - }, - kbnTestServer: { - ...xPackApiIntegrationTestsConfig.get('kbnTestServer'), - serverArgs: [ - ...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'), - ...(options.publicBaseUrl ? ['--server.publicBaseUrl=http://localhost:5620'] : []), - ], - }, - }; - }; -} diff --git a/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts b/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts deleted file mode 100644 index 31f9ae386d170..0000000000000 --- a/x-pack/test/observability_solution_api_integration/config/serverless/config.base.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 { FtrConfigProviderContext } from '@kbn/test'; -import { services } from '../../../../test_serverless/api_integration/services'; - -export interface CreateTestConfigOptions { - testFiles: string[]; - junit: { reportName: string }; -} - -export function createTestConfig(options: CreateTestConfigOptions) { - return async ({ readConfigFile }: FtrConfigProviderContext) => { - const svlSharedConfig = await readConfigFile( - require.resolve('../../../../test_serverless/shared/config.base.ts') - ); - - return { - ...svlSharedConfig.getAll(), - services: { - ...services, - }, - kbnTestServer: { - ...svlSharedConfig.get('kbnTestServer'), - serverArgs: [...svlSharedConfig.get('kbnTestServer.serverArgs'), `--serverless=oblt`], - }, - testFiles: options.testFiles, - junit: options.junit, - suiteTags: { - include: ['ess'], - exclude: ['skipInEss'], - }, - }; - }; -} diff --git a/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts b/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts deleted file mode 100644 index ed7c5216c803c..0000000000000 --- a/x-pack/test/observability_solution_api_integration/ftr_provider_context.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 type { FtrProviderContext } from '../api_integration/ftr_provider_context'; - -export type { FtrProviderContext }; diff --git a/x-pack/test/observability_solution_api_integration/package.json b/x-pack/test/observability_solution_api_integration/package.json deleted file mode 100644 index 713a729590462..0000000000000 --- a/x-pack/test/observability_solution_api_integration/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "author": "Elastic", - "name": "@kbn/observability_solution_api_integration", - "version": "1.0.0", - "private": true, - "license": "Elastic License 2.0", - "scripts": { - "alerting_burn_rate:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/burn_rate/configs/serverless.config.ts", - "alerting_burn_rate:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/burn_rate/configs/serverless.config.ts", - "alerting_burn_rate:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/burn_rate/configs/ess.config.ts", - "alerting_burn_rate:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/burn_rate/configs/ess.config.ts", - "alerting_custom_threshold:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/custom_threshold/configs/serverless.config.ts", - "alerting_custom_threshold:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/custom_threshold/configs/serverless.config.ts", - "alerting_custom_threshold:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/alerting/custom_threshold/configs/ess.config.ts", - "alerting_custom_threshold:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/alerting/custom_threshold/configs/ess.config.ts" - } -} \ No newline at end of file diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts deleted file mode 100644 index faeda1a68fc2e..0000000000000 --- a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/ess.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 { createTestConfig } from '../../../../config/ess/config.base'; - -export default createTestConfig({ - testFiles: [require.resolve('..')], - junit: { - reportName: 'SLO - Burn rate Integration Tests - ESS Env', - }, -}); diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts deleted file mode 100644 index 21bbb8b63b009..0000000000000 --- a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/configs/serverless.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 { createTestConfig } from '../../../../config/serverless/config.base'; - -export default createTestConfig({ - testFiles: [require.resolve('..')], - junit: { - reportName: 'SLO - Burn rate Integration Tests - Serverless Env', - }, -}); diff --git a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts b/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts deleted file mode 100644 index a4fc8b21753bd..0000000000000 --- a/x-pack/test/observability_solution_api_integration/test_suites/alerting/burn_rate/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('Slo - Burn rate rule', function () { - this.tags(['ess', 'serverless']); - loadTestFile(require.resolve('./burn_rate_rule')); - }); -} diff --git a/x-pack/test/observability_solution_api_integration/tsconfig.json b/x-pack/test/observability_solution_api_integration/tsconfig.json deleted file mode 100644 index 183117c4f1336..0000000000000 --- a/x-pack/test/observability_solution_api_integration/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": ["node", "jest","@kbn/ambient-ftr-types"] - }, - "include": [ - "**/*", - "../../../typings/**/*", - "../../../packages/kbn-test/types/ftr_globals/**/*", - ], - "exclude": [ - "target/**/*" - ], - "kbn_references": [ - { "path": "../../test_serverless/tsconfig.json" }, - { "path": "../../test_serverless/api_integration/**/*" }, - { "path": "../../test_serverless/shared/**/*" }, - { "path": "../../api_integration/services/**/*" }, - "@kbn/test", - "@kbn/expect", - "@kbn/data-forge", - "@kbn/observability-plugin", - "@kbn/rule-data-utils", - "@kbn/share-plugin", - "@kbn/es-query", - "@kbn/utility-types", - ] -} \ No newline at end of file From f28913a2b8e852c276d9a58c0768619070a90273 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 12 Aug 2024 16:29:22 -0400 Subject: [PATCH 05/28] update codeowners --- .github/CODEOWNERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6c4f63d4cde00..51d2caefe7259 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1133,7 +1133,9 @@ x-pack/test/observability_ai_assistant_functional @elastic/obs-ai-assistant /x-pack/test_serverless/**/test_suites/observability/custom_threshold_rule/ @elastic/obs-ux-management-team /x-pack/test_serverless/**/test_suites/observability/slos/ @elastic/obs-ux-management-team /x-pack/test_serverless/api_integration/test_suites/observability/es_query_rule @elastic/obs-ux-management-team -/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule @elastic/obs-ux-management-team +/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule @elastic/obs-ux-management-team +/x-pack/test/api_integration/deployment_agnostic/services/alerting_api @elastic/obs-ux-management-team +/x-pack/test/api_integration/deployment_agnostic/services/slo_api @elastic/obs-ux-management-team /x-pack/test_serverless/**/test_suites/observability/infra/ @elastic/obs-ux-infra_services-team # Elastic Stack Monitoring From fb4d5535a0c81f54f64d92a580c0c1b13164f227 Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Mon, 12 Aug 2024 16:51:19 -0400 Subject: [PATCH 06/28] adjust alerting api --- .../services/alerting_api.ts | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 7862164f65605..ec0ab48b6f32f 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -32,9 +32,8 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide return await retry.tryForTime(retryTimeout, async () => { const response = await supertest .get(`/api/alerting/rule/${ruleId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') .set(roleAuthc.apiKeyHeader) + .set(roleAuthc.getInternalRequestHeader()) .timeout(requestTimeout); const { execution_status: executionStatus } = response.body || {}; const { status } = executionStatus || {}; @@ -95,11 +94,19 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide }); }, - async createIndexConnector({ name, indexName }: { name: string; indexName: string }) { + async createIndexConnector({ + name, + indexName, + roleAuthc, + }: { + name: string; + indexName: string; + roleAuthC: RoleCredentials; + }) { const { body } = await supertest .post(`/api/actions/connector`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .set(roleAuthC.getInternalRequestHeader()) .send({ name, config: { @@ -119,6 +126,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide tags = [], schedule, consumer, + roleAuthc, }: { ruleTypeId: string; name: string; @@ -127,11 +135,12 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide tags?: any[]; schedule?: { interval: string }; consumer: string; + roleAuthc: RoleCredentials; }) { const { body } = await supertest .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') + .set(roleAuthc.apiKeyHeader) + .set(roleAuthC.getInternalRequestHeader()) .send({ params, consumer, @@ -146,14 +155,14 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide return body; }, - async findRule(ruleId: string) { + async findRule(ruleId: string, roleAuthc: RoleCredentials) { if (!ruleId) { throw new Error(`'ruleId' is undefined`); } const response = await supertest .get('/api/alerting/rules/_find') - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo'); + .set(roleAuthc.apiKeyHeader) + .set(roleAuthC.getInternalRequestHeader()); return response.body.data.find((obj: any) => obj.id === ruleId); }, }; From f1d7143ce0d8245e42e65f5fa0edfd37be8a2ab3 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Aug 2024 08:24:28 -0400 Subject: [PATCH 07/28] Update x-pack/test/api_integration/services/index.ts --- x-pack/test/api_integration/services/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 5993a44b2018f..349f640f33ee6 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -45,5 +45,5 @@ export const services = { slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, alertingApi: AlertingApiProvider, - sloApi: SloApiProviderNew, // TODO: There was already an slo service here for the slo api tests. Unify SloApiProvider and SloApiProviderNew as part of the slo API migration issue https://github.com/elastic/kibana/issues/183397 + sloApi: SloApiProviderNew }; From 7d70b1af3234399456b3843a2262886e18d9bd6f Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Aug 2024 08:30:19 -0400 Subject: [PATCH 08/28] sUpdate x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts --- .../api_integration/deployment_agnostic/oblt.stateful.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts b/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts index bbad5fb8c70d7..2f39fce8d1858 100644 --- a/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts +++ b/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts @@ -8,7 +8,6 @@ import { createStatefulTestConfig } from './default_configs/stateful.config.base'; export default createStatefulTestConfig({ - serverlessProject: 'oblt', testFiles: [require.resolve('./oblt.index.ts')], junit: { reportName: 'Stateful Observability - Deployment-agnostic API Integration Tests', From 390ebb6f48e286d86815d7c23c6fba46bc066cad Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Aug 2024 08:31:22 -0400 Subject: [PATCH 09/28] Update .eslintrc.js --- .eslintrc.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index d8a7472df4dfb..2b8c6c819bb3e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -629,8 +629,6 @@ module.exports = { 'x-pack/test/profiling_api_integration/**/*.ts', 'x-pack/test/security_solution_api_integration/*/test_suites/**/*', 'x-pack/test/security_solution_api_integration/**/config*.ts', - 'x-pack/test/observability_solution_api_integration/*/test_suites/**/*', - 'x-pack/test/observability_solution_api_integration/**/config*.ts', ], rules: { 'import/no-default-export': 'off', From ad1215620b15ce1987483b2077a617277bd130d6 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:28:12 +0000 Subject: [PATCH 10/28] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- x-pack/test/api_integration/services/index.ts | 2 +- x-pack/test/api_integration/services/slo_api.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 349f640f33ee6..f1e63c4196a1c 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -45,5 +45,5 @@ export const services = { slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, alertingApi: AlertingApiProvider, - sloApi: SloApiProviderNew + sloApi: SloApiProviderNew, }; diff --git a/x-pack/test/api_integration/services/slo_api.ts b/x-pack/test/api_integration/services/slo_api.ts index e147e57361ab8..51b64173407ca 100644 --- a/x-pack/test/api_integration/services/slo_api.ts +++ b/x-pack/test/api_integration/services/slo_api.ts @@ -10,8 +10,8 @@ import { FetchHistoricalSummaryResponse, } from '@kbn/slo-schema'; import * as t from 'io-ts'; +import { RoleCredentials } from '@kbn/test-suites-serverless/shared/services'; import { FtrProviderContext } from '../../functional/ftr_provider_context'; -import { RoleCredentials } from '../../../test_serverless/shared/services'; type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; From c02f861a8812125e7d7d5cab827e6f43093460ef Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:39:06 +0000 Subject: [PATCH 11/28] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/test/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 41bf815ae047a..cd0e161d0fdb0 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -178,6 +178,7 @@ "@kbn/entities-schema", "@kbn/actions-simulators-plugin", "@kbn/cases-api-integration-test-plugin", - "@kbn/mock-idp-utils" + "@kbn/mock-idp-utils", + "@kbn/test-suites-serverless" ] } From 145ed27ca82e1f2cd52fc230c3d7fed5bdd5d61a Mon Sep 17 00:00:00 2001 From: Dominique Belcher Date: Tue, 13 Aug 2024 10:02:11 -0400 Subject: [PATCH 12/28] adjust tests --- .../apis/observability/alerting/burn_rate_rule.ts | 5 ++++- .../deployment_agnostic/services/alerting_api.ts | 11 ++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index 49c0f5d8f12c1..81595b70b15cc 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -103,6 +103,7 @@ export default function ({ getService }: FtrProviderContext) { describe('Rule creation', () => { it('creates rule successfully', async () => { actionId = await alertingApi.createIndexConnector({ + roleAuthc, name: 'Index Connector: Slo Burn rate API test', indexName: ALERT_ACTION_INDEX, }); @@ -135,6 +136,7 @@ export default function ({ getService }: FtrProviderContext) { ); const dependencyRule = await alertingApi.createRule({ + roleAuthc, tags: ['observability'], consumer: expectedConsumer, name: 'SLO Burn Rate rule - Dependency', @@ -207,6 +209,7 @@ export default function ({ getService }: FtrProviderContext) { }); const createdRule = await alertingApi.createRule({ + roleAuthc, tags: ['observability'], consumer: expectedConsumer, name: 'SLO Burn Rate rule', @@ -309,7 +312,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should find the created rule with correct information about the consumer', async () => { - const match = await alertingApi.findRule(ruleId); + const match = await alertingApi.findRule(ruleId, roleAuthc); expect(match).not.to.be(undefined); expect(match.consumer).to.be(expectedConsumer); }); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index ec0ab48b6f32f..9d367e82982e6 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -10,6 +10,7 @@ import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { const retry = getService('retry'); + const samlAuth = getService('samlAuth'); const supertest = getService('supertest'); const es = getService('es'); const requestTimeout = 30 * 1000; @@ -33,7 +34,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide const response = await supertest .get(`/api/alerting/rule/${ruleId}`) .set(roleAuthc.apiKeyHeader) - .set(roleAuthc.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .timeout(requestTimeout); const { execution_status: executionStatus } = response.body || {}; const { status } = executionStatus || {}; @@ -101,12 +102,12 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide }: { name: string; indexName: string; - roleAuthC: RoleCredentials; + roleAuthc: RoleCredentials; }) { const { body } = await supertest .post(`/api/actions/connector`) .set(roleAuthc.apiKeyHeader) - .set(roleAuthC.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .send({ name, config: { @@ -140,7 +141,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide const { body } = await supertest .post(`/api/alerting/rule`) .set(roleAuthc.apiKeyHeader) - .set(roleAuthC.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .send({ params, consumer, @@ -162,7 +163,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide const response = await supertest .get('/api/alerting/rules/_find') .set(roleAuthc.apiKeyHeader) - .set(roleAuthC.getInternalRequestHeader()); + .set(samlAuth.getInternalRequestHeader()); return response.body.data.find((obj: any) => obj.id === ruleId); }, }; From 6ee3000c28209ae05d54512d429b0403b812a941 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 15:09:44 +0200 Subject: [PATCH 13/28] update service and test --- .../observability/alerting/burn_rate_rule.ts | 51 ++++++++----------- .../services/alerting_api.ts | 13 ++--- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index 81595b70b15cc..32332c70d6081 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -11,8 +11,9 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); - const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); + const samlAuth = getService('samlAuth'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const logger = getService('log'); const alertingApi = getService('alertingApi'); const dataViewApi = getService('dataViewApi'); @@ -25,21 +26,17 @@ export default function ({ getService }: FtrProviderContext) { const RULE_TYPE_ID = 'slo.rules.burnRate'; const DATA_VIEW = 'kbn-data-forge-fake_hosts.fake_hosts-*'; const RULE_ALERT_INDEX = '.alerts-observability.slo.alerts-default'; - const ALERT_ACTION_INDEX = 'alert-action-slo'; const DATA_VIEW_ID = 'data-view-id'; let dataForgeConfig: PartialConfig; let dataForgeIndices: string[]; let actionId: string; let ruleId: string; - - const samlAuth = getService('samlAuth'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + let adminRoleAuthc: RoleCredentials; let internalHeaders: InternalRequestHeader; before(async () => { - roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin'); + adminRoleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin'); internalHeaders = samlAuth.getInternalRequestHeader(); dataForgeConfig = { schedule: [ @@ -60,10 +57,10 @@ export default function ({ getService }: FtrProviderContext) { await alertingApi.waitForDocumentInIndex({ indexName: DATA_VIEW, docCountTarget: 360, - roleAuthc, + roleAuthc: adminRoleAuthc, }); await dataViewApi.create({ - roleAuthc, + roleAuthc: adminRoleAuthc, name: DATA_VIEW, id: DATA_VIEW_ID, title: DATA_VIEW, @@ -71,39 +68,35 @@ export default function ({ getService }: FtrProviderContext) { }); after(async () => { - await supertest + await supertestWithoutAuth .delete(`/api/alerting/rule/${ruleId}`) - .set(roleAuthc.apiKeyHeader) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo'); - await supertest + .set(adminRoleAuthc.apiKeyHeader) + .set(internalHeaders); + await supertestWithoutAuth .delete(`/api/actions/connector/${actionId}`) - .set('kbn-xsrf', 'foo') - .set(roleAuthc.apiKeyHeader) - .set('x-elastic-internal-origin', 'foo'); + .set(adminRoleAuthc.apiKeyHeader) + .set(internalHeaders); await esClient.deleteByQuery({ index: '.kibana-event-log-*', query: { term: { 'rule.id': ruleId } }, conflicts: 'proceed', }); await dataViewApi.delete({ - roleAuthc, + roleAuthc: adminRoleAuthc, id: DATA_VIEW_ID, }); - await supertest + await supertestWithoutAuth .delete('/api/observability/slos/my-custom-id') - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo'); - + .set(internalHeaders); await esDeleteAllIndices([ALERT_ACTION_INDEX, ...dataForgeIndices]); await cleanup({ client: esClient, config: dataForgeConfig, logger }); - await samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await samlAuth.invalidateM2mApiKeyWithRoleScope(adminRoleAuthc); }); describe('Rule creation', () => { it('creates rule successfully', async () => { actionId = await alertingApi.createIndexConnector({ - roleAuthc, + roleAuthc: adminRoleAuthc, name: 'Index Connector: Slo Burn rate API test', indexName: ALERT_ACTION_INDEX, }); @@ -132,11 +125,11 @@ export default function ({ getService }: FtrProviderContext) { }, groupBy: '*', }, - roleAuthc + adminRoleAuthc ); const dependencyRule = await alertingApi.createRule({ - roleAuthc, + roleAuthc: adminRoleAuthc, tags: ['observability'], consumer: expectedConsumer, name: 'SLO Burn Rate rule - Dependency', @@ -209,7 +202,7 @@ export default function ({ getService }: FtrProviderContext) { }); const createdRule = await alertingApi.createRule({ - roleAuthc, + roleAuthc: adminRoleAuthc, tags: ['observability'], consumer: expectedConsumer, name: 'SLO Burn Rate rule', @@ -292,7 +285,7 @@ export default function ({ getService }: FtrProviderContext) { it('should be active', async () => { const executionStatus = await alertingApi.waitForRuleStatus({ - roleAuthc, + roleAuthc: adminRoleAuthc, ruleId, expectedStatus: 'active', }); @@ -312,7 +305,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should find the created rule with correct information about the consumer', async () => { - const match = await alertingApi.findRule(ruleId, roleAuthc); + const match = await alertingApi.findRule(ruleId, adminRoleAuthc); expect(match).not.to.be(undefined); expect(match.consumer).to.be(expectedConsumer); }); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 9d367e82982e6..c2b6c3b9394c7 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -11,10 +11,11 @@ import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { const retry = getService('retry'); const samlAuth = getService('samlAuth'); - const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const es = getService('es'); + const config = getService('config'); + const retryTimeout = config.get('timeouts.try'); const requestTimeout = 30 * 1000; - const retryTimeout = 120 * 1000; const logger = getService('log'); return { @@ -31,7 +32,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide throw new Error(`'ruleId' is undefined`); } return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest + const response = await supertestWithoutAuth .get(`/api/alerting/rule/${ruleId}`) .set(roleAuthc.apiKeyHeader) .set(samlAuth.getInternalRequestHeader()) @@ -104,7 +105,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide indexName: string; roleAuthc: RoleCredentials; }) { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/api/actions/connector`) .set(roleAuthc.apiKeyHeader) .set(samlAuth.getInternalRequestHeader()) @@ -138,7 +139,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide consumer: string; roleAuthc: RoleCredentials; }) { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/api/alerting/rule`) .set(roleAuthc.apiKeyHeader) .set(samlAuth.getInternalRequestHeader()) @@ -160,7 +161,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide if (!ruleId) { throw new Error(`'ruleId' is undefined`); } - const response = await supertest + const response = await supertestWithoutAuth .get('/api/alerting/rules/_find') .set(roleAuthc.apiKeyHeader) .set(samlAuth.getInternalRequestHeader()); From 34fc89c4d1662376bb96b2d184aff39d15965c68 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 16:09:04 +0200 Subject: [PATCH 14/28] avoid loading stateful services --- .../services/deployment_agnostic_services.ts | 1 + .../api_integration/deployment_agnostic/services/index.ts | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/deployment_agnostic_services.ts b/x-pack/test/api_integration/deployment_agnostic/services/deployment_agnostic_services.ts index 38222c096bed0..9623df1bebbd0 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/deployment_agnostic_services.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/deployment_agnostic_services.ts @@ -15,6 +15,7 @@ import { services as apiIntegrationServices } from '../../services'; export const deploymentAgnosticServices = _.pick(apiIntegrationServices, [ 'supertest', // TODO: review its behaviour 'es', + 'esDeleteAllIndices', // TODO: review its behaviour 'esArchiver', 'esSupertest', // TODO: review its behaviour 'indexPatterns', diff --git a/x-pack/test/api_integration/deployment_agnostic/services/index.ts b/x-pack/test/api_integration/deployment_agnostic/services/index.ts index 270665edcf139..0fc0528675520 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/index.ts @@ -10,7 +10,6 @@ import { deploymentAgnosticServices } from './deployment_agnostic_services'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo_api'; import { AlertingApiProvider } from './alerting_api'; -import { services as commonServices } from '../../../common/services'; export type { InternalRequestHeader, @@ -19,11 +18,10 @@ export type { } from '@kbn/ftr-common-functional-services'; export const services = { - ...commonServices, ...deploymentAgnosticServices, - alertingApi: AlertingApiProvider, supertestWithoutAuth: commonFunctionalServices.supertestWithoutAuth, samlAuth: commonFunctionalServices.samlAuth, + alertingApi: AlertingApiProvider, dataViewApi: DataViewApiProvider, sloApi: SloApiProvider, // create a new deployment-agnostic service and load here From 770101b4d4a32d430531a3aa8588f3408154262b Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 16:30:28 +0200 Subject: [PATCH 15/28] remove duplicated service --- x-pack/test/api_integration/services/index.ts | 2 - .../test/api_integration/services/slo_api.ts | 283 ------------------ 2 files changed, 285 deletions(-) delete mode 100644 x-pack/test/api_integration/services/slo_api.ts diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index f1e63c4196a1c..f516f1e22a7f7 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -22,7 +22,6 @@ import { IngestPipelinesProvider } from './ingest_pipelines'; import { IndexManagementProvider } from './index_management'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo'; -import { SloApiProvider as SloApiProviderNew } from './slo_api'; import { AlertingApiProvider } from './alerting_api'; import { SecuritySolutionApiProvider } from './security_solution_api.gen'; @@ -45,5 +44,4 @@ export const services = { slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, alertingApi: AlertingApiProvider, - sloApi: SloApiProviderNew, }; diff --git a/x-pack/test/api_integration/services/slo_api.ts b/x-pack/test/api_integration/services/slo_api.ts deleted file mode 100644 index 51b64173407ca..0000000000000 --- a/x-pack/test/api_integration/services/slo_api.ts +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 { - fetchHistoricalSummaryParamsSchema, - FetchHistoricalSummaryResponse, -} from '@kbn/slo-schema'; -import * as t from 'io-ts'; -import { RoleCredentials } from '@kbn/test-suites-serverless/shared/services'; -import { FtrProviderContext } from '../../functional/ftr_provider_context'; - -type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; - -interface Duration { - value: number; - unit: DurationUnit; -} - -interface WindowSchema { - id: string; - burnRateThreshold: number; - maxBurnRateThreshold: number; - longWindow: Duration; - shortWindow: Duration; - actionGroup: string; -} - -interface Dependency { - ruleId: string; - actionGroupsToSuppressOn: string[]; -} - -export interface SloBurnRateRuleParams { - sloId: string; - windows: WindowSchema[]; - dependencies?: Dependency[]; -} - -interface SloParams { - id?: string; - name: string; - description: string; - indicator: { - type: 'sli.kql.custom'; - params: { - index: string; - good: string; - total: string; - timestampField: string; - }; - }; - timeWindow: { - duration: string; - type: string; - }; - budgetingMethod: string; - objective: { - target: number; - }; - groupBy: string; -} - -type FetchHistoricalSummaryParams = t.OutputOf< - typeof fetchHistoricalSummaryParamsSchema.props.body ->; - -export function SloApiProvider({ getService }: FtrProviderContext) { - const es = getService('es'); - const supertest = getService('supertest'); - const retry = getService('retry'); - const config = getService('config'); - const isServerless = config.get('serverless'); - let svlUserManager; - if (isServerless) { - svlUserManager = getService('svlUserManager'); - } - - const requestTimeout = 30 * 1000; - const retryTimeout = 180 * 1000; - - return { - async create(slo: SloParams) { - let roleAuthc: RoleCredentials; - if (isServerless) { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - const { body } = await supertest - .post(`/api/observability/slos`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .set(roleAuthc.apiKeyHeader) - .send(slo); - - return body; - } else { - const { body } = await supertest - .post(`/api/observability/slos`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .send(slo); - - return body; - } - }, - - async delete(sloId: string) { - let roleAuthc: RoleCredentials; - if (isServerless) { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .set(roleAuthc.apiKeyHeader); - return response; - } else { - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo'); - return response; - } - }, - - async fetchHistoricalSummary( - params: FetchHistoricalSummaryParams - ): Promise { - let roleAuthc: RoleCredentials; - if (isServerless) { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - const { body } = await supertest - .post(`/internal/observability/slos/_historical_summary`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .set(roleAuthc.apiKeyHeader) - .send(params); - - return body; - } else { - const { body } = await supertest - .post(`/internal/observability/slos/_historical_summary`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .send(params); - - return body; - } - }, - - async waitForSloToBeDeleted(sloId: string) { - if (!sloId) { - throw new Error(`sloId is undefined`); - } - let roleAuthc: RoleCredentials; - - return await retry.tryForTime(retryTimeout, async () => { - if (isServerless) { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .set(roleAuthc.apiKeyHeader) - .timeout(requestTimeout); - if (!response.ok) { - throw new Error(`slodId [${sloId}] was not deleted`); - } - return response; - } else { - const response = await supertest - .delete(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .timeout(requestTimeout); - if (!response.ok) { - throw new Error(`slodId [${sloId}] was not deleted`); - } - return response; - } - }); - }, - - async waitForSloCreated({ sloId }: { sloId: string }) { - if (!sloId) { - throw new Error(`'sloId is undefined`); - } - let roleAuthc: RoleCredentials; - - return await retry.tryForTime(retryTimeout, async () => { - if (isServerless) { - roleAuthc = await svlUserManager.createApiKeyForRole('admin'); - const response = await supertest - .get(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .set(roleAuthc.apiKeyHeader) - .timeout(requestTimeout); - if (response.body.id === undefined) { - throw new Error(`No slo with id ${sloId} found`); - } - return response.body; - } else { - const response = await supertest - .get(`/api/observability/slos/${sloId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .timeout(requestTimeout); - if (response.body.id === undefined) { - throw new Error(`No slo with id ${sloId} found`); - } - return response.body; - } - }); - }, - - async waitForSloSummaryTempIndexToExist(index: string) { - if (!index) { - throw new Error(`index is undefined`); - } - - return await retry.tryForTime(retryTimeout, async () => { - const indexExists = await es.indices.exists({ index, allow_no_indices: false }); - if (!indexExists) { - throw new Error(`index ${index} should exist`); - } - return indexExists; - }); - }, - - async getSloData({ sloId, indexName }: { sloId: string; indexName: string }) { - const response = await es.search({ - index: indexName, - body: { - query: { - bool: { - filter: [{ term: { 'slo.id': sloId } }], - }, - }, - }, - }); - return response; - }, - async waitForSloData({ sloId, indexName }: { sloId: string; indexName: string }) { - return await retry.tryForTime(retryTimeout, async () => { - const response = await es.search({ - index: indexName, - body: { - query: { - bool: { - filter: [{ term: { 'slo.id': sloId } }], - }, - }, - }, - }); - if (response.hits.hits.length === 0) { - throw new Error(`No hits found at index [${indexName}] for slo [${sloId}] `); - } - return response; - }); - }, - async deleteAllSLOs() { - const response = await supertest - .get(`/api/observability/slos/_definitions`) - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send() - .expect(200); - await Promise.all( - response.body.results.map(({ id }: { id: string }) => { - return supertest - .delete(`/api/observability/slos/${id}`) - .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') - .send() - .expect(204); - }) - ); - }, - }; -} From 9356c2a1897a991535ef68735e7ce5e9112b9903 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 16:39:19 +0200 Subject: [PATCH 16/28] remove unused alerting_api service --- .../api_integration/services/alerting_api.ts | 162 ------------------ x-pack/test/api_integration/services/index.ts | 2 - 2 files changed, 164 deletions(-) delete mode 100644 x-pack/test/api_integration/services/alerting_api.ts diff --git a/x-pack/test/api_integration/services/alerting_api.ts b/x-pack/test/api_integration/services/alerting_api.ts deleted file mode 100644 index 534d8bf156a87..0000000000000 --- a/x-pack/test/api_integration/services/alerting_api.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 type { - AggregationsAggregate, - SearchResponse, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - -import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; -import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; -import { SloBurnRateRuleParams } from './slo_api'; -import { FtrProviderContext } from '../ftr_provider_context'; - -export function AlertingApiProvider({ getService }: FtrProviderContext) { - const retry = getService('retry'); - const supertest = getService('supertest'); - const es = getService('es'); - const requestTimeout = 30 * 1000; - const retryTimeout = 120 * 1000; - const logger = getService('log'); - - return { - async waitForRuleStatus({ - ruleId, - expectedStatus, - }: { - ruleId: string; - expectedStatus: string; - }) { - if (!ruleId) { - throw new Error(`'ruleId' is undefined`); - } - return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest - .get(`/api/alerting/rule/${ruleId}`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .timeout(requestTimeout); - const { execution_status: executionStatus } = response.body || {}; - const { status } = executionStatus || {}; - if (status !== expectedStatus) { - throw new Error(`waitForStatus(${expectedStatus}): got ${status}`); - } - return executionStatus?.status; - }); - }, - - async waitForDocumentInIndex({ - indexName, - docCountTarget = 1, - }: { - indexName: string; - docCountTarget?: number; - }): Promise>> { - return await retry.tryForTime(retryTimeout, async () => { - const response = await es.search({ - index: indexName, - rest_total_hits_as_int: true, - }); - logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); - if (!response.hits.total || response.hits.total < docCountTarget) { - throw new Error('No hits found'); - } - return response; - }); - }, - - async waitForAlertInIndex({ - indexName, - ruleId, - }: { - indexName: string; - ruleId: string; - }): Promise>> { - if (!ruleId) { - throw new Error(`'ruleId' is undefined`); - } - return await retry.tryForTime(retryTimeout, async () => { - const response = await es.search({ - index: indexName, - body: { - query: { - term: { - 'kibana.alert.rule.uuid': ruleId, - }, - }, - }, - }); - if (response.hits.hits.length === 0) { - throw new Error('No hits found'); - } - return response; - }); - }, - - async createIndexConnector({ name, indexName }: { name: string; indexName: string }) { - const { body } = await supertest - .post(`/api/actions/connector`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .send({ - name, - config: { - index: indexName, - refresh: true, - }, - connector_type_id: '.index', - }); - return body.id as string; - }, - - async createRule({ - name, - ruleTypeId, - params, - actions = [], - tags = [], - schedule, - consumer, - }: { - ruleTypeId: string; - name: string; - params: MetricThresholdParams | ThresholdParams | SloBurnRateRuleParams; - actions?: any[]; - tags?: any[]; - schedule?: { interval: string }; - consumer: string; - }) { - const { body } = await supertest - .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo') - .send({ - params, - consumer, - schedule: schedule || { - interval: '5m', - }, - tags, - name, - rule_type_id: ruleTypeId, - actions, - }); - return body; - }, - - async findRule(ruleId: string) { - if (!ruleId) { - throw new Error(`'ruleId' is undefined`); - } - const response = await supertest - .get('/api/alerting/rules/_find') - .set('kbn-xsrf', 'foo') - .set('x-elastic-internal-origin', 'foo'); - return response.body.data.find((obj: any) => obj.id === ruleId); - }, - }; -} diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index f516f1e22a7f7..cc2b3f77ca0fa 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -22,7 +22,6 @@ import { IngestPipelinesProvider } from './ingest_pipelines'; import { IndexManagementProvider } from './index_management'; import { DataViewApiProvider } from './data_view_api'; import { SloApiProvider } from './slo'; -import { AlertingApiProvider } from './alerting_api'; import { SecuritySolutionApiProvider } from './security_solution_api.gen'; export const services = { @@ -43,5 +42,4 @@ export const services = { indexManagement: IndexManagementProvider, slo: SloApiProvider, securitySolutionApi: SecuritySolutionApiProvider, - alertingApi: AlertingApiProvider, }; From 65e4e17922e89ec7cff98e5af86da7204062e78a Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:50:42 +0000 Subject: [PATCH 17/28] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/test/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index cd0e161d0fdb0..8f879ff660197 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -179,6 +179,5 @@ "@kbn/actions-simulators-plugin", "@kbn/cases-api-integration-test-plugin", "@kbn/mock-idp-utils", - "@kbn/test-suites-serverless" ] } From 4978fe75dccb1d483d6578be4fe117578ec4f301 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 16:54:24 +0200 Subject: [PATCH 18/28] restore original services --- .../api_integration/services/alerting_api.ts | 176 +++++++++++++++ .../api_integration/services/index.ts | 4 + .../api_integration/services/slo_api.ts | 213 ++++++++++++++++++ .../services/deployment_agnostic_services.ts | 2 - 4 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 x-pack/test_serverless/api_integration/services/alerting_api.ts create mode 100644 x-pack/test_serverless/api_integration/services/slo_api.ts diff --git a/x-pack/test_serverless/api_integration/services/alerting_api.ts b/x-pack/test_serverless/api_integration/services/alerting_api.ts new file mode 100644 index 0000000000000..6000e9d8bdc88 --- /dev/null +++ b/x-pack/test_serverless/api_integration/services/alerting_api.ts @@ -0,0 +1,176 @@ +/* + * 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 type { + AggregationsAggregate, + SearchResponse, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; +import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; +import { RoleCredentials } from '../../shared/services'; +import { SloBurnRateRuleParams } from './slo_api'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function AlertingApiProvider({ getService }: FtrProviderContext) { + const retry = getService('retry'); + const es = getService('es'); + const requestTimeout = 30 * 1000; + const retryTimeout = 120 * 1000; + const logger = getService('log'); + const svlCommonApi = getService('svlCommonApi'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + return { + async waitForRuleStatus({ + roleAuthc, + ruleId, + expectedStatus, + }: { + roleAuthc: RoleCredentials; + ruleId: string; + expectedStatus: string; + }) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertestWithoutAuth + .get(`/api/alerting/rule/${ruleId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + const { execution_status: executionStatus } = response.body || {}; + const { status } = executionStatus || {}; + if (status !== expectedStatus) { + throw new Error(`waitForStatus(${expectedStatus}): got ${status}`); + } + return executionStatus?.status; + }); + }, + + async waitForDocumentInIndex({ + indexName, + docCountTarget = 1, + }: { + indexName: string; + docCountTarget?: number; + }): Promise>> { + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + rest_total_hits_as_int: true, + }); + logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); + if (!response.hits.total || (response.hits.total as number) < docCountTarget) { + throw new Error('No hits found'); + } + return response; + }); + }, + + async waitForAlertInIndex({ + indexName, + ruleId, + }: { + indexName: string; + ruleId: string; + }): Promise>> { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + body: { + query: { + term: { + 'kibana.alert.rule.uuid': ruleId, + }, + }, + }, + }); + if (response.hits.hits.length === 0) { + throw new Error('No hits found'); + } + return response; + }); + }, + + async createIndexConnector({ + roleAuthc, + name, + indexName, + }: { + roleAuthc: RoleCredentials; + name: string; + indexName: string; + }) { + const { body } = await supertestWithoutAuth + .post(`/api/actions/connector`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .send({ + name, + config: { + index: indexName, + refresh: true, + }, + connector_type_id: '.index', + }); + return body.id as string; + }, + + async createRule({ + roleAuthc, + name, + ruleTypeId, + params, + actions = [], + tags = [], + schedule, + consumer, + }: { + roleAuthc: RoleCredentials; + ruleTypeId: string; + name: string; + params: MetricThresholdParams | ThresholdParams | SloBurnRateRuleParams; + actions?: any[]; + tags?: any[]; + schedule?: { interval: string }; + consumer: string; + }) { + const { body } = await supertestWithoutAuth + .post(`/api/alerting/rule`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .send({ + params, + consumer, + schedule: schedule || { + interval: '5m', + }, + tags, + name, + rule_type_id: ruleTypeId, + actions, + }); + return body; + }, + + async findRule(roleAuthc: RoleCredentials, ruleId: string) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + const response = await supertestWithoutAuth + .get('/api/alerting/rules/_find') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + return response.body.data.find((obj: any) => obj.id === ruleId); + }, + }; +} diff --git a/x-pack/test_serverless/api_integration/services/index.ts b/x-pack/test_serverless/api_integration/services/index.ts index c14a836f79c0b..347fc1f68b0ca 100644 --- a/x-pack/test_serverless/api_integration/services/index.ts +++ b/x-pack/test_serverless/api_integration/services/index.ts @@ -9,8 +9,10 @@ import { GenericFtrProviderContext } from '@kbn/test'; import { services as deploymentAgnosticSharedServices } from '../../shared/services/deployment_agnostic_services'; import { services as svlSharedServices } from '../../shared/services'; +import { AlertingApiProvider } from './alerting_api'; import { SamlToolsProvider } from './saml_tools'; import { SvlCasesServiceProvider } from './svl_cases'; +import { SloApiProvider } from './slo_api'; import { TransformProvider } from './transform'; import { SvlEnrichPoliciesApi } from './index_management/svl_enrich_policies.api'; @@ -33,8 +35,10 @@ export const services = { // serverless FTR services ...svlSharedServices, + alertingApi: AlertingApiProvider, samlTools: SamlToolsProvider, svlCases: SvlCasesServiceProvider, + sloApi: SloApiProvider, transform: TransformProvider, synthtrace: SynthtraceProvider, svlEnrichPoliciesApi: SvlEnrichPoliciesApi, diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts new file mode 100644 index 0000000000000..96b7f9e518f31 --- /dev/null +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -0,0 +1,213 @@ +/* + * 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 { + fetchHistoricalSummaryParamsSchema, + FetchHistoricalSummaryResponse, +} from '@kbn/slo-schema'; +import * as t from 'io-ts'; +import type { RoleCredentials } from '../../shared/services'; +import { FtrProviderContext } from '../ftr_provider_context'; + +type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; + +interface Duration { + value: number; + unit: DurationUnit; +} + +interface WindowSchema { + id: string; + burnRateThreshold: number; + maxBurnRateThreshold: number; + longWindow: Duration; + shortWindow: Duration; + actionGroup: string; +} + +interface Dependency { + ruleId: string; + actionGroupsToSuppressOn: string[]; +} + +export interface SloBurnRateRuleParams { + sloId: string; + windows: WindowSchema[]; + dependencies?: Dependency[]; +} + +interface SloParams { + id?: string; + name: string; + description: string; + indicator: { + type: 'sli.kql.custom'; + params: { + index: string; + good: string; + total: string; + timestampField: string; + }; + }; + timeWindow: { + duration: string; + type: string; + }; + budgetingMethod: string; + objective: { + target: number; + }; + groupBy: string; +} + +type FetchHistoricalSummaryParams = t.OutputOf< + typeof fetchHistoricalSummaryParamsSchema.props.body +>; + +export function SloApiProvider({ getService }: FtrProviderContext) { + const es = getService('es'); + const supertest = getService('supertest'); + const svlCommonApi = getService('svlCommonApi'); + const retry = getService('retry'); + const requestTimeout = 30 * 1000; + const retryTimeout = 180 * 1000; + + return { + async create(slo: SloParams, roleAuthc: RoleCredentials) { + const { body } = await supertest + .post(`/api/observability/slos`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .send(slo); + + return body; + }, + + async delete({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + return response; + }, + + async fetchHistoricalSummary( + params: FetchHistoricalSummaryParams, + roleAuthc: RoleCredentials + ): Promise { + const { body } = await supertest + .post(`/internal/observability/slos/_historical_summary`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .send(params); + + return body; + }, + + async waitForSloToBeDeleted({ + sloId, + roleAuthc, + }: { + sloId: string; + roleAuthc: RoleCredentials; + }) { + if (!sloId) { + throw new Error(`sloId is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .delete(`/api/observability/slos/${sloId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + if (!response.ok) { + throw new Error(`slodId [${sloId}] was not deleted`); + } + return response; + }); + }, + + async waitForSloCreated({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { + if (!sloId) { + throw new Error(`'sloId is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .get(`/api/observability/slos/${sloId}`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + if (response.body.id === undefined) { + throw new Error(`No slo with id ${sloId} found`); + } + return response.body; + }); + }, + + async waitForSloSummaryTempIndexToExist(index: string) { + if (!index) { + throw new Error(`index is undefined`); + } + + return await retry.tryForTime(retryTimeout, async () => { + const indexExists = await es.indices.exists({ index, allow_no_indices: false }); + if (!indexExists) { + throw new Error(`index ${index} should exist`); + } + return indexExists; + }); + }, + + async getSloData({ sloId, indexName }: { sloId: string; indexName: string }) { + const response = await es.search({ + index: indexName, + body: { + query: { + bool: { + filter: [{ term: { 'slo.id': sloId } }], + }, + }, + }, + }); + return response; + }, + async waitForSloData({ sloId, indexName }: { sloId: string; indexName: string }) { + return await retry.tryForTime(retryTimeout, async () => { + const response = await es.search({ + index: indexName, + body: { + query: { + bool: { + filter: [{ term: { 'slo.id': sloId } }], + }, + }, + }, + }); + if (response.hits.hits.length === 0) { + throw new Error(`No hits found at index [${indexName}] for slo [${sloId}] `); + } + return response; + }); + }, + async deleteAllSLOs() { + const response = await supertest + .get(`/api/observability/slos/_definitions`) + .set(svlCommonApi.getInternalRequestHeader()) + .send() + .expect(200); + await Promise.all( + response.body.results.map(({ id }: { id: string }) => { + return supertest + .delete(`/api/observability/slos/${id}`) + .set(svlCommonApi.getInternalRequestHeader()) + .send() + .expect(204); + }) + ); + }, + }; +} diff --git a/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts b/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts index 4162a08b2e56a..97a5963bd9e3b 100644 --- a/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts +++ b/x-pack/test_serverless/shared/services/deployment_agnostic_services.ts @@ -30,8 +30,6 @@ const deploymentAgnosticApiIntegrationServices = _.pick(apiIntegrationServices, 'usageAPI', 'console', 'securitySolutionApi', - 'alertingApi', - 'sloApi', ]); export const services = { From 1facfd1b4af233f47c1ed26ad0f7c0f6446b1245 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 18:37:24 +0200 Subject: [PATCH 19/28] fix type errors --- .../apis/observability/alerting/burn_rate_rule.ts | 5 +++-- .../apis/observability/alerting/index.ts | 4 ++-- .../deployment_agnostic/services/alerting_api.ts | 12 ++++++++++++ .../deployment_agnostic/services/slo_api.ts | 6 ------ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index 32332c70d6081..c4ddddb6bde03 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -6,10 +6,11 @@ */ import { cleanup, Dataset, generate, PartialConfig } from '@kbn/data-forge'; +import { RoleCredentials, InternalRequestHeader } from '@kbn/ftr-common-functional-services'; import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ getService }: FtrProviderContext) { +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { const esClient = getService('es'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const samlAuth = getService('samlAuth'); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts index a4fc8b21753bd..10e8550581dcf 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ loadTestFile }: FtrProviderContext) { +export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { describe('Slo - Burn rate rule', function () { this.tags(['ess', 'serverless']); loadTestFile(require.resolve('./burn_rate_rule')); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index c2b6c3b9394c7..14e24aac94327 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -5,9 +5,21 @@ * 2.0. */ +import type { + AggregationsAggregate, + SearchResponse, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; +import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; import { RoleCredentials } from '@kbn/ftr-common-functional-services'; import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; +export interface SloBurnRateRuleParams { + sloId: string; + windows: WindowSchema[]; + dependencies?: Dependency[]; +} + export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { const retry = getService('retry'); const samlAuth = getService('samlAuth'); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts index 4c83a536ffb36..cdc3da680586c 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts @@ -34,12 +34,6 @@ interface Dependency { actionGroupsToSuppressOn: string[]; } -export interface SloBurnRateRuleParams { - sloId: string; - windows: WindowSchema[]; - dependencies?: Dependency[]; -} - interface SloParams { id?: string; name: string; From dea02c6925da1fe01417af98e0d5cfa363dcee40 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 14 Aug 2024 18:39:14 +0200 Subject: [PATCH 20/28] remove tags --- .../deployment_agnostic/apis/observability/alerting/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts index 10e8550581dcf..6b7b1d56d0ecd 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts @@ -9,7 +9,6 @@ import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_cont export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { describe('Slo - Burn rate rule', function () { - this.tags(['ess', 'serverless']); loadTestFile(require.resolve('./burn_rate_rule')); }); } From 7053b2b57d8d6fec91f3fdf89104dc18dbf5a336 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 15 Aug 2024 07:59:26 +0200 Subject: [PATCH 21/28] fix test loading and move types --- .../apis/observability/alerting/index.ts | 4 ++-- .../services/alerting_api.ts | 21 +++++++++++++++++++ .../deployment_agnostic/services/slo_api.ts | 21 ------------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts index 6b7b1d56d0ecd..b2dc2abeca67d 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/index.ts @@ -7,8 +7,8 @@ import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { - describe('Slo - Burn rate rule', function () { +export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { + describe('Slo - Burn rate rule', () => { loadTestFile(require.resolve('./burn_rate_rule')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 14e24aac94327..145619580e909 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -20,6 +20,27 @@ export interface SloBurnRateRuleParams { dependencies?: Dependency[]; } +interface WindowSchema { + id: string; + burnRateThreshold: number; + maxBurnRateThreshold: number; + longWindow: Duration; + shortWindow: Duration; + actionGroup: string; +} + +interface Dependency { + ruleId: string; + actionGroupsToSuppressOn: string[]; +} + +type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; + +interface Duration { + value: number; + unit: DurationUnit; +} + export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { const retry = getService('retry'); const samlAuth = getService('samlAuth'); diff --git a/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts index cdc3da680586c..05db3259ddbc6 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/slo_api.ts @@ -13,27 +13,6 @@ import * as t from 'io-ts'; import { RoleCredentials } from '@kbn/ftr-common-functional-services'; import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; -type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; - -interface Duration { - value: number; - unit: DurationUnit; -} - -interface WindowSchema { - id: string; - burnRateThreshold: number; - maxBurnRateThreshold: number; - longWindow: Duration; - shortWindow: Duration; - actionGroup: string; -} - -interface Dependency { - ruleId: string; - actionGroupsToSuppressOn: string[]; -} - interface SloParams { id?: string; name: string; From 9b76f4fa0127a8fcce40baf549b409fe06fcbc69 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 15 Aug 2024 08:03:50 +0200 Subject: [PATCH 22/28] add missing auth header --- .../apis/observability/alerting/burn_rate_rule.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index c4ddddb6bde03..4a8a67209eeeb 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -88,6 +88,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { }); await supertestWithoutAuth .delete('/api/observability/slos/my-custom-id') + .set(adminRoleAuthc.apiKeyHeader) .set(internalHeaders); await esDeleteAllIndices([ALERT_ACTION_INDEX, ...dataForgeIndices]); await cleanup({ client: esClient, config: dataForgeConfig, logger }); From c4cfa24a55352a41603fc70022c4165d49f9a33f Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 15 Aug 2024 08:06:40 +0200 Subject: [PATCH 23/28] remove unused arg in alerting_api service --- .../deployment_agnostic/services/alerting_api.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 145619580e909..7abfe87d056a7 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -82,11 +82,9 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide async waitForDocumentInIndex({ indexName, docCountTarget = 1, - roleAuthc, }: { indexName: string; docCountTarget?: number; - roleAuthc: RoleCredentials; }): Promise>> { return await retry.tryForTime(retryTimeout, async () => { const response = await es.search({ From 7dd26491f2bca82b614468588ae1856f50cce0bd Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 15 Aug 2024 12:44:00 +0200 Subject: [PATCH 24/28] fix types --- .../observability/alerting/burn_rate_rule.ts | 1 - .../services/alerting_api.ts | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts index 4a8a67209eeeb..22a70ad439851 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/alerting/burn_rate_rule.ts @@ -58,7 +58,6 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { await alertingApi.waitForDocumentInIndex({ indexName: DATA_VIEW, docCountTarget: 360, - roleAuthc: adminRoleAuthc, }); await dataViewApi.create({ roleAuthc: adminRoleAuthc, diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 7abfe87d056a7..550ba4e97db4b 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -42,14 +42,14 @@ interface Duration { } export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProviderContext) { - const retry = getService('retry'); const samlAuth = getService('samlAuth'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const es = getService('es'); + const retry = getService('retry'); + const logger = getService('log'); const config = getService('config'); const retryTimeout = config.get('timeouts.try'); const requestTimeout = 30 * 1000; - const logger = getService('log'); return { async waitForRuleStatus({ @@ -61,9 +61,6 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide expectedStatus: string; roleAuthc: RoleCredentials; }) { - if (!ruleId) { - throw new Error(`'ruleId' is undefined`); - } return await retry.tryForTime(retryTimeout, async () => { const response = await supertestWithoutAuth .get(`/api/alerting/rule/${ruleId}`) @@ -92,9 +89,16 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide rest_total_hits_as_int: true, }); logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); - if (!response.hits.total || response.hits.total < docCountTarget) { + + if ( + !response.hits.total || + (typeof response.hits.total === 'number' + ? response.hits.total < docCountTarget + : response.hits.total.value < docCountTarget) + ) { throw new Error('No hits found'); } + return response; }); }, @@ -189,9 +193,6 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide }, async findRule(ruleId: string, roleAuthc: RoleCredentials) { - if (!ruleId) { - throw new Error(`'ruleId' is undefined`); - } const response = await supertestWithoutAuth .get('/api/alerting/rules/_find') .set(roleAuthc.apiKeyHeader) From ea47dbfbae695f0cd65fb9cae5776a3115c2bfe3 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Tue, 20 Aug 2024 17:44:33 +0300 Subject: [PATCH 25/28] remove unused path --- x-pack/test/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 3da32b4042d61..160aa0a3d81f6 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -25,7 +25,6 @@ "*/packages/**/*", "*/*/packages/**/*", "security_solution_api_integration/**/*", - "observability_solution_api_integration/**/*", "security_solution_endpoint/**/*" ], "kbn_references": [ From 0a2b008d43fd916e636b6a3083be6e7c832d7148 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Tue, 20 Aug 2024 23:42:29 +0300 Subject: [PATCH 26/28] configs for deployment agnostic tests --- .buildkite/ftr_oblt_serverless_configs.yml | 2 +- .buildkite/ftr_oblt_stateful_configs.yml | 2 +- .../{ => configs/serverless}/oblt.index.ts | 10 +++++----- .../serverless}/oblt.serverless.config.ts | 2 +- .../configs/stateful/oblt.index.ts | 16 ++++++++++++++++ .../stateful}/oblt.stateful.config.ts | 2 +- 6 files changed, 25 insertions(+), 9 deletions(-) rename x-pack/test/api_integration/deployment_agnostic/{ => configs/serverless}/oblt.index.ts (57%) rename x-pack/test/api_integration/deployment_agnostic/{ => configs/serverless}/oblt.serverless.config.ts (84%) create mode 100644 x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts rename x-pack/test/api_integration/deployment_agnostic/{ => configs/stateful}/oblt.stateful.config.ts (83%) diff --git a/.buildkite/ftr_oblt_serverless_configs.yml b/.buildkite/ftr_oblt_serverless_configs.yml index 8fe505ff0e93e..e49655999ec59 100644 --- a/.buildkite/ftr_oblt_serverless_configs.yml +++ b/.buildkite/ftr_oblt_serverless_configs.yml @@ -27,4 +27,4 @@ enabled: - x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group6.ts - x-pack/test_serverless/functional/test_suites/observability/config.screenshots.ts # serverless config files that run deployment-agnostic tests - - x-pack/test/api_integration/deployment_agnostic/oblt.serverless.config.ts + - x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts diff --git a/.buildkite/ftr_oblt_stateful_configs.yml b/.buildkite/ftr_oblt_stateful_configs.yml index ff22d5453c9d0..1ab61c44b61c5 100644 --- a/.buildkite/ftr_oblt_stateful_configs.yml +++ b/.buildkite/ftr_oblt_stateful_configs.yml @@ -51,4 +51,4 @@ enabled: - x-pack/test/profiling_api_integration/cloud/config.ts - x-pack/test/functional/apps/apm/config.ts # Stateful configs that run deployment-agnostic tests - - x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts + - x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts similarity index 57% rename from x-pack/test/api_integration/deployment_agnostic/oblt.index.ts rename to x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts index 78885e470fce0..4d6261d956bce 100644 --- a/x-pack/test/api_integration/deployment_agnostic/oblt.index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.index.ts @@ -4,13 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { DeploymentAgnosticFtrProviderContext } from './ftr_provider_context'; +import { DeploymentAgnosticFtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { describe('Serverless Observability - Deployment-agnostic api integration tests', () => { - loadTestFile(require.resolve('./apis/console')); - loadTestFile(require.resolve('./apis/core')); - loadTestFile(require.resolve('./apis/painless_lab')); - loadTestFile(require.resolve('./apis/observability/alerting')); + loadTestFile(require.resolve('../../apis/console')); + loadTestFile(require.resolve('../../apis/core')); + loadTestFile(require.resolve('../../apis/painless_lab')); + loadTestFile(require.resolve('../../apis/observability/alerting')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.serverless.config.ts b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts similarity index 84% rename from x-pack/test/api_integration/deployment_agnostic/oblt.serverless.config.ts rename to x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts index 52e1ba2d431ac..245663416243f 100644 --- a/x-pack/test/api_integration/deployment_agnostic/oblt.serverless.config.ts +++ b/x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { createServerlessTestConfig } from './default_configs/serverless.config.base'; +import { createServerlessTestConfig } from '../../default_configs/serverless.config.base'; export default createServerlessTestConfig({ serverlessProject: 'oblt', diff --git a/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts new file mode 100644 index 0000000000000..889d95f533637 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.index.ts @@ -0,0 +1,16 @@ +/* + * 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 { DeploymentAgnosticFtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { + describe('Stateful Observability - Deployment-agnostic api integration tests', () => { + loadTestFile(require.resolve('../../apis/console')); + loadTestFile(require.resolve('../../apis/core')); + loadTestFile(require.resolve('../../apis/painless_lab')); + loadTestFile(require.resolve('../../apis/observability/alerting')); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts similarity index 83% rename from x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts rename to x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts index 2f39fce8d1858..7b3cf3a7f1818 100644 --- a/x-pack/test/api_integration/deployment_agnostic/oblt.stateful.config.ts +++ b/x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { createStatefulTestConfig } from './default_configs/stateful.config.base'; +import { createStatefulTestConfig } from '../../default_configs/stateful.config.base'; export default createStatefulTestConfig({ testFiles: [require.resolve('./oblt.index.ts')], From 364eea387b1b8bd965984f2a181680a3121a78a1 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Wed, 21 Aug 2024 13:42:34 +0200 Subject: [PATCH 27/28] Update x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts Co-authored-by: Robert Oskamp --- .../deployment_agnostic/services/alerting_api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 550ba4e97db4b..4e22e98cb84d8 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -88,7 +88,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide index: indexName, rest_total_hits_as_int: true, }); - logger.debug(`Found ${response.hits.total} docs, looking for atleast ${docCountTarget}.`); + logger.debug(`Found ${response.hits.total} docs, looking for at least ${docCountTarget}.`); if ( !response.hits.total || From 85273a2f9243676ccb34b79073c4a1f8047d92d8 Mon Sep 17 00:00:00 2001 From: Panagiota Mitsopoulou Date: Wed, 21 Aug 2024 16:00:32 +0300 Subject: [PATCH 28/28] better error message --- .../deployment_agnostic/services/alerting_api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts index 4e22e98cb84d8..430fd51efdc32 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/alerting_api.ts @@ -96,7 +96,7 @@ export function AlertingApiProvider({ getService }: DeploymentAgnosticFtrProvide ? response.hits.total < docCountTarget : response.hits.total.value < docCountTarget) ) { - throw new Error('No hits found'); + throw new Error('No hits or not enough hits found'); } return response;