feat(slo): return early when no update is made (#169546)

This commit is contained in:
Kevin Delemme 2023-10-23 15:26:20 -04:00 committed by GitHub
parent 416a95417d
commit 2bbfd64668
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 2 deletions

View file

@ -7,6 +7,8 @@
import { ElasticsearchClient } from '@kbn/core/server'; import { ElasticsearchClient } from '@kbn/core/server';
import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks';
import { UpdateSLOParams } from '@kbn/slo-schema';
import { cloneDeep, pick, omit } from 'lodash';
import { import {
getSLOTransformId, getSLOTransformId,
@ -38,6 +40,123 @@ describe('UpdateSLO', () => {
updateSLO = new UpdateSLO(mockRepository, mockTransformManager, mockEsClient); updateSLO = new UpdateSLO(mockRepository, mockTransformManager, mockEsClient);
}); });
describe('when the update payload does not change the original SLO', () => {
function expectNoCallsToAnyMocks() {
expect(mockTransformManager.stop).not.toBeCalled();
expect(mockTransformManager.uninstall).not.toBeCalled();
expect(mockTransformManager.install).not.toBeCalled();
expect(mockTransformManager.preview).not.toBeCalled();
expect(mockTransformManager.start).not.toBeCalled();
expect(mockEsClient.deleteByQuery).not.toBeCalled();
}
it('returns early with a full identical SLO payload', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = omit(cloneDeep(slo), [
'id',
'revision',
'createdAt',
'updatedAt',
'enabled',
]);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical name', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['name']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical indicator', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['indicator']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical timeWindow', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['timeWindow']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical budgetingMethod', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['budgetingMethod']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical description', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['description']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical groupBy', async () => {
const slo = createSLO({ groupBy: 'project.id' });
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['groupBy']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical objective', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['objective']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical tags', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['tags']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
it('returns early with identical settings', async () => {
const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo);
const updatePayload: UpdateSLOParams = pick(cloneDeep(slo), ['settings']);
await updateSLO.execute(slo.id, updatePayload);
expectNoCallsToAnyMocks();
});
});
it('updates the settings correctly', async () => { it('updates the settings correctly', async () => {
const slo = createSLO(); const slo = createSLO();
mockRepository.findById.mockResolvedValueOnce(slo); mockRepository.findById.mockResolvedValueOnce(slo);

View file

@ -7,6 +7,7 @@
import { ElasticsearchClient } from '@kbn/core/server'; import { ElasticsearchClient } from '@kbn/core/server';
import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema'; import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema';
import { isEqual } from 'lodash';
import { import {
getSLOTransformId, getSLOTransformId,
SLO_DESTINATION_INDEX_PATTERN, SLO_DESTINATION_INDEX_PATTERN,
@ -28,10 +29,17 @@ export class UpdateSLO {
public async execute(sloId: string, params: UpdateSLOParams): Promise<UpdateSLOResponse> { public async execute(sloId: string, params: UpdateSLOParams): Promise<UpdateSLOResponse> {
const originalSlo = await this.repository.findById(sloId); const originalSlo = await this.repository.findById(sloId);
const updatedSlo: SLO = Object.assign({}, originalSlo, params, { let updatedSlo: SLO = Object.assign({}, originalSlo, params, {
groupBy: !!params.groupBy ? params.groupBy : originalSlo.groupBy,
});
if (isEqual(originalSlo, updatedSlo)) {
return this.toResponse(originalSlo);
}
updatedSlo = Object.assign(updatedSlo, {
updatedAt: new Date(), updatedAt: new Date(),
revision: originalSlo.revision + 1, revision: originalSlo.revision + 1,
groupBy: !!params.groupBy ? params.groupBy : originalSlo.groupBy,
}); });
validateSLO(updatedSlo); validateSLO(updatedSlo);