Skip to content

Commit

Permalink
slo agnostic tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mgiota committed May 3, 2024
1 parent a6491ab commit de15462
Show file tree
Hide file tree
Showing 8 changed files with 529 additions and 0 deletions.
1 change: 1 addition & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ enabled:
- x-pack/performance/journeys_e2e/infra_hosts_view.ts
- x-pack/test/custom_branding/config.ts
- x-pack/test/profiling_api_integration/cloud/config.ts
- x-pack/test/api_integration/apis/all_deployments/config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/actions/trial_license_complete_tier/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/configs/ess.config.ts
Expand Down
19 changes: 19 additions & 0 deletions x-pack/test/api_integration/apis/all_deployments/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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';

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

return {
...baseIntegrationTestsConfig.getAll(),
testFiles: [
require.resolve('../../../../test_all_deployments/api_integration/test_suites/observability'),
],
};
}
162 changes: 162 additions & 0 deletions x-pack/test/api_integration/services/alerting_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* 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';
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<T>({
indexName,
docCountTarget = 1,
}: {
indexName: string;
docCountTarget?: number;
}): Promise<SearchResponse<T, Record<string, AggregationsAggregate>>> {
return await retry.tryForTime(retryTimeout, async () => {
const response = await es.search<T>({
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<T>({
indexName,
ruleId,
}: {
indexName: string;
ruleId: string;
}): Promise<SearchResponse<T, Record<string, AggregationsAggregate>>> {
if (!ruleId) {
throw new Error(`'ruleId' is undefined`);
}
return await retry.tryForTime(retryTimeout, async () => {
const response = await es.search<T>({
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);
},
};
}
2 changes: 2 additions & 0 deletions x-pack/test/api_integration/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ 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 = {
Expand All @@ -44,5 +45,6 @@ export const services = {
ingestPipelines: IngestPipelinesProvider,
indexManagement: IndexManagementProvider,
slo: SloApiProvider,
alertingApi: AlertingApiProvider,
securitySolutionApi: SecuritySolutionApiProvider,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { GenericFtrProviderContext } from '@kbn/test';

// eslint-disable-next-line @kbn/imports/no_boundary_crossing
import { services } from '../../test/api_integration/services';

export type FtrProviderContext = GenericFtrProviderContext<typeof services, {}>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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('all deployments observability API', function () {
loadTestFile(require.resolve('./slo/burn_rate_rule'));
});
}
Loading

0 comments on commit de15462

Please sign in to comment.