From da55fe03cd491535b07a963ec44fc65f40a66e30 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Thu, 13 Mar 2025 09:20:03 -0400 Subject: [PATCH 01/14] consider namespace for slo existence validation --- .../plugins/slo/server/services/slo_repository.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index d3bdc04f830e6..777ffbe898ddd 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -32,11 +32,12 @@ export interface SLORepository { export class KibanaSavedObjectsSLORepository implements SLORepository { constructor(private soClient: SavedObjectsClientContract, private logger: Logger) {} - async exists(id: string) { + async exists(id: string, namespaces = []) { const findResponse = await this.soClient.find({ type: SO_SLO_TYPE, perPage: 0, filter: `slo.attributes.id:(${id})`, + namespaces: [...namespaces], }); return findResponse.total > 0; From 8400f3f11eb8f34c36e319c856b363fd823030e1 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Thu, 13 Mar 2025 18:22:19 -0400 Subject: [PATCH 02/14] add test for space check --- .../plugins/slo/server/services/create_slo.ts | 2 +- .../slo/server/services/slo_repository.ts | 2 +- .../apis/observability/slo/create_slo.ts | 32 ++++++++++++++++++- .../apis/observability/slo/fixtures/slo.ts | 10 ++++++ .../deployment_agnostic/services/slo_api.ts | 15 +++++++++ x-pack/test/common/services/spaces.ts | 2 +- 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index 25a6c91eaf0a8..a52a95e973608 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -123,7 +123,7 @@ export class CreateSLO { } private async assertSLOInexistant(slo: SLODefinition) { - const exists = await this.repository.exists(slo.id); + const exists = await this.repository.exists(slo.id, ['*']); if (exists) { throw new SLOIdConflict(`SLO [${slo.id}] already exists`); } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index 777ffbe898ddd..ea4aaef63bd2d 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -16,7 +16,7 @@ import { SLONotFound } from '../errors'; import { SO_SLO_TYPE } from '../saved_objects'; export interface SLORepository { - exists(id: string): Promise; + exists(id: string, namespaces?: Array): Promise; create(slo: SLODefinition): Promise; update(slo: SLODefinition): Promise; findAllByIds(ids: string[]): Promise; diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts index 3e74f02d504db..b3d1558a63854 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts @@ -11,12 +11,13 @@ import { RoleCredentials } from '@kbn/ftr-common-functional-services'; import { getSLOSummaryTransformId, getSLOTransformId } from '@kbn/slo-plugin/common/constants'; import { UserProfile } from '@kbn/test/src/auth/types'; import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -import { DEFAULT_SLO } from './fixtures/slo'; +import { DEFAULT_SLO, DEFAULT_SPACE_FOR_SLO } from './fixtures/slo'; import { DATA_FORGE_CONFIG } from './helpers/dataforge'; import { TransformHelper, createTransformHelper } from './helpers/transform'; export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { const esClient = getService('es'); + const spaceApi = getService('spaces'); const sloApi = getService('sloApi'); const logger = getService('log'); const retry = getService('retry'); @@ -55,6 +56,8 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { await cleanup({ client: esClient, config: DATA_FORGE_CONFIG, logger }); await sloApi.deleteAllSLOs(adminRoleAuthc); await samlAuth.invalidateM2mApiKeyWithRoleScope(adminRoleAuthc); + await spaceApi.delete('space1'); + await spaceApi.delete('space2'); }); it('creates a new slo and transforms', async () => { @@ -125,6 +128,33 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { }); }); + it('creates two SLOs with matching ids across different spaces', async () => { + const spaceApiResponse = await spaceApi.create({ + ...DEFAULT_SPACE_FOR_SLO, + name: 'space1', + id: 'space1', + initials: '1', + }); + expect(spaceApiResponse.space).property('id'); + const { + space: { id: spaceId1 }, + } = spaceApiResponse; + const apiResponse = await sloApi.createWithSpace(DEFAULT_SLO, spaceId1, adminRoleAuthc, 200); + expect(apiResponse).property('id'); + const { id } = apiResponse; + const spaceApiResponse2 = await spaceApi.create({ + ...DEFAULT_SPACE_FOR_SLO, + name: 'space2', + id: 'space2', + initials: '2', + }); + const { + space: { id: spaceId2 }, + } = spaceApiResponse; + expect(spaceApiResponse2.space).property('id'); + await sloApi.createWithSpace({ ...DEFAULT_SLO, id }, spaceId2, adminRoleAuthc, 409); + }); + describe('groupBy smoke tests', () => { it('creates instanceId for SLOs with multi groupBy', async () => { const apiResponse = await sloApi.create( diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts index dfc216760644c..b06a63ba64e65 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts @@ -6,6 +6,7 @@ */ import { CreateSLOInput } from '@kbn/slo-schema'; +import { SpaceCreate } from '@kbn/test-suites-xpack/common/services/spaces'; export const DEFAULT_SLO: CreateSLOInput = { name: 'Test SLO for api integration', @@ -31,3 +32,12 @@ export const DEFAULT_SLO: CreateSLOInput = { tags: ['test'], groupBy: 'tags', }; + +export const DEFAULT_SPACE_FOR_SLO: SpaceCreate = { + name: 'default', + id: 'default', + initials: 'D', + color: '#A6EDEA', + disabledFeatures: [], + solution: 'classic', +}; 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 8ee202b2cf23e..87658972929e9 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 @@ -24,6 +24,21 @@ export function SloApiProvider({ getService }: DeploymentAgnosticFtrProviderCont return body; }, + async createWithSpace( + slo: CreateSLOInput & { id?: string }, + spaceId: string, + roleAuthc: RoleCredentials, + expectedStatus: 200 | 409 + ) { + const { body } = await supertestWithoutAuth + .post(`/s/${spaceId}/api/observability/slos`) + .set(roleAuthc.apiKeyHeader) + .set(samlAuth.getInternalRequestHeader()) + .send(slo) + .expect(expectedStatus); + return body; + }, + async reset(id: string, roleAuthc: RoleCredentials) { const { body } = await supertestWithoutAuth .post(`/api/observability/slos/${id}/_reset`) diff --git a/x-pack/test/common/services/spaces.ts b/x-pack/test/common/services/spaces.ts index 67da912fb6a54..f9d52701648b8 100644 --- a/x-pack/test/common/services/spaces.ts +++ b/x-pack/test/common/services/spaces.ts @@ -16,7 +16,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; const chance = new Chance(); -interface SpaceCreate { +export interface SpaceCreate { name?: string; id?: string; description?: string; From bb9a1c3d0342992d98b0d6f66c748e7ac81aa5b6 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Fri, 14 Mar 2025 09:41:46 -0400 Subject: [PATCH 03/14] improve syntax --- .../apis/observability/slo/create_slo.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts index b3d1558a63854..f53ad760a670d 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts @@ -136,22 +136,31 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { initials: '1', }); expect(spaceApiResponse.space).property('id'); + const { space: { id: spaceId1 }, } = spaceApiResponse; - const apiResponse = await sloApi.createWithSpace(DEFAULT_SLO, spaceId1, adminRoleAuthc, 200); - expect(apiResponse).property('id'); - const { id } = apiResponse; + const sloApiResponse = await sloApi.createWithSpace( + DEFAULT_SLO, + spaceId1, + adminRoleAuthc, + 200 + ); + expect(sloApiResponse).property('id'); + + const { id } = sloApiResponse; const spaceApiResponse2 = await spaceApi.create({ ...DEFAULT_SPACE_FOR_SLO, name: 'space2', id: 'space2', initials: '2', }); + const { space: { id: spaceId2 }, } = spaceApiResponse; expect(spaceApiResponse2.space).property('id'); + await sloApi.createWithSpace({ ...DEFAULT_SLO, id }, spaceId2, adminRoleAuthc, 409); }); From 0c8df5222710085f18f09992d1807beca209d3d5 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:06:41 +0000 Subject: [PATCH 04/14] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/test/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 925cd59bf3072..51427ce52d801 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -190,5 +190,6 @@ "@kbn/response-ops-rule-params", "@kbn/scout-info", "@kbn/inference-common", + "@kbn/test-suites-xpack", ] } From 61745bbb3717edab265c516c8d9c9dfe8d734dbd Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:30:08 +0000 Subject: [PATCH 05/14] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../observability/plugins/slo/server/services/slo_repository.ts | 2 +- .../deployment_agnostic/apis/observability/slo/fixtures/slo.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index ea4aaef63bd2d..d721a02929863 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -16,7 +16,7 @@ import { SLONotFound } from '../errors'; import { SO_SLO_TYPE } from '../saved_objects'; export interface SLORepository { - exists(id: string, namespaces?: Array): Promise; + exists(id: string, namespaces?: string[]): Promise; create(slo: SLODefinition): Promise; update(slo: SLODefinition): Promise; findAllByIds(ids: string[]): Promise; diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts index b06a63ba64e65..a5393948ab343 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts @@ -6,7 +6,7 @@ */ import { CreateSLOInput } from '@kbn/slo-schema'; -import { SpaceCreate } from '@kbn/test-suites-xpack/common/services/spaces'; +import { SpaceCreate } from '../../../../../../common/services/spaces'; export const DEFAULT_SLO: CreateSLOInput = { name: 'Test SLO for api integration', From 7d865cbce8f99378cad71cd623711747ca9c6f89 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 14 Mar 2025 14:40:30 +0000 Subject: [PATCH 06/14] [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 51427ce52d801..925cd59bf3072 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -190,6 +190,5 @@ "@kbn/response-ops-rule-params", "@kbn/scout-info", "@kbn/inference-common", - "@kbn/test-suites-xpack", ] } From 03f2be8fd7f54d927c53564525a3826270f5d04c Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Fri, 14 Mar 2025 14:20:04 -0400 Subject: [PATCH 07/14] introduce internal so client for slo validation --- .../lib/collectors/integration_tests/fetcher.test.ts | 3 ++- .../plugins/slo/server/routes/slo/create_slo.ts | 7 ++++++- .../plugins/slo/server/services/slo_repository.ts | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts index cad41936ffe72..4c2476e71e0e9 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts @@ -141,9 +141,10 @@ describe('SLO usage collector fetcher', () => { soClient = new SavedObjectsClient( kibanaServer.coreStart.savedObjects.createInternalRepository() ); + loggerMock = createLoggerMock(); - sloRepository = new KibanaSavedObjectsSLORepository(soClient, loggerMock); + sloRepository = new KibanaSavedObjectsSLORepository(soClient, soClient, loggerMock); } async function stopServers() { diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts index 857a8c8987373..ae040c97a2a1c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts @@ -6,6 +6,7 @@ */ import { createSLOParamsSchema } from '@kbn/slo-schema'; +import { SavedObjectsClient } from '@kbn/core/server'; import { CreateSLO, DefaultSummaryTransformManager, @@ -37,8 +38,12 @@ export const createSLORoute = createSloServerRoute({ const scopedClusterClient = core.elasticsearch.client; const esClient = core.elasticsearch.client.asCurrentUser; const soClient = core.savedObjects.client; + const [coreStart] = await corePlugins.getStartServices(); + const internalSoClient = new SavedObjectsClient( + coreStart.savedObjects.createInternalRepository() + ); const basePath = corePlugins.http.basePath; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const repository = new KibanaSavedObjectsSLORepository(soClient, internalSoClient, logger); const [spaceId, dataViewsService] = await Promise.all([ getSpaceId(plugins, request), diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index d721a02929863..aa8abafb43370 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -30,10 +30,14 @@ export interface SLORepository { } export class KibanaSavedObjectsSLORepository implements SLORepository { - constructor(private soClient: SavedObjectsClientContract, private logger: Logger) {} + constructor( + private soClient: SavedObjectsClientContract, + private internalSOClient: SavedObjectsClientContract, + private logger: Logger + ) {} async exists(id: string, namespaces = []) { - const findResponse = await this.soClient.find({ + const findResponse = await this.internalSOClient.find({ type: SO_SLO_TYPE, perPage: 0, filter: `slo.attributes.id:(${id})`, From ccf84c22c347e7b5de92e16ade705c744e62cd88 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Fri, 14 Mar 2025 16:14:18 -0400 Subject: [PATCH 08/14] rework solution --- .../slo/server/routes/slo/create_slo.ts | 5 +++- .../slo/server/services/create_slo.test.ts | 11 +++++-- .../plugins/slo/server/services/create_slo.ts | 4 ++- .../slo/server/services/mocks/index.ts | 7 +++++ .../slo/server/services/slo_repository.ts | 18 +----------- .../slo/server/services/slo_validator.ts | 29 +++++++++++++++++++ 6 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts index ae040c97a2a1c..33a184f4adae2 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts @@ -18,6 +18,7 @@ import { createTransformGenerators } from '../../services/transform_generators'; import { createSloServerRoute } from '../create_slo_server_route'; import { assertPlatinumLicense } from './utils/assert_platinum_license'; import { getSpaceId } from './utils/get_space_id'; +import { KibanaSavedObjectsSLOValidator } from '../../services/slo_validator'; export const createSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos 2023-10-31', @@ -43,7 +44,8 @@ export const createSLORoute = createSloServerRoute({ coreStart.savedObjects.createInternalRepository() ); const basePath = corePlugins.http.basePath; - const repository = new KibanaSavedObjectsSLORepository(soClient, internalSoClient, logger); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const validator = new KibanaSavedObjectsSLOValidator(internalSoClient); const [spaceId, dataViewsService] = await Promise.all([ getSpaceId(plugins, request), @@ -70,6 +72,7 @@ export const createSLORoute = createSloServerRoute({ esClient, scopedClusterClient, repository, + validator, transformManager, summaryTransformManager, logger, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts index e112bfbaf2d3d..17c2a4dd5f79a 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts @@ -18,18 +18,21 @@ import { fiveMinute, oneMinute } from './fixtures/duration'; import { createAPMTransactionErrorRateIndicator, createSLOParams } from './fixtures/slo'; import { createSLORepositoryMock, + createSLOValidatorMock, createSummaryTransformManagerMock, createTransformManagerMock, } from './mocks'; import { SLORepository } from './slo_repository'; import { TransformManager } from './transform_manager'; import { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/types'; +import { SLOValidator } from './slo_validator'; describe('CreateSLO', () => { let mockEsClient: ElasticsearchClientMock; let mockScopedClusterClient: ScopedClusterClientMock; let mockLogger: jest.Mocked; let mockRepository: jest.Mocked; + let mockValidator: jest.Mocked; let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let createSLO: CreateSLO; @@ -41,12 +44,14 @@ describe('CreateSLO', () => { mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockLogger = loggingSystemMock.createLogger(); mockRepository = createSLORepositoryMock(); + mockValidator = createSLOValidatorMock(); mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); createSLO = new CreateSLO( mockEsClient, mockScopedClusterClient, mockRepository, + mockValidator, mockTransformManager, mockSummaryTransformManager, mockLogger, @@ -58,7 +63,7 @@ describe('CreateSLO', () => { describe('happy path', () => { beforeEach(() => { - mockRepository.exists.mockResolvedValue(false); + mockValidator.exists.mockResolvedValue(false); mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); @@ -168,14 +173,14 @@ describe('CreateSLO', () => { describe('unhappy path', () => { beforeEach(() => { - mockRepository.exists.mockResolvedValue(false); + mockValidator.exists.mockResolvedValue(false); mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); }); it('throws a SLOIdConflict error when the SLO already exists', async () => { - mockRepository.exists.mockResolvedValue(true); + mockValidator.exists.mockResolvedValue(true); const sloParams = createSLOParams({ indicator: createAPMTransactionErrorRateIndicator() }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index 2ed10527df185..8c63e16bd7ffd 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -26,6 +26,7 @@ import { validateSLO } from '../domain/services'; import { SLOIdConflict, SecurityException } from '../errors'; import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; +import { SLOValidator } from './slo_validator'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; import { TransformManager } from './transform_manager'; import { assertExpectedIndicatorSourceIndexPrivileges } from './utils/assert_expected_indicator_source_index_privileges'; @@ -36,6 +37,7 @@ export class CreateSLO { private esClient: ElasticsearchClient, private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, + private validator: SLOValidator, private transformManager: TransformManager, private summaryTransformManager: TransformManager, private logger: Logger, @@ -123,7 +125,7 @@ export class CreateSLO { } private async assertSLOInexistant(slo: SLODefinition) { - const exists = await this.repository.exists(slo.id, ['*']); + const exists = await this.validator.exists(slo.id, ['*']); if (exists) { throw new SLOIdConflict(`SLO [${slo.id}] already exists`); } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts index 0b3c1d4d07453..0ee9473ad80c8 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts @@ -11,6 +11,7 @@ import { SLORepository } from '../slo_repository'; import { SummaryClient } from '../summary_client'; import { SummarySearchClient } from '../summary_search_client/types'; import { TransformManager } from '../transform_manager'; +import { SLOValidator } from '../slo_validator'; const createResourceInstallerMock = (): jest.Mocked => { return { @@ -50,6 +51,11 @@ const createSLORepositoryMock = (): jest.Mocked => { findAllByIds: jest.fn(), deleteById: jest.fn(), search: jest.fn(), + }; +}; + +const createSLOValidatorMock = (): jest.Mocked => { + return { exists: jest.fn(), }; }; @@ -77,6 +83,7 @@ export { createTransformManagerMock, createSummaryTransformManagerMock, createSLORepositoryMock, + createSLOValidatorMock, createSummaryClientMock, createSummarySearchClientMock, createBurnRatesClientMock, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts index aa8abafb43370..5c531c1e6d616 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.ts @@ -16,7 +16,6 @@ import { SLONotFound } from '../errors'; import { SO_SLO_TYPE } from '../saved_objects'; export interface SLORepository { - exists(id: string, namespaces?: string[]): Promise; create(slo: SLODefinition): Promise; update(slo: SLODefinition): Promise; findAllByIds(ids: string[]): Promise; @@ -30,22 +29,7 @@ export interface SLORepository { } export class KibanaSavedObjectsSLORepository implements SLORepository { - constructor( - private soClient: SavedObjectsClientContract, - private internalSOClient: SavedObjectsClientContract, - private logger: Logger - ) {} - - async exists(id: string, namespaces = []) { - const findResponse = await this.internalSOClient.find({ - type: SO_SLO_TYPE, - perPage: 0, - filter: `slo.attributes.id:(${id})`, - namespaces: [...namespaces], - }); - - return findResponse.total > 0; - } + constructor(private soClient: SavedObjectsClientContract, private logger: Logger) {} async create(slo: SLODefinition): Promise { await this.soClient.create(SO_SLO_TYPE, toStoredSLO(slo)); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts new file mode 100644 index 0000000000000..90f88f5f56c5d --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts @@ -0,0 +1,29 @@ +/* + * 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 { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { StoredSLODefinition } from '../domain/models'; +import { SO_SLO_TYPE } from '../saved_objects'; + +export interface SLOValidator { + exists(id: string, namespaces?: string[]): Promise; +} + +export class KibanaSavedObjectsSLOValidator implements SLOValidator { + constructor(private internalSOClient: SavedObjectsClientContract) {} + + async exists(id: string, namespaces = []) { + const findResponse = await this.internalSOClient.find({ + type: SO_SLO_TYPE, + perPage: 0, + filter: `slo.attributes.id:(${id})`, + namespaces: [...namespaces], + }); + + return findResponse.total > 0; + } +} From b445717c0080ca53ce6b1d49aa9186db68f88f76 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Fri, 14 Mar 2025 16:46:05 -0400 Subject: [PATCH 09/14] fix tests --- .../lib/collectors/integration_tests/fetcher.test.ts | 2 +- .../plugins/slo/server/routes/slo/inspect_slo.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts index 4c2476e71e0e9..93d8b738571f6 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts @@ -144,7 +144,7 @@ describe('SLO usage collector fetcher', () => { loggerMock = createLoggerMock(); - sloRepository = new KibanaSavedObjectsSLORepository(soClient, soClient, loggerMock); + sloRepository = new KibanaSavedObjectsSLORepository(soClient, loggerMock); } async function stopServers() { diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts index e4af6958d310e..eea0e2be18033 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts @@ -6,6 +6,7 @@ */ import { createSLOParamsSchema } from '@kbn/slo-schema'; +import { SavedObjectsClient } from '@kbn/core/server'; import { CreateSLO, DefaultSummaryTransformManager, @@ -17,6 +18,7 @@ import { createTransformGenerators } from '../../services/transform_generators'; import { createSloServerRoute } from '../create_slo_server_route'; import { assertPlatinumLicense } from './utils/assert_platinum_license'; import { getSpaceId } from './utils/get_space_id'; +import { KibanaSavedObjectsSLOValidator } from '../../services/slo_validator'; export const inspectSLORoute = createSloServerRoute({ endpoint: 'POST /internal/observability/slos/_inspect', @@ -39,7 +41,12 @@ export const inspectSLORoute = createSloServerRoute({ const esClient = core.elasticsearch.client.asCurrentUser; const username = core.security.authc.getCurrentUser()?.username!; const soClient = core.savedObjects.client; + const [coreStart] = await corePlugins.getStartServices(); + const internalSoClient = new SavedObjectsClient( + coreStart.savedObjects.createInternalRepository() + ); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const validator = new KibanaSavedObjectsSLOValidator(internalSoClient); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformGenerators = createTransformGenerators( @@ -62,6 +69,7 @@ export const inspectSLORoute = createSloServerRoute({ esClient, scopedClusterClient, repository, + validator, transformManager, summaryTransformManager, logger, From fde79d68c931a3bb964911733e5281d0839b973f Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Mon, 17 Mar 2025 10:28:15 -0400 Subject: [PATCH 10/14] always validate against all spaces --- .../observability/plugins/slo/server/services/create_slo.ts | 2 +- .../plugins/slo/server/services/slo_validator.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index 8c63e16bd7ffd..0e77a392f531f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -125,7 +125,7 @@ export class CreateSLO { } private async assertSLOInexistant(slo: SLODefinition) { - const exists = await this.validator.exists(slo.id, ['*']); + const exists = await this.validator.exists(slo.id); if (exists) { throw new SLOIdConflict(`SLO [${slo.id}] already exists`); } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts index 90f88f5f56c5d..5c8608981d62c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts @@ -10,18 +10,18 @@ import { StoredSLODefinition } from '../domain/models'; import { SO_SLO_TYPE } from '../saved_objects'; export interface SLOValidator { - exists(id: string, namespaces?: string[]): Promise; + exists(id: string): Promise; } export class KibanaSavedObjectsSLOValidator implements SLOValidator { constructor(private internalSOClient: SavedObjectsClientContract) {} - async exists(id: string, namespaces = []) { + async exists(id: string) { const findResponse = await this.internalSOClient.find({ type: SO_SLO_TYPE, perPage: 0, filter: `slo.attributes.id:(${id})`, - namespaces: [...namespaces], + namespaces: ['*'], }); return findResponse.total > 0; From 34d37f0612d2e6426fd0747ee13e34db813b6f88 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Mon, 17 Mar 2025 12:36:01 -0400 Subject: [PATCH 11/14] simplify solution, remove incompaitble fields for serverless test --- .../slo/server/routes/slo/create_slo.ts | 4 +-- .../slo/server/routes/slo/inspect_slo.ts | 4 +-- .../slo/server/services/create_slo.test.ts | 32 ++++++++++--------- .../plugins/slo/server/services/create_slo.ts | 24 +++++++++++--- .../slo/server/services/mocks/index.ts | 8 ----- .../slo/server/services/slo_validator.ts | 29 ----------------- .../apis/observability/slo/create_slo.ts | 4 +-- .../apis/observability/slo/fixtures/slo.ts | 10 ------ 8 files changed, 39 insertions(+), 76 deletions(-) delete mode 100644 x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts index 33a184f4adae2..304f03221645a 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts @@ -18,7 +18,6 @@ import { createTransformGenerators } from '../../services/transform_generators'; import { createSloServerRoute } from '../create_slo_server_route'; import { assertPlatinumLicense } from './utils/assert_platinum_license'; import { getSpaceId } from './utils/get_space_id'; -import { KibanaSavedObjectsSLOValidator } from '../../services/slo_validator'; export const createSLORoute = createSloServerRoute({ endpoint: 'POST /api/observability/slos 2023-10-31', @@ -45,7 +44,6 @@ export const createSLORoute = createSloServerRoute({ ); const basePath = corePlugins.http.basePath; const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const validator = new KibanaSavedObjectsSLOValidator(internalSoClient); const [spaceId, dataViewsService] = await Promise.all([ getSpaceId(plugins, request), @@ -72,7 +70,7 @@ export const createSLORoute = createSloServerRoute({ esClient, scopedClusterClient, repository, - validator, + internalSoClient, transformManager, summaryTransformManager, logger, diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts index eea0e2be18033..fb9738cfbb293 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts @@ -18,7 +18,6 @@ import { createTransformGenerators } from '../../services/transform_generators'; import { createSloServerRoute } from '../create_slo_server_route'; import { assertPlatinumLicense } from './utils/assert_platinum_license'; import { getSpaceId } from './utils/get_space_id'; -import { KibanaSavedObjectsSLOValidator } from '../../services/slo_validator'; export const inspectSLORoute = createSloServerRoute({ endpoint: 'POST /internal/observability/slos/_inspect', @@ -46,7 +45,6 @@ export const inspectSLORoute = createSloServerRoute({ coreStart.savedObjects.createInternalRepository() ); const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const validator = new KibanaSavedObjectsSLOValidator(internalSoClient); const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); const transformGenerators = createTransformGenerators( @@ -69,7 +67,7 @@ export const inspectSLORoute = createSloServerRoute({ esClient, scopedClusterClient, repository, - validator, + internalSoClient, transformManager, summaryTransformManager, logger, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts index 17c2a4dd5f79a..e5c9b3917da3c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.test.ts @@ -12,27 +12,27 @@ import { loggingSystemMock, ScopedClusterClientMock, } from '@kbn/core/server/mocks'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; import { MockedLogger } from '@kbn/logging-mocks'; import { CreateSLO } from './create_slo'; import { fiveMinute, oneMinute } from './fixtures/duration'; import { createAPMTransactionErrorRateIndicator, createSLOParams } from './fixtures/slo'; import { createSLORepositoryMock, - createSLOValidatorMock, createSummaryTransformManagerMock, createTransformManagerMock, } from './mocks'; import { SLORepository } from './slo_repository'; import { TransformManager } from './transform_manager'; import { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/types'; -import { SLOValidator } from './slo_validator'; +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; describe('CreateSLO', () => { let mockEsClient: ElasticsearchClientMock; let mockScopedClusterClient: ScopedClusterClientMock; + let mockSavedObjectsClient: jest.Mocked; let mockLogger: jest.Mocked; let mockRepository: jest.Mocked; - let mockValidator: jest.Mocked; let mockTransformManager: jest.Mocked; let mockSummaryTransformManager: jest.Mocked; let createSLO: CreateSLO; @@ -42,16 +42,16 @@ describe('CreateSLO', () => { beforeEach(() => { mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); + mockSavedObjectsClient = savedObjectsClientMock.create(); mockLogger = loggingSystemMock.createLogger(); mockRepository = createSLORepositoryMock(); - mockValidator = createSLOValidatorMock(); mockTransformManager = createTransformManagerMock(); mockSummaryTransformManager = createSummaryTransformManagerMock(); createSLO = new CreateSLO( mockEsClient, mockScopedClusterClient, mockRepository, - mockValidator, + mockSavedObjectsClient, mockTransformManager, mockSummaryTransformManager, mockLogger, @@ -63,10 +63,15 @@ describe('CreateSLO', () => { describe('happy path', () => { beforeEach(() => { - mockValidator.exists.mockResolvedValue(false); mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); + mockSavedObjectsClient.find.mockResolvedValue({ + saved_objects: [], + per_page: 20, + page: 0, + total: 0, + }); }); it('calls the expected services', async () => { @@ -173,18 +178,15 @@ describe('CreateSLO', () => { describe('unhappy path', () => { beforeEach(() => { - mockValidator.exists.mockResolvedValue(false); mockEsClient.security.hasPrivileges.mockResolvedValue({ has_all_requested: true, } as SecurityHasPrivilegesResponse); - }); - - it('throws a SLOIdConflict error when the SLO already exists', async () => { - mockValidator.exists.mockResolvedValue(true); - - const sloParams = createSLOParams({ indicator: createAPMTransactionErrorRateIndicator() }); - - await expect(createSLO.execute(sloParams)).rejects.toThrowError(/SLO \[.*\] already exists/); + mockSavedObjectsClient.find.mockResolvedValue({ + saved_objects: [], + per_page: 20, + page: 0, + total: 0, + }); }); it('throws a SecurityException error when the user does not have the required privileges', async () => { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index 0e77a392f531f..f2684ec461aee 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -6,7 +6,13 @@ */ import { IngestPutPipelineRequest } from '@elastic/elasticsearch/lib/api/types'; import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; -import { ElasticsearchClient, IBasePath, IScopedClusterClient, Logger } from '@kbn/core/server'; +import { + ElasticsearchClient, + IBasePath, + IScopedClusterClient, + Logger, + SavedObjectsClientContract, +} from '@kbn/core/server'; import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema'; import { asyncForEach } from '@kbn/std'; import { merge } from 'lodash'; @@ -21,23 +27,23 @@ import { } from '../../common/constants'; import { getSLIPipelineTemplate } from '../assets/ingest_templates/sli_pipeline_template'; import { getSummaryPipelineTemplate } from '../assets/ingest_templates/summary_pipeline_template'; -import { Duration, DurationUnit, SLODefinition } from '../domain/models'; +import { Duration, DurationUnit, SLODefinition, StoredSLODefinition } from '../domain/models'; import { validateSLO } from '../domain/services'; import { SLOIdConflict, SecurityException } from '../errors'; import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; -import { SLOValidator } from './slo_validator'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; import { TransformManager } from './transform_manager'; import { assertExpectedIndicatorSourceIndexPrivileges } from './utils/assert_expected_indicator_source_index_privileges'; import { getTransformQueryComposite } from './utils/get_transform_compite_query'; +import { SO_SLO_TYPE } from '../saved_objects'; export class CreateSLO { constructor( private esClient: ElasticsearchClient, private scopedClusterClient: IScopedClusterClient, private repository: SLORepository, - private validator: SLOValidator, + private internalSOClient: SavedObjectsClientContract, private transformManager: TransformManager, private summaryTransformManager: TransformManager, private logger: Logger, @@ -125,7 +131,15 @@ export class CreateSLO { } private async assertSLOInexistant(slo: SLODefinition) { - const exists = await this.validator.exists(slo.id); + const findResponse = await this.internalSOClient.find({ + type: SO_SLO_TYPE, + perPage: 0, + filter: `slo.attributes.id:(${slo.id})`, + namespaces: ['*'], + }); + + const exists = findResponse.total > 0; + if (exists) { throw new SLOIdConflict(`SLO [${slo.id}] already exists`); } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts index 0ee9473ad80c8..eee093686fe25 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/mocks/index.ts @@ -11,7 +11,6 @@ import { SLORepository } from '../slo_repository'; import { SummaryClient } from '../summary_client'; import { SummarySearchClient } from '../summary_search_client/types'; import { TransformManager } from '../transform_manager'; -import { SLOValidator } from '../slo_validator'; const createResourceInstallerMock = (): jest.Mocked => { return { @@ -54,12 +53,6 @@ const createSLORepositoryMock = (): jest.Mocked => { }; }; -const createSLOValidatorMock = (): jest.Mocked => { - return { - exists: jest.fn(), - }; -}; - const createSummaryClientMock = (): jest.Mocked => { return { computeSummary: jest.fn(), @@ -83,7 +76,6 @@ export { createTransformManagerMock, createSummaryTransformManagerMock, createSLORepositoryMock, - createSLOValidatorMock, createSummaryClientMock, createSummarySearchClientMock, createBurnRatesClientMock, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts deleted file mode 100644 index 5c8608981d62c..0000000000000 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_validator.ts +++ /dev/null @@ -1,29 +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 { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import { StoredSLODefinition } from '../domain/models'; -import { SO_SLO_TYPE } from '../saved_objects'; - -export interface SLOValidator { - exists(id: string): Promise; -} - -export class KibanaSavedObjectsSLOValidator implements SLOValidator { - constructor(private internalSOClient: SavedObjectsClientContract) {} - - async exists(id: string) { - const findResponse = await this.internalSOClient.find({ - type: SO_SLO_TYPE, - perPage: 0, - filter: `slo.attributes.id:(${id})`, - namespaces: ['*'], - }); - - return findResponse.total > 0; - } -} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts index ecf40b085290f..a71c24f5cd9f0 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/create_slo.ts @@ -11,7 +11,7 @@ import { RoleCredentials } from '@kbn/ftr-common-functional-services'; import { getSLOSummaryTransformId, getSLOTransformId } from '@kbn/slo-plugin/common/constants'; import { omit } from 'lodash'; import { DeploymentAgnosticFtrProviderContext } from '../../../ftr_provider_context'; -import { DEFAULT_SLO, DEFAULT_SPACE_FOR_SLO } from './fixtures/slo'; +import { DEFAULT_SLO } from './fixtures/slo'; import { DATA_FORGE_CONFIG } from './helpers/dataforge'; import { TransformHelper, createTransformHelper } from './helpers/transform'; @@ -126,7 +126,6 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { it('creates two SLOs with matching ids across different spaces', async () => { const spaceApiResponse = await spaceApi.create({ - ...DEFAULT_SPACE_FOR_SLO, name: 'space1', id: 'space1', initials: '1', @@ -146,7 +145,6 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { const { id } = sloApiResponse; const spaceApiResponse2 = await spaceApi.create({ - ...DEFAULT_SPACE_FOR_SLO, name: 'space2', id: 'space2', initials: '2', diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts index a5393948ab343..dfc216760644c 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/fixtures/slo.ts @@ -6,7 +6,6 @@ */ import { CreateSLOInput } from '@kbn/slo-schema'; -import { SpaceCreate } from '../../../../../../common/services/spaces'; export const DEFAULT_SLO: CreateSLOInput = { name: 'Test SLO for api integration', @@ -32,12 +31,3 @@ export const DEFAULT_SLO: CreateSLOInput = { tags: ['test'], groupBy: 'tags', }; - -export const DEFAULT_SPACE_FOR_SLO: SpaceCreate = { - name: 'default', - id: 'default', - initials: 'D', - color: '#A6EDEA', - disabledFeatures: [], - solution: 'classic', -}; From 14461249e6b30b2d55a39a5dc59555445e194744 Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Mon, 17 Mar 2025 12:37:18 -0400 Subject: [PATCH 12/14] remove empty line --- .../slo/server/lib/collectors/integration_tests/fetcher.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts index 93d8b738571f6..cad41936ffe72 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/integration_tests/fetcher.test.ts @@ -141,7 +141,6 @@ describe('SLO usage collector fetcher', () => { soClient = new SavedObjectsClient( kibanaServer.coreStart.savedObjects.createInternalRepository() ); - loggerMock = createLoggerMock(); sloRepository = new KibanaSavedObjectsSLORepository(soClient, loggerMock); From b665609c5d54a2f0f3df99e12208608eb7a0b6fd Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Mon, 17 Mar 2025 12:38:44 -0400 Subject: [PATCH 13/14] remove export no longer used --- x-pack/test/common/services/spaces.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/common/services/spaces.ts b/x-pack/test/common/services/spaces.ts index f9d52701648b8..67da912fb6a54 100644 --- a/x-pack/test/common/services/spaces.ts +++ b/x-pack/test/common/services/spaces.ts @@ -16,7 +16,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; const chance = new Chance(); -export interface SpaceCreate { +interface SpaceCreate { name?: string; id?: string; description?: string; From 0e08115988480c30424d45ae6174469981769b4b Mon Sep 17 00:00:00 2001 From: Bailey Cash Date: Mon, 17 Mar 2025 12:46:50 -0400 Subject: [PATCH 14/14] use spaces constant --- .../observability/plugins/slo/server/services/create_slo.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index f2684ec461aee..c85c7a984860e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -17,6 +17,7 @@ import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema'; import { asyncForEach } from '@kbn/std'; import { merge } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; +import { ALL_SPACES_ID } from '@kbn/spaces-plugin/common/constants'; import { SLO_MODEL_VERSION, SUMMARY_TEMP_INDEX_NAME, @@ -135,7 +136,7 @@ export class CreateSLO { type: SO_SLO_TYPE, perPage: 0, filter: `slo.attributes.id:(${slo.id})`, - namespaces: ['*'], + namespaces: [ALL_SPACES_ID], }); const exists = findResponse.total > 0;