From beb8316ccab2ce647b6fb783f9e85fa21a53df0e Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Mon, 7 Oct 2024 15:50:02 -0400 Subject: [PATCH 1/6] Add update slo test for serverless --- .../api_integration/services/slo_api.ts | 54 +++-- .../test_suites/observability/slos/index.ts | 1 + .../observability/slos/update_slo.ts | 226 ++++++++++++++++++ 3 files changed, 256 insertions(+), 25 deletions(-) create mode 100644 x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index 96b7f9e518f31..5fd19ea95d2c6 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -6,8 +6,12 @@ */ import { + CreateSLOInput, fetchHistoricalSummaryParamsSchema, FetchHistoricalSummaryResponse, + FindSLODefinitionsResponse, + findSloDefinitionsResponseSchema, + UpdateSLOInput, } from '@kbn/slo-schema'; import * as t from 'io-ts'; import type { RoleCredentials } from '../../shared/services'; @@ -40,30 +44,6 @@ export interface SloBurnRateRuleParams { 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 >; @@ -77,7 +57,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { const retryTimeout = 180 * 1000; return { - async create(slo: SloParams, roleAuthc: RoleCredentials) { + async create(slo: CreateSLOInput, roleAuthc: RoleCredentials) { const { body } = await supertest .post(`/api/observability/slos`) .set(svlCommonApi.getInternalRequestHeader()) @@ -87,6 +67,19 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return body; }, + async update( + { sloId, slo }: { sloId: string; slo: UpdateSLOInput }, + roleAuthc: RoleCredentials + ) { + const { body } = await supertest + .put(`/api/observability/slos/${sloId}`) + .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}`) @@ -95,6 +88,16 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return response; }, + async findDefinitions(): Promise { + const response = await supertest + .get(`/api/observability/slos/_definitions`) + .set(svlCommonApi.getInternalRequestHeader()) + .send() + .expect(200); + + return findSloDefinitionsResponseSchema.encode(response as unknown as any); + }, + async fetchHistoricalSummary( params: FetchHistoricalSummaryParams, roleAuthc: RoleCredentials @@ -193,6 +196,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return response; }); }, + async deleteAllSLOs() { const response = await supertest .get(`/api/observability/slos/_definitions`) diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts index 8df59e6f3b624..a80240c23d341 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts @@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('SLOs', function () { loadTestFile(require.resolve('./create_slo')); + loadTestFile(require.resolve('./update_slo')); loadTestFile(require.resolve('./delete_slo')); loadTestFile(require.resolve('./fetch_historical_summary')); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts new file mode 100644 index 0000000000000..1ac527322b93d --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts @@ -0,0 +1,226 @@ +/* + * 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 expect from '@kbn/expect'; +import { cleanup, generate } from '@kbn/infra-forge'; +import { getSLOPipelineId, getSLOSummaryPipelineId } from '@kbn/slo-plugin/common/constants'; +import { SO_SLO_TYPE } from '@kbn/slo-plugin/server/saved_objects'; +import { ALL_VALUE } from '@kbn/slo-schema'; +import type { RoleCredentials } from '../../../../shared/services'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const supertest = getService('supertest'); + + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const logger = getService('log'); + const dataViewApi = getService('dataViewApi'); + const sloApi = getService('sloApi'); + const kibanaServer = getService('kibanaServer'); + const transform = getService('transform'); + const svlUserManager = getService('svlUserManager'); + const svlCommonApi = getService('svlCommonApi'); + + describe('update_slo', () => { + // DATE_VIEW should match the index template: + // x-pack/packages/kbn-infra-forge/src/data_sources/composable/template.json + const DATE_VIEW = 'kbn-data-forge-fake_hosts'; + const DATA_VIEW_ID = 'data-view-id'; + let infraDataIndex: string; + let roleAuthc: RoleCredentials; + + before(async () => { + infraDataIndex = await generate({ + esClient, + lookback: 'now-15m', + logger, + }); + await dataViewApi.create({ + name: DATE_VIEW, + id: DATA_VIEW_ID, + title: DATE_VIEW, + }); + await kibanaServer.savedObjects.cleanStandardList(); + roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + }); + + after(async () => { + await dataViewApi.delete({ + id: DATA_VIEW_ID, + }); + await supertest + .delete('/api/observability/slos/my-custom-id1') + .set(svlCommonApi.getInternalRequestHeader()); + + await supertest + .delete('/api/observability/slos/my-custom-id2') + .set(svlCommonApi.getInternalRequestHeader()); + + await esDeleteAllIndices([infraDataIndex]); + await cleanup({ esClient, logger }); + await kibanaServer.savedObjects.clean({ types: [SO_SLO_TYPE] }); + await transform.api.cleanTransformIndices(); + await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + }); + + describe('when updating fields without revision bump', () => { + const sloId = 'my-custom-id1'; + + before(async () => { + await sloApi.create( + { + id: sloId, + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: infraDataIndex, + 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: ALL_VALUE, + }, + roleAuthc + ); + }); + + it('updates the SO definition', async () => { + let definitions = await sloApi.findDefinitions(); + expect(definitions.total).to.eql(1); + expect(definitions.results[0].name).to.eql('my custom name'); + expect(definitions.results[0].description).to.eql('my custom description'); + expect(definitions.results[0].revision).to.eql(1); + + await sloApi.update( + { + sloId, + slo: { + name: 'updated name', + description: 'updated description', + }, + }, + roleAuthc + ); + + // assert definition is updated + definitions = await sloApi.findDefinitions(); + expect(definitions.total).to.eql(1); + expect(definitions.results[0].name).to.eql('updated name'); + expect(definitions.results[0].description).to.eql('updated description'); + expect(definitions.results[0].revision).to.eql(1); + + // assert resources are not reinstalled + const expectedRevision = 1; + const rollupPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOPipelineId(sloId, expectedRevision), + }); + const expectedRollupPipeline = `.slo-observability.sli.pipeline-${sloId}-${expectedRevision}`; + expect(rollupPipelineResponse[expectedRollupPipeline]).not.to.be(undefined); + + const summaryPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOSummaryPipelineId(sloId, expectedRevision), + }); + const expectedSummaryPipeline = `.slo-observability.summary.pipeline-${sloId}-${expectedRevision}`; + expect(summaryPipelineResponse[expectedSummaryPipeline]).not.to.be(undefined); + + const sloTransformId = `slo-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloTransformId, 200); + const sloSummaryTransformId = `slo-summary-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloSummaryTransformId, 200); + }); + }); + + describe('when updating fields with revision bump', () => { + const sloId = 'my-custom-id2'; + + before(async () => { + await sloApi.create( + { + id: sloId, + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: infraDataIndex, + 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.95, + }, + groupBy: ALL_VALUE, + }, + roleAuthc + ); + }); + + it('updates the SO definition and reinstall the resources', async () => { + let definitions = await sloApi.findDefinitions(); + expect(definitions.total).to.eql(1); + expect(definitions.results[0].objective).to.eql({ target: 0.95 }); + expect(definitions.results[0].revision).to.eql(1); + + await sloApi.update( + { + sloId, + slo: { + objective: { + target: 0.8, + }, + }, + }, + roleAuthc + ); + + // assert definition is updated + definitions = await sloApi.findDefinitions(); + expect(definitions.total).to.eql(1); + expect(definitions.results[0].objective).to.eql({ target: 0.8 }); + expect(definitions.results[0].revision).to.eql(2); + + // assert resources are reinstalled + const expectedRevision = 2; + const rollupPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOPipelineId(sloId, expectedRevision), + }); + const expectedRollupPipeline = `.slo-observability.sli.pipeline-${sloId}-${expectedRevision}`; + expect(rollupPipelineResponse[expectedRollupPipeline]).not.to.be(undefined); + + const summaryPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOSummaryPipelineId(sloId, expectedRevision), + }); + const expectedSummaryPipeline = `.slo-observability.summary.pipeline-${sloId}-${expectedRevision}`; + expect(summaryPipelineResponse[expectedSummaryPipeline]).not.to.be(undefined); + + const sloTransformId = `slo-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloTransformId, 200); + const sloSummaryTransformId = `slo-summary-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloSummaryTransformId, 200); + }); + }); + }); +} From 8d991253ef17340c7b3e3a94a0df3879c0f5710a Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 8 Oct 2024 07:37:25 -0400 Subject: [PATCH 2/6] Fix api helper --- x-pack/test_serverless/api_integration/services/slo_api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index 5fd19ea95d2c6..40b4216150751 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -89,13 +89,13 @@ export function SloApiProvider({ getService }: FtrProviderContext) { }, async findDefinitions(): Promise { - const response = await supertest + const { body } = await supertest .get(`/api/observability/slos/_definitions`) .set(svlCommonApi.getInternalRequestHeader()) .send() .expect(200); - return findSloDefinitionsResponseSchema.encode(response as unknown as any); + return findSloDefinitionsResponseSchema.encode(body); }, async fetchHistoricalSummary( From 09e45bf3d3d973dc77c52be598384d83ecc06b9d Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 8 Oct 2024 08:24:28 -0400 Subject: [PATCH 3/6] Fix update flow --- .../api_integration/services/slo_api.ts | 3 +- .../observability/slos/update_slo.ts | 32 ++++++++----------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index 40b4216150751..0cd3baf2e5b1e 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -10,7 +10,6 @@ import { fetchHistoricalSummaryParamsSchema, FetchHistoricalSummaryResponse, FindSLODefinitionsResponse, - findSloDefinitionsResponseSchema, UpdateSLOInput, } from '@kbn/slo-schema'; import * as t from 'io-ts'; @@ -95,7 +94,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { .send() .expect(200); - return findSloDefinitionsResponseSchema.encode(body); + return body; }, async fetchHistoricalSummary( diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts index 1ac527322b93d..ff04f1d662191 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/update_slo.ts @@ -101,11 +101,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('updates the SO definition', async () => { - let definitions = await sloApi.findDefinitions(); - expect(definitions.total).to.eql(1); - expect(definitions.results[0].name).to.eql('my custom name'); - expect(definitions.results[0].description).to.eql('my custom description'); - expect(definitions.results[0].revision).to.eql(1); + let sloResponse = await sloApi.waitForSloCreated({ sloId, roleAuthc }); + expect(sloResponse.name).to.eql('my custom name'); + expect(sloResponse.description).to.eql('my custom description'); + expect(sloResponse.revision).to.eql(1); await sloApi.update( { @@ -119,11 +118,10 @@ export default function ({ getService }: FtrProviderContext) { ); // assert definition is updated - definitions = await sloApi.findDefinitions(); - expect(definitions.total).to.eql(1); - expect(definitions.results[0].name).to.eql('updated name'); - expect(definitions.results[0].description).to.eql('updated description'); - expect(definitions.results[0].revision).to.eql(1); + sloResponse = await sloApi.waitForSloCreated({ sloId, roleAuthc }); + expect(sloResponse.name).to.eql('updated name'); + expect(sloResponse.description).to.eql('updated description'); + expect(sloResponse.revision).to.eql(1); // assert resources are not reinstalled const expectedRevision = 1; @@ -179,10 +177,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('updates the SO definition and reinstall the resources', async () => { - let definitions = await sloApi.findDefinitions(); - expect(definitions.total).to.eql(1); - expect(definitions.results[0].objective).to.eql({ target: 0.95 }); - expect(definitions.results[0].revision).to.eql(1); + let sloResponse = await sloApi.waitForSloCreated({ sloId, roleAuthc }); + expect(sloResponse.objective).to.eql({ target: 0.95 }); + expect(sloResponse.revision).to.eql(1); await sloApi.update( { @@ -197,10 +194,9 @@ export default function ({ getService }: FtrProviderContext) { ); // assert definition is updated - definitions = await sloApi.findDefinitions(); - expect(definitions.total).to.eql(1); - expect(definitions.results[0].objective).to.eql({ target: 0.8 }); - expect(definitions.results[0].revision).to.eql(2); + sloResponse = await sloApi.waitForSloCreated({ sloId, roleAuthc }); + expect(sloResponse.objective).to.eql({ target: 0.8 }); + expect(sloResponse.revision).to.eql(2); // assert resources are reinstalled const expectedRevision = 2; From 7c8250638baaa73bb1c74b27ebe3cce89b8b574d Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 8 Oct 2024 09:27:25 -0400 Subject: [PATCH 4/6] Add test for reset case --- .../api_integration/services/slo_api.ts | 22 ++- .../test_suites/observability/slos/index.ts | 1 + .../observability/slos/reset_slo.ts | 131 ++++++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index 0cd3baf2e5b1e..a28d7e0c83db7 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -87,10 +87,11 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return response; }, - async findDefinitions(): Promise { + async findDefinitions(roleAuthc: RoleCredentials): Promise { const { body } = await supertest .get(`/api/observability/slos/_definitions`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send() .expect(200); @@ -135,7 +136,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { async waitForSloCreated({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { if (!sloId) { - throw new Error(`'sloId is undefined`); + throw new Error(`sloId is undefined`); } return await retry.tryForTime(retryTimeout, async () => { const response = await supertest @@ -150,6 +151,23 @@ export function SloApiProvider({ getService }: FtrProviderContext) { }); }, + async waitForSloReseted(sloId: string, roleAuthc: RoleCredentials) { + if (!sloId) { + throw new Error('sloId is undefined'); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .post(`/api/observability/slos/${sloId}/_reset`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) + .timeout(requestTimeout); + if (response.body.id === undefined) { + throw new Error(`Error reseting ${sloId}`); + } + return response.body; + }); + }, + async waitForSloSummaryTempIndexToExist(index: string) { if (!index) { throw new Error(`index is undefined`); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts index a80240c23d341..0256db73bccbb 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts @@ -11,6 +11,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./create_slo')); loadTestFile(require.resolve('./update_slo')); loadTestFile(require.resolve('./delete_slo')); + loadTestFile(require.resolve('./reset_slo')); loadTestFile(require.resolve('./fetch_historical_summary')); }); } diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts new file mode 100644 index 0000000000000..cd26c44d09987 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts @@ -0,0 +1,131 @@ +/* + * 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 expect from '@kbn/expect'; +import { cleanup, generate } from '@kbn/infra-forge'; +import { getSLOPipelineId, getSLOSummaryPipelineId } from '@kbn/slo-plugin/common/constants'; +import { SO_SLO_TYPE } from '@kbn/slo-plugin/server/saved_objects'; +import { ALL_VALUE } from '@kbn/slo-schema'; +import type { RoleCredentials } from '../../../../shared/services'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const supertest = getService('supertest'); + + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const logger = getService('log'); + const dataViewApi = getService('dataViewApi'); + const sloApi = getService('sloApi'); + const kibanaServer = getService('kibanaServer'); + const transform = getService('transform'); + const svlUserManager = getService('svlUserManager'); + const svlCommonApi = getService('svlCommonApi'); + + describe('reset_slo', () => { + // DATE_VIEW should match the index template: + // x-pack/packages/kbn-infra-forge/src/data_sources/composable/template.json + const DATE_VIEW = 'kbn-data-forge-fake_hosts'; + const DATA_VIEW_ID = 'data-view-id'; + let infraDataIndex: string; + let roleAuthc: RoleCredentials; + + before(async () => { + infraDataIndex = await generate({ + esClient, + lookback: 'now-15m', + logger, + }); + await dataViewApi.create({ + name: DATE_VIEW, + id: DATA_VIEW_ID, + title: DATE_VIEW, + }); + await kibanaServer.savedObjects.cleanStandardList(); + roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + }); + + after(async () => { + await dataViewApi.delete({ + id: DATA_VIEW_ID, + }); + await supertest + .delete('/api/observability/slos/my-custom-id1') + .set(svlCommonApi.getInternalRequestHeader()); + + await supertest + .delete('/api/observability/slos/my-custom-id2') + .set(svlCommonApi.getInternalRequestHeader()); + + await esDeleteAllIndices([infraDataIndex]); + await cleanup({ esClient, logger }); + await kibanaServer.savedObjects.clean({ types: [SO_SLO_TYPE] }); + await transform.api.cleanTransformIndices(); + await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + }); + + describe('with a broken SLO', () => { + const sloId = 'my-custom-id1'; + + before(async () => { + await sloApi.create( + { + id: sloId, + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: infraDataIndex, + 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.95, + }, + groupBy: ALL_VALUE, + }, + roleAuthc + ); + + await transform.api.stopTransform(`slo-${sloId}-1`); + await transform.api.stopTransform(`slo-summary-${sloId}-1`); + }); + + it('resets the SLO resources', async () => { + const expectedRevision = 1; + const sloResponse = await sloApi.waitForSloReseted(sloId, roleAuthc); + expect(sloResponse.revision).to.eql(expectedRevision); + + // assert resources are reinstalled + const rollupPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOPipelineId(sloId, expectedRevision), + }); + const expectedRollupPipeline = `.slo-observability.sli.pipeline-${sloId}-${expectedRevision}`; + expect(rollupPipelineResponse[expectedRollupPipeline]).not.to.be(undefined); + + const summaryPipelineResponse = await esClient.ingest.getPipeline({ + id: getSLOSummaryPipelineId(sloId, expectedRevision), + }); + const expectedSummaryPipeline = `.slo-observability.summary.pipeline-${sloId}-${expectedRevision}`; + expect(summaryPipelineResponse[expectedSummaryPipeline]).not.to.be(undefined); + + const sloTransformId = `slo-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloTransformId, 200); + const sloSummaryTransformId = `slo-summary-${sloId}-${expectedRevision}`; + await transform.api.getTransform(sloSummaryTransformId, 200); + }); + }); + }); +} From 71a4292221210ae2c6094aca2a461320880d8715 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 8 Oct 2024 09:32:40 -0400 Subject: [PATCH 5/6] Update reset --- .../api_integration/services/transform/api.ts | 10 +++++++++- .../test_suites/observability/slos/reset_slo.ts | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/x-pack/test_serverless/api_integration/services/transform/api.ts b/x-pack/test_serverless/api_integration/services/transform/api.ts index b96f8aeca2ad9..84fdd2451cbaa 100644 --- a/x-pack/test_serverless/api_integration/services/transform/api.ts +++ b/x-pack/test_serverless/api_integration/services/transform/api.ts @@ -267,7 +267,15 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async stopTransform(transformId: string) { log.debug(`Stopping transform '${transformId}' ...`); - const { body, status } = await esSupertest.post(`/_transform/${transformId}/_stop`); + const { body, status } = await esSupertest.post( + `/_transform/${transformId}/_stop?force=true` + ); + this.assertResponseStatusCode(200, status, body); + }, + + async deleteTransform(transformId: string) { + log.debug(`Deleting transform '${transformId}' ...`); + const { body, status } = await esSupertest.delete(`/_transform/${transformId}`); this.assertResponseStatusCode(200, status, body); }, diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts index cd26c44d09987..c5fc8972ca66a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/reset_slo.ts @@ -100,7 +100,9 @@ export default function ({ getService }: FtrProviderContext) { ); await transform.api.stopTransform(`slo-${sloId}-1`); + await transform.api.deleteTransform(`slo-${sloId}-1`); await transform.api.stopTransform(`slo-summary-${sloId}-1`); + await transform.api.deleteTransform(`slo-summary-${sloId}-1`); }); it('resets the SLO resources', async () => { From d23a04eaca33994030822dc8ab8f534f37e0b6c3 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 8 Oct 2024 10:19:57 -0400 Subject: [PATCH 6/6] use supertest without auth --- .../api_integration/services/slo_api.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index a28d7e0c83db7..c7403d2708429 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -50,6 +50,7 @@ type FetchHistoricalSummaryParams = t.OutputOf< export function SloApiProvider({ getService }: FtrProviderContext) { const es = getService('es'); const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const svlCommonApi = getService('svlCommonApi'); const retry = getService('retry'); const requestTimeout = 30 * 1000; @@ -57,7 +58,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return { async create(slo: CreateSLOInput, roleAuthc: RoleCredentials) { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/api/observability/slos`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -70,7 +71,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { { sloId, slo }: { sloId: string; slo: UpdateSLOInput }, roleAuthc: RoleCredentials ) { - const { body } = await supertest + const { body } = await supertestWithoutAuth .put(`/api/observability/slos/${sloId}`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -80,7 +81,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { }, async delete({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) { - const response = await supertest + const response = await supertestWithoutAuth .delete(`/api/observability/slos/${sloId}`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader); @@ -88,7 +89,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { }, async findDefinitions(roleAuthc: RoleCredentials): Promise { - const { body } = await supertest + const { body } = await supertestWithoutAuth .get(`/api/observability/slos/_definitions`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -102,7 +103,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { params: FetchHistoricalSummaryParams, roleAuthc: RoleCredentials ): Promise { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/observability/slos/_historical_summary`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -122,7 +123,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { throw new Error(`sloId is undefined`); } return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest + const response = await supertestWithoutAuth .delete(`/api/observability/slos/${sloId}`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -139,7 +140,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { throw new Error(`sloId is undefined`); } return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest + const response = await supertestWithoutAuth .get(`/api/observability/slos/${sloId}`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader) @@ -156,7 +157,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { throw new Error('sloId is undefined'); } return await retry.tryForTime(retryTimeout, async () => { - const response = await supertest + const response = await supertestWithoutAuth .post(`/api/observability/slos/${sloId}/_reset`) .set(svlCommonApi.getInternalRequestHeader()) .set(roleAuthc.apiKeyHeader)