From ff052f92d174cb5a98e76567877712043afaba21 Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 09:16:39 +0300 Subject: [PATCH 1/8] feat: aggregate experiments in the report --- .../models/chaosExperimentsManager.js | 6 +- .../models/database/databaseConnector.js | 10 +- .../database/sequelize/sequelizeConnector.js | 12 +- src/reports/models/aggregateReportManager.js | 20 +++ .../sequelize/sequelizeConnector-test.js | 21 +++- .../models/finalReportGenerator-test.js | 115 +++++++++++++++++- 6 files changed, 167 insertions(+), 17 deletions(-) diff --git a/src/chaos-experiments/models/chaosExperimentsManager.js b/src/chaos-experiments/models/chaosExperimentsManager.js index 6ef808bd4..a619f743c 100644 --- a/src/chaos-experiments/models/chaosExperimentsManager.js +++ b/src/chaos-experiments/models/chaosExperimentsManager.js @@ -92,5 +92,9 @@ module.exports.runChaosExperiment = async (kubernetesChaosConfig, jobExperimentI }; module.exports.getFutureJobExperiments = async function (timestamp, contextId) { - return databaseConnector.getFutureJobExperiments(contextId); + return databaseConnector.getFutureJobExperiments(timestamp, contextId); +}; + +module.exports.getChaosJobExperimentsByJobId = async function (jobId, contextId) { + return databaseConnector.getChaosJobExperimentsByJobId(jobId, contextId); }; diff --git a/src/chaos-experiments/models/database/databaseConnector.js b/src/chaos-experiments/models/database/databaseConnector.js index 04783f22f..3702c2862 100644 --- a/src/chaos-experiments/models/database/databaseConnector.js +++ b/src/chaos-experiments/models/database/databaseConnector.js @@ -9,7 +9,7 @@ module.exports = { getChaosExperimentsByIds, deleteChaosExperiment, insertChaosJobExperiment, - getChaosJobExperimentById, + getChaosJobExperimentsByJobId, getChaosJobExperimentByJobId, getFutureJobExperiments, setChaosJobExperimentTriggered, @@ -57,16 +57,16 @@ async function insertChaosJobExperiment(jobExperimentId, jobId, experimentId, st return databaseConnector.insertChaosJobExperiment(jobExperimentId, jobId, experimentId, startTime, endTime, contextId); } -async function getChaosJobExperimentById(jobExperimentId, contextId) { - return databaseConnector.getChaosJobExperimentById(jobExperimentId, contextId); +async function getChaosJobExperimentsByJobId(jobExperimentId, contextId) { + return databaseConnector.getChaosJobExperimentsByJobId(jobExperimentId, contextId); } async function getChaosJobExperimentByJobId(jobId, contextId) { return databaseConnector.getChaosJobExperimentById(jobId, contextId); } -async function getFutureJobExperiments(contextId) { - return databaseConnector.getFutureJobExperiments(contextId); +async function getFutureJobExperiments(timestamp, contextId) { + return databaseConnector.getFutureJobExperiments(timestamp, contextId); } async function setChaosJobExperimentTriggered(jobExperimentId, isTriggered, contextId) { diff --git a/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js b/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js index b556c01c5..7da590f4c 100644 --- a/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js +++ b/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js @@ -17,7 +17,7 @@ module.exports = { updateChaosExperiment, insertChaosJobExperiment, getChaosJobExperimentById, - getChaosJobExperimentByJobId, + getChaosJobExperimentsByJobId, getFutureJobExperiments, setChaosJobExperimentTriggered }; @@ -159,7 +159,7 @@ async function getChaosJobExperimentById(jobExperimentId, contextId) { return chaosExperiment; } -async function getChaosJobExperimentByJobId(jobId, contextId) { +async function getChaosJobExperimentsByJobId(jobId, contextId) { const options = { where: { job_id: jobId } }; @@ -168,11 +168,9 @@ async function getChaosJobExperimentByJobId(jobId, contextId) { options.where.context_id = contextId; } - let chaosExperiment = await _getChaosJobExperiment(options); - if (chaosExperiment) { - chaosExperiment = chaosExperiment.get(); - } - return chaosExperiment; + const chaosJobExperimentModel = client.model(CHAOS_JOB_EXPERIMENTS_TABLE_NAME); + const allChaosJobExperiments = await chaosJobExperimentModel.findAll(options); + return allChaosJobExperiments; } async function getFutureJobExperiments(timestamp, contextId) { diff --git a/src/reports/models/aggregateReportManager.js b/src/reports/models/aggregateReportManager.js index ccc7185f9..d9c3a3858 100644 --- a/src/reports/models/aggregateReportManager.js +++ b/src/reports/models/aggregateReportManager.js @@ -5,6 +5,7 @@ const math = require('mathjs'); const logger = require('../../common/logger'); const databaseConnector = require('./databaseConnector'); +const chaosExperimentsManager = require('../../chaos-experiments/models/chaosExperimentsManager'); const constants = require('../utils/constants'); const STATS_INTERVAL = 30; @@ -15,6 +16,7 @@ module.exports = { async function aggregateReport(report) { let stats = await databaseConnector.getStats(report.test_id, report.report_id); + const experiments = await getChaosExperiments(report.job_id); if (stats.length === 0) { const errorMessage = `Can not generate aggregate report as there are no statistics yet for testId: ${report.test_id} and reportId: ${report.report_id}`; @@ -35,6 +37,7 @@ async function aggregateReport(report) { reportInput.revision_id = report.revision_id; reportInput.score = report.score; reportInput.benchmark_weights_data = report.benchmark_weights_data; + reportInput.experiments = experiments; reportInput.notes = report.notes; reportInput.status = mapReportStatus(report.status); @@ -63,6 +66,23 @@ async function aggregateReport(report) { return reportInput; } +async function getChaosExperiments(job_id) { + const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(job_id); + const uniqueExperimentIds = [...new Set(chaosJobExperiments.map(jobExperiment => jobExperiment.experiment_id))]; + const chaosExperiments = await chaosExperimentsManager.getChaosExperimentsByIds(uniqueExperimentIds); + const mappedChaosJobExperiments = chaosJobExperiments.map((jobExperiment) => { + const chaosExperiment = chaosExperiments.find((experiment) => experiment.id === jobExperiment.experiment_id && jobExperiment.is_triggered); + return { + kind: chaosExperiment.kubeObject.kind, + name: chaosExperiment.name, + id: chaosExperiment.id, + start_time: jobExperiment.start_time, + end_time: jobExperiment.end_time + }; + }); + return mappedChaosJobExperiments; +} + function createAggregateManually(listOfStats) { const requestMedians = [], requestMaxs = [], requestMins = [], scenario95 = [], scenario99 = [], request95 = [], request99 = [], scenarioMins = [], scenarioMaxs = [], scenarioMedians = []; diff --git a/tests/unit-tests/chaos-experiments/sequelize/sequelizeConnector-test.js b/tests/unit-tests/chaos-experiments/sequelize/sequelizeConnector-test.js index c1c356eaa..c8bedec8b 100644 --- a/tests/unit-tests/chaos-experiments/sequelize/sequelizeConnector-test.js +++ b/tests/unit-tests/chaos-experiments/sequelize/sequelizeConnector-test.js @@ -140,7 +140,7 @@ describe('Sequelize client tests', function () { should(sequelizeGetStub.args[0][0]).containDeep({ where: { name: experimentName } }); }); }); - describe('Get ChaosExperimentsById', () => { + describe('Get ChaosExperimentsByIds', () => { it('Validate sequelize passed arguments', async () => { sequelizeGetStub.returns([experiment]); const experimentIds = ['1234', '4321']; @@ -226,15 +226,30 @@ describe('Sequelize client tests', function () { should(sequelizeGetStub.args[0][0]).containDeep({ where: { id: jobExperimentId } }); }); }); - describe('getChaosJobExperimentByJobId', function() { + describe('getChaosJobExperimentsByJobId', function() { it('Validate sequelize passed arguments', async () => { sequelizeGetStub.returns([jobExperiment]); const experimentJobId = experiment.job_id; - await sequelizeConnector.getChaosJobExperimentByJobId(experimentJobId); + await sequelizeConnector.getChaosJobExperimentsByJobId(experimentJobId); should(sequelizeGetStub.calledOnce).eql(true); should(sequelizeGetStub.args[0][0]).containDeep({ where: { job_id: experimentJobId } }); }); }); + describe('getFutureJobExperiments', function() { + it('Validate sequelize passed arguments', async () => { + sequelizeGetStub.returns([jobExperiment]); + const timestamp = Date.now(); + await sequelizeConnector.getFutureJobExperiments(timestamp, 'contextId'); + should(sequelizeGetStub.calledOnce).eql(true); + should(sequelizeGetStub.args[0][0]).deepEqual({ + where: { + is_triggered: false, + start_time: {}, + context_id: 'contextId' + } + }); + }); + }); }); describe('Set job experiment is triggered', () => { diff --git a/tests/unit-tests/reporter/models/finalReportGenerator-test.js b/tests/unit-tests/reporter/models/finalReportGenerator-test.js index 6114c9e9e..1a49cdd4a 100644 --- a/tests/unit-tests/reporter/models/finalReportGenerator-test.js +++ b/tests/unit-tests/reporter/models/finalReportGenerator-test.js @@ -6,6 +6,7 @@ const rewire = require('rewire'); const logger = require('../../../../src/common/logger'); const aggregateReportGenerator = rewire('../../../../src/reports/models/aggregateReportGenerator'); const aggregateReportManager = rewire('../../../../src/reports/models/aggregateReportManager'); +const chaosExperimentsManager = require('../../../../src/chaos-experiments/models/chaosExperimentsManager'); const databaseConnector = require('../../../../src/reports/models/databaseConnector'); const reportsManager = require('../../../../src/reports/models/reportsManager'); @@ -17,17 +18,26 @@ const REPORT = { test_name: 'some_test_name', webhooks: ['http://www.zooz.com'], arrival_rate: 100, + job_id: 'job_id', duration: 10, environment: 'test' }; describe('Artillery report generator test', () => { - let sandbox, databaseConnectorGetStatsStub, loggerErrorStub, loggerWarnStub, reportsManagerGetReportStub; + let sandbox, + databaseConnectorGetStatsStub, + getJobExperimentsStubByJobIdStub, + getChaosExperimentsByIdsStub, + loggerErrorStub, + loggerWarnStub, + reportsManagerGetReportStub; before(() => { sandbox = sinon.sandbox.create(); databaseConnectorGetStatsStub = sandbox.stub(databaseConnector, 'getStats'); reportsManagerGetReportStub = sandbox.stub(reportsManager, 'getReport'); + getJobExperimentsStubByJobIdStub = sandbox.stub(chaosExperimentsManager, 'getChaosJobExperimentsByJobId'); + getChaosExperimentsByIdsStub = sandbox.stub(chaosExperimentsManager, 'getChaosExperimentsByIds'); loggerErrorStub = sandbox.stub(logger, 'error'); loggerWarnStub = sandbox.stub(logger, 'warn'); }); @@ -48,6 +58,7 @@ describe('Artillery report generator test', () => { it('create aggregate report when there is only intermediate rows', async () => { databaseConnectorGetStatsStub.resolves(SINGLE_RUNNER_INTERMEDIATE_ROWS); + getJobExperimentsStubByJobIdStub.resolves([]); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); should(reportOutput.parallelism).eql(1); @@ -57,6 +68,7 @@ describe('Artillery report generator test', () => { const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); statsWithUnknownData.push({ phase_status: 'some_unknown_phase', data: JSON.stringify({}) }); databaseConnectorGetStatsStub.resolves(statsWithUnknownData); + getJobExperimentsStubByJobIdStub.resolves([]); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); should(reportOutput.parallelism).eql(1); @@ -72,6 +84,38 @@ describe('Artillery report generator test', () => { loggerWarnStub.callCount.should.eql(1); }); + + it('create final report successfully with chaos experiments', async function() { + const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); + statsWithUnknownData.push({ phase_status: 'intermediate', data: 'unsupported data type' }); + databaseConnectorGetStatsStub.resolves(statsWithUnknownData); + getJobExperimentsStubByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); + getChaosExperimentsByIdsStub.resolves(CHAOS_EXPERIMENTS_ROWS); + const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); + should(reportOutput.experiments).deepEqual([ + { + kind: CHAOS_EXPERIMENTS_ROWS[0].kubeObject.kind, + name: CHAOS_EXPERIMENTS_ROWS[0].name, + id: JOB_EXPERIMENTS_ROWS[0].experiment_id, + start_time: JOB_EXPERIMENTS_ROWS[0].start_time, + end_time: JOB_EXPERIMENTS_ROWS[0].end_time + }, + { + kind: CHAOS_EXPERIMENTS_ROWS[1].kubeObject.kind, + name: CHAOS_EXPERIMENTS_ROWS[1].name, + id: JOB_EXPERIMENTS_ROWS[1].experiment_id, + start_time: JOB_EXPERIMENTS_ROWS[1].start_time, + end_time: JOB_EXPERIMENTS_ROWS[1].end_time + }, + { + kind: CHAOS_EXPERIMENTS_ROWS[2].kubeObject.kind, + name: CHAOS_EXPERIMENTS_ROWS[2].name, + id: JOB_EXPERIMENTS_ROWS[2].experiment_id, + start_time: JOB_EXPERIMENTS_ROWS[2].start_time, + end_time: JOB_EXPERIMENTS_ROWS[2].end_time + } + ]); + }); }); describe('Happy flows - With parallelism', function () { @@ -86,6 +130,7 @@ describe('Artillery report generator test', () => { const firstStatsTimestamp = JSON.parse(PARALLEL_INTERMEDIATE_ROWS[0].data).timestamp; reportsManagerGetReportStub.resolves(REPORT); + getJobExperimentsStubByJobIdStub.resolves([]); REPORT.start_time = new Date(new Date(firstStatsTimestamp).getTime() - (STATS_INTERVAL * 1000)); databaseConnectorGetStatsStub.resolves(PARALLEL_INTERMEDIATE_ROWS); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); @@ -233,9 +278,42 @@ describe('Artillery report generator test', () => { testShouldFail.should.eql(false, 'Test action was supposed to get exception'); }); + + it('create final report fails when get experiments returns error on get job experiments', async () => { + databaseConnectorGetStatsStub.resolves(SINGLE_RUNNER_INTERMEDIATE_ROWS); + reportsManagerGetReportStub.rejects(new Error('Database failure')); + + let testShouldFail = true; + try { + await aggregateReportGenerator.createAggregateReport('testId', 'reportId'); + } catch (error) { + testShouldFail = false; + error.message.should.eql('Database failure'); + } + + testShouldFail.should.eql(false, 'Test action was supposed to get exception'); + }); + + it('create final report fails when get experiments returns error on get chaos experiments', async () => { + databaseConnectorGetStatsStub.resolves(SINGLE_RUNNER_INTERMEDIATE_ROWS); + getJobExperimentsStubByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); + getChaosExperimentsByIdsStub.rejects(new Error('Database failure')); + + let testShouldFail = true; + try { + await aggregateReportGenerator.createAggregateReport('testId', 'reportId'); + } catch (error) { + testShouldFail = false; + error.message.should.eql('Database failure'); + } + + testShouldFail.should.eql(false, 'Test action was supposed to get exception'); + }); }); }); +const timestamp = Date.now(); + const SINGLE_RUNNER_INTERMEDIATE_ROWS = [{ test_id: 'cb7d7862-55c2-4a9b-bcec-d41d54101836', report_id: 'b6489011-2073-4998-91cc-fd62f8b927f7', @@ -337,3 +415,38 @@ const PARALLEL_INTERMEDIATE_ROWS = [ data: '{"timestamp":"2019-03-10T17:24:33.043Z","scenariosCreated":300,"scenariosCompleted":300,"requestsCompleted":300,"latency":{"min":59.5,"max":98.3,"median":61.3,"p95":72.9,"p99":84},"rps":{"count":300,"mean":20},"scenarioDuration":{"min":60,"max":98.9,"median":61.9,"p95":73.5,"p99":84.5},"scenarioCounts":{"Get response code 200":300},"errors":{},"codes":{"200":300},"matches":0,"customStats":{},"counters":{},"concurrency":1,"pendingRequests":1,"scenariosAvoided":0}' } ]; + +const JOB_EXPERIMENTS_ROWS = [{ + job_id: REPORT.job_id, + experiment_id: '1234-abc-5678', + start_time: timestamp, + end_time: timestamp + 100 +}, +{ + job_id: REPORT.job_id, + experiment_id: 'abcd-1234-efgh', + start_time: timestamp, + end_time: timestamp + 200 +}, +{ + job_id: REPORT.job_id, + experiment_id: '4321-abc-5678', + start_time: timestamp, + end_time: timestamp + 300 +}]; + +const CHAOS_EXPERIMENTS_ROWS = [{ + id: '1234-abc-5678', + name: 'first-experiment', + kubeObject: { kind: 'PodChaos' } +}, +{ + id: 'abcd-1234-efgh', + name: 'second-experiment', + kubeObject: { kind: 'DNSChaos' } +}, +{ + id: '4321-abc-5678', + name: 'third-experiment', + kubeObject: { kind: 'IOChaos' } +}]; From 44a77663693e83c5dbae4c29b6024e27ad7543fe Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 14:43:48 +0300 Subject: [PATCH 2/8] feat: aggregate experiments in the report --- .../models/database/sequelize/sequelizeConnector.js | 12 +++++------- src/reports/models/aggregateReportManager.js | 9 +++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js b/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js index 7da590f4c..ae11fa729 100644 --- a/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js +++ b/src/chaos-experiments/models/database/sequelize/sequelizeConnector.js @@ -70,11 +70,10 @@ async function getChaosExperimentById(experimentId, contextId) { options.where.context_id = contextId; } - let chaosExperiment = await _getChaosExperiment(options); + const chaosExperiment = await _getChaosExperiment(options); if (chaosExperiment) { - chaosExperiment = chaosExperiment.get(); + return chaosExperiment.get(); } - return chaosExperiment; } async function getChaosExperimentsByIds(experimentIds, exclude, contextId) { @@ -152,11 +151,10 @@ async function getChaosJobExperimentById(jobExperimentId, contextId) { options.where.context_id = contextId; } - let chaosExperiment = await _getChaosJobExperiment(options); - if (chaosExperiment) { - chaosExperiment = chaosExperiment.get(); + const chaosJobExperiment = await _getChaosJobExperiment(options); + if (chaosJobExperiment) { + return chaosJobExperiment.get(); } - return chaosExperiment; } async function getChaosJobExperimentsByJobId(jobId, contextId) { diff --git a/src/reports/models/aggregateReportManager.js b/src/reports/models/aggregateReportManager.js index d9c3a3858..872c1181b 100644 --- a/src/reports/models/aggregateReportManager.js +++ b/src/reports/models/aggregateReportManager.js @@ -7,6 +7,11 @@ const logger = require('../../common/logger'); const databaseConnector = require('./databaseConnector'); const chaosExperimentsManager = require('../../chaos-experiments/models/chaosExperimentsManager'); const constants = require('../utils/constants'); +const configHandler = require('../../configManager/models/configHandler'); +const { + CONFIG, + KUBERNETES +} = require('../../common/consts'); const STATS_INTERVAL = 30; @@ -67,6 +72,10 @@ async function aggregateReport(report) { } async function getChaosExperiments(job_id) { + const jobPlatform = await configHandler.getConfigValue(CONFIG.JOB_PLATFORM); + if (jobPlatform.toUpperCase() !== KUBERNETES) { + return; + } const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(job_id); const uniqueExperimentIds = [...new Set(chaosJobExperiments.map(jobExperiment => jobExperiment.experiment_id))]; const chaosExperiments = await chaosExperimentsManager.getChaosExperimentsByIds(uniqueExperimentIds); From b1a69091ab4101cfc8def7b7ff63dcdd5138a2fc Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 15:37:51 +0300 Subject: [PATCH 3/8] feat: aggregate experiments in the report --- src/reports/models/aggregateReportManager.js | 22 +++++++++++--------- ui/src/features/components/JobForm/index.js | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/reports/models/aggregateReportManager.js b/src/reports/models/aggregateReportManager.js index 872c1181b..cd9467c5a 100644 --- a/src/reports/models/aggregateReportManager.js +++ b/src/reports/models/aggregateReportManager.js @@ -21,7 +21,7 @@ module.exports = { async function aggregateReport(report) { let stats = await databaseConnector.getStats(report.test_id, report.report_id); - const experiments = await getChaosExperiments(report.job_id); + const experiments = await getChaosExperimentsByJobId(report.job_id); if (stats.length === 0) { const errorMessage = `Can not generate aggregate report as there are no statistics yet for testId: ${report.test_id} and reportId: ${report.report_id}`; @@ -71,23 +71,25 @@ async function aggregateReport(report) { return reportInput; } -async function getChaosExperiments(job_id) { +async function getChaosExperimentsByJobId(jobId) { const jobPlatform = await configHandler.getConfigValue(CONFIG.JOB_PLATFORM); if (jobPlatform.toUpperCase() !== KUBERNETES) { return; } - const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(job_id); + const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(jobId); const uniqueExperimentIds = [...new Set(chaosJobExperiments.map(jobExperiment => jobExperiment.experiment_id))]; const chaosExperiments = await chaosExperimentsManager.getChaosExperimentsByIds(uniqueExperimentIds); const mappedChaosJobExperiments = chaosJobExperiments.map((jobExperiment) => { const chaosExperiment = chaosExperiments.find((experiment) => experiment.id === jobExperiment.experiment_id && jobExperiment.is_triggered); - return { - kind: chaosExperiment.kubeObject.kind, - name: chaosExperiment.name, - id: chaosExperiment.id, - start_time: jobExperiment.start_time, - end_time: jobExperiment.end_time - }; + if (chaosExperiment) { + return { + kind: chaosExperiment.kubeObject.kind, + name: chaosExperiment.name, + id: chaosExperiment.id, + start_time: jobExperiment.start_time, + end_time: jobExperiment.end_time + }; + } }); return mappedChaosJobExperiments; } diff --git a/ui/src/features/components/JobForm/index.js b/ui/src/features/components/JobForm/index.js index b048de530..ae8903b40 100644 --- a/ui/src/features/components/JobForm/index.js +++ b/ui/src/features/components/JobForm/index.js @@ -212,7 +212,7 @@ class Form extends React.Component { experiment name: {experiment.experiment_name} start after: - {experiment.start_after / ONE_MIN_MS} seconds + {experiment.start_after / ONE_MIN_MS} minutes Date: Mon, 2 Oct 2023 15:52:39 +0300 Subject: [PATCH 4/8] feat: aggregate experiments in the report --- .../reporter/models/finalReportGenerator-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit-tests/reporter/models/finalReportGenerator-test.js b/tests/unit-tests/reporter/models/finalReportGenerator-test.js index 1a49cdd4a..39856aa7a 100644 --- a/tests/unit-tests/reporter/models/finalReportGenerator-test.js +++ b/tests/unit-tests/reporter/models/finalReportGenerator-test.js @@ -26,7 +26,7 @@ const REPORT = { describe('Artillery report generator test', () => { let sandbox, databaseConnectorGetStatsStub, - getJobExperimentsStubByJobIdStub, + getJobExperimentsByJobIdStub, getChaosExperimentsByIdsStub, loggerErrorStub, loggerWarnStub, @@ -36,7 +36,7 @@ describe('Artillery report generator test', () => { sandbox = sinon.sandbox.create(); databaseConnectorGetStatsStub = sandbox.stub(databaseConnector, 'getStats'); reportsManagerGetReportStub = sandbox.stub(reportsManager, 'getReport'); - getJobExperimentsStubByJobIdStub = sandbox.stub(chaosExperimentsManager, 'getChaosJobExperimentsByJobId'); + getJobExperimentsByJobIdStub = sandbox.stub(chaosExperimentsManager, 'getChaosJobExperimentsByJobId'); getChaosExperimentsByIdsStub = sandbox.stub(chaosExperimentsManager, 'getChaosExperimentsByIds'); loggerErrorStub = sandbox.stub(logger, 'error'); loggerWarnStub = sandbox.stub(logger, 'warn'); @@ -58,7 +58,7 @@ describe('Artillery report generator test', () => { it('create aggregate report when there is only intermediate rows', async () => { databaseConnectorGetStatsStub.resolves(SINGLE_RUNNER_INTERMEDIATE_ROWS); - getJobExperimentsStubByJobIdStub.resolves([]); + getJobExperimentsByJobIdStub.resolves([]); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); should(reportOutput.parallelism).eql(1); @@ -68,7 +68,7 @@ describe('Artillery report generator test', () => { const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); statsWithUnknownData.push({ phase_status: 'some_unknown_phase', data: JSON.stringify({}) }); databaseConnectorGetStatsStub.resolves(statsWithUnknownData); - getJobExperimentsStubByJobIdStub.resolves([]); + getJobExperimentsByJobIdStub.resolves([]); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); should(reportOutput.parallelism).eql(1); From 7c7251257f51cbcbf1a8cb07d0a11ef30a6e31b4 Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 16:24:13 +0300 Subject: [PATCH 5/8] feat: aggregate experiments in the report --- .../unit-tests/reporter/models/finalReportGenerator-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit-tests/reporter/models/finalReportGenerator-test.js b/tests/unit-tests/reporter/models/finalReportGenerator-test.js index 39856aa7a..c0fcb3485 100644 --- a/tests/unit-tests/reporter/models/finalReportGenerator-test.js +++ b/tests/unit-tests/reporter/models/finalReportGenerator-test.js @@ -89,7 +89,7 @@ describe('Artillery report generator test', () => { const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); statsWithUnknownData.push({ phase_status: 'intermediate', data: 'unsupported data type' }); databaseConnectorGetStatsStub.resolves(statsWithUnknownData); - getJobExperimentsStubByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); + getJobExperimentsByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); getChaosExperimentsByIdsStub.resolves(CHAOS_EXPERIMENTS_ROWS); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); should(reportOutput.experiments).deepEqual([ @@ -130,7 +130,7 @@ describe('Artillery report generator test', () => { const firstStatsTimestamp = JSON.parse(PARALLEL_INTERMEDIATE_ROWS[0].data).timestamp; reportsManagerGetReportStub.resolves(REPORT); - getJobExperimentsStubByJobIdStub.resolves([]); + getJobExperimentsByJobIdStub.resolves([]); REPORT.start_time = new Date(new Date(firstStatsTimestamp).getTime() - (STATS_INTERVAL * 1000)); databaseConnectorGetStatsStub.resolves(PARALLEL_INTERMEDIATE_ROWS); const reportOutput = await aggregateReportGenerator.createAggregateReport(REPORT.test_id, REPORT.report_id); @@ -296,7 +296,7 @@ describe('Artillery report generator test', () => { it('create final report fails when get experiments returns error on get chaos experiments', async () => { databaseConnectorGetStatsStub.resolves(SINGLE_RUNNER_INTERMEDIATE_ROWS); - getJobExperimentsStubByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); + getJobExperimentsByJobIdStub.resolves(JOB_EXPERIMENTS_ROWS); getChaosExperimentsByIdsStub.rejects(new Error('Database failure')); let testShouldFail = true; From 33bb00964e0e301e47a86adfd6cc654c11d344b3 Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 16:40:23 +0300 Subject: [PATCH 6/8] feat: aggregate experiments in the report --- .../reporter/models/finalReportGenerator-test.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/unit-tests/reporter/models/finalReportGenerator-test.js b/tests/unit-tests/reporter/models/finalReportGenerator-test.js index c0fcb3485..a22f27587 100644 --- a/tests/unit-tests/reporter/models/finalReportGenerator-test.js +++ b/tests/unit-tests/reporter/models/finalReportGenerator-test.js @@ -9,6 +9,8 @@ const aggregateReportManager = rewire('../../../../src/reports/models/aggregateR const chaosExperimentsManager = require('../../../../src/chaos-experiments/models/chaosExperimentsManager'); const databaseConnector = require('../../../../src/reports/models/databaseConnector'); const reportsManager = require('../../../../src/reports/models/reportsManager'); +const configHandler = require('../../../../src/configManager/models/configHandler'); +const consts = require('../../../../src/common/consts'); const REPORT = { test_id: 'test_id', @@ -25,6 +27,7 @@ const REPORT = { describe('Artillery report generator test', () => { let sandbox, + configHandlerStub, databaseConnectorGetStatsStub, getJobExperimentsByJobIdStub, getChaosExperimentsByIdsStub, @@ -34,6 +37,7 @@ describe('Artillery report generator test', () => { before(() => { sandbox = sinon.sandbox.create(); + configHandlerStub = sandbox.stub(configHandler, 'getConfigValue'); databaseConnectorGetStatsStub = sandbox.stub(databaseConnector, 'getStats'); reportsManagerGetReportStub = sandbox.stub(reportsManager, 'getReport'); getJobExperimentsByJobIdStub = sandbox.stub(chaosExperimentsManager, 'getChaosJobExperimentsByJobId'); @@ -85,7 +89,8 @@ describe('Artillery report generator test', () => { loggerWarnStub.callCount.should.eql(1); }); - it('create final report successfully with chaos experiments', async function() { + it.only('create final report successfully with chaos experiments', async function() { + configHandlerStub.withArgs(consts.CONFIG.JOB_PLATFORM).resolves('KUBERNETES'); const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); statsWithUnknownData.push({ phase_status: 'intermediate', data: 'unsupported data type' }); databaseConnectorGetStatsStub.resolves(statsWithUnknownData); @@ -420,19 +425,22 @@ const JOB_EXPERIMENTS_ROWS = [{ job_id: REPORT.job_id, experiment_id: '1234-abc-5678', start_time: timestamp, - end_time: timestamp + 100 + end_time: timestamp + 100, + is_triggered: true }, { job_id: REPORT.job_id, experiment_id: 'abcd-1234-efgh', start_time: timestamp, - end_time: timestamp + 200 + end_time: timestamp + 200, + is_triggered: true }, { job_id: REPORT.job_id, experiment_id: '4321-abc-5678', start_time: timestamp, - end_time: timestamp + 300 + end_time: timestamp + 300, + is_triggered: true }]; const CHAOS_EXPERIMENTS_ROWS = [{ From 1e1386feddd38ef0f015ea2880275938e1f35ed1 Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 16:47:22 +0300 Subject: [PATCH 7/8] feat: aggregate experiments in the report --- tests/unit-tests/reporter/models/finalReportGenerator-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit-tests/reporter/models/finalReportGenerator-test.js b/tests/unit-tests/reporter/models/finalReportGenerator-test.js index a22f27587..dea810cda 100644 --- a/tests/unit-tests/reporter/models/finalReportGenerator-test.js +++ b/tests/unit-tests/reporter/models/finalReportGenerator-test.js @@ -89,7 +89,7 @@ describe('Artillery report generator test', () => { loggerWarnStub.callCount.should.eql(1); }); - it.only('create final report successfully with chaos experiments', async function() { + it('create final report successfully with chaos experiments', async function() { configHandlerStub.withArgs(consts.CONFIG.JOB_PLATFORM).resolves('KUBERNETES'); const statsWithUnknownData = JSON.parse(JSON.stringify(SINGLE_RUNNER_INTERMEDIATE_ROWS)); statsWithUnknownData.push({ phase_status: 'intermediate', data: 'unsupported data type' }); From 6ebe6840022fa2c041aa6cd344ae86274eb81f2a Mon Sep 17 00:00:00 2001 From: kerenfinkelstein Date: Mon, 2 Oct 2023 17:25:34 +0300 Subject: [PATCH 8/8] feat: aggregate experiments in the report --- src/reports/models/aggregateReportManager.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/reports/models/aggregateReportManager.js b/src/reports/models/aggregateReportManager.js index cd9467c5a..71030fce3 100644 --- a/src/reports/models/aggregateReportManager.js +++ b/src/reports/models/aggregateReportManager.js @@ -7,11 +7,6 @@ const logger = require('../../common/logger'); const databaseConnector = require('./databaseConnector'); const chaosExperimentsManager = require('../../chaos-experiments/models/chaosExperimentsManager'); const constants = require('../utils/constants'); -const configHandler = require('../../configManager/models/configHandler'); -const { - CONFIG, - KUBERNETES -} = require('../../common/consts'); const STATS_INTERVAL = 30; @@ -72,11 +67,10 @@ async function aggregateReport(report) { } async function getChaosExperimentsByJobId(jobId) { - const jobPlatform = await configHandler.getConfigValue(CONFIG.JOB_PLATFORM); - if (jobPlatform.toUpperCase() !== KUBERNETES) { + const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(jobId); + if (!chaosJobExperiments) { return; } - const chaosJobExperiments = await chaosExperimentsManager.getChaosJobExperimentsByJobId(jobId); const uniqueExperimentIds = [...new Set(chaosJobExperiments.map(jobExperiment => jobExperiment.experiment_id))]; const chaosExperiments = await chaosExperimentsManager.getChaosExperimentsByIds(uniqueExperimentIds); const mappedChaosJobExperiments = chaosJobExperiments.map((jobExperiment) => {