From cfb1a33734e1bd0fc03b9da7968b4bbc0023dcb6 Mon Sep 17 00:00:00 2001 From: Jason Claxton <30830544+Jozzey@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:31:20 +0100 Subject: [PATCH] Add `system` to new status page (#462) The new `health/info` page does not contain the Version & Commit hash for the system repo. This PR will add those details. --- .../health/fetch-system-info.service.js | 40 +++++++++++++++++++ app/services/health/info.service.js | 21 +++++++--- .../health/fetch-system-info.service.test.js | 26 ++++++++++++ test/services/health/info.service.test.js | 24 +++++------ 4 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 app/services/health/fetch-system-info.service.js create mode 100644 test/services/health/fetch-system-info.service.test.js diff --git a/app/services/health/fetch-system-info.service.js b/app/services/health/fetch-system-info.service.js new file mode 100644 index 0000000000..88bf3700a0 --- /dev/null +++ b/app/services/health/fetch-system-info.service.js @@ -0,0 +1,40 @@ +'use strict' + +/** + * Returns information about the `system` repo in the format required by the info service + * @module FetchSystemInfoService + */ + +// We use promisify to wrap exec in a promise. This allows us to await it without resorting to using callbacks. +const util = require('util') +const exec = util.promisify(require('child_process').exec) + +const { version } = require('../../../package.json') + +/** + * Returns information about the `system` repo in the format required by the info service + * + * @returns {Object} An object containing the `name`, `serviceName`, `version`, `commit` & `jobs` + */ +async function go () { + return { + name: 'System', + serviceName: 'system', + version, + commit: await _getCommitHash(), + jobs: [] + } +} + +async function _getCommitHash () { + try { + const { stdout, stderr } = await exec('git rev-parse HEAD') + return stderr ? `ERROR: ${stderr}` : stdout.replace('\n', '') + } catch (error) { + return `ERROR: ${error.message}` + } +} + +module.exports = { + go +} diff --git a/app/services/health/info.service.js b/app/services/health/info.service.js index 639b20d805..a262940ea0 100644 --- a/app/services/health/info.service.js +++ b/app/services/health/info.service.js @@ -11,8 +11,9 @@ const util = require('util') const exec = util.promisify(ChildProcess.exec) const ChargingModuleRequestLib = require('../../lib/charging-module-request.lib.js') -const CreateRedisClient = require('./create-redis-client.service.js') -const FetchImportJobs = require('./fetch-import-jobs.service.js') +const CreateRedisClientService = require('./create-redis-client.service.js') +const FetchImportJobsService = require('./fetch-import-jobs.service.js') +const FetchSystemInfoService = require('./fetch-system-info.service.js') const { formatLongDateTime } = require('../../presenters/base.presenter.js') const RequestLib = require('../../lib/request.lib.js') const LegacyRequestLib = require('../../lib/legacy-request.lib.js') @@ -28,11 +29,13 @@ const servicesConfig = require('../../../config/services.config.js') */ async function go () { const addressFacadeData = await _getAddressFacadeData() - const appData = await _getAppData() const chargingModuleData = await _getChargingModuleData() + const legacyAppData = await _getLegacyAppData() const redisConnectivityData = await _getRedisConnectivityData() const virusScannerData = await _getVirusScannerData() + const appData = await _addSystemInfoToLegacyAppData(legacyAppData) + return { addressFacadeData, appData, @@ -42,6 +45,12 @@ async function go () { } } +async function _addSystemInfoToLegacyAppData (appData) { + const systemInfo = await FetchSystemInfoService.go() + + return [...appData, systemInfo] +} + async function _getAddressFacadeData () { const statusUrl = new URL('/address-service/hola', servicesConfig.addressFacade.url) const result = await RequestLib.get(statusUrl.href) @@ -53,7 +62,7 @@ async function _getAddressFacadeData () { return _parseFailedRequestResult(result) } -async function _getAppData () { +async function _getLegacyAppData () { const healthInfoPath = 'health/info' const services = [ @@ -97,7 +106,7 @@ async function _getChargingModuleData () { async function _getImportJobsData () { try { - const importJobs = await FetchImportJobs.go() + const importJobs = await FetchImportJobsService.go() return _mapArrayToTextCells(importJobs) } catch (error) { @@ -109,7 +118,7 @@ async function _getRedisConnectivityData () { let redis try { - redis = await CreateRedisClient.go() + redis = await CreateRedisClientService.go() await redis.ping() diff --git a/test/services/health/fetch-system-info.service.test.js b/test/services/health/fetch-system-info.service.test.js new file mode 100644 index 0000000000..c00fe158bc --- /dev/null +++ b/test/services/health/fetch-system-info.service.test.js @@ -0,0 +1,26 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it } = exports.lab = Lab.script() +const { expect } = Code + +// Test helpers +const { version } = require('../../../package.json') + +// Thing under test +const FetchSystemInfoService = require('../../../app/services/health/fetch-system-info.service.js') + +describe('Fetch System Info service', () => { + it('returns the systems version and commit hash', async () => { + const result = await FetchSystemInfoService.go() + + expect(result.name).to.equal('System') + expect(result.serviceName).to.equal('system') + expect(result.version).to.equal(version) + expect(result.commit).to.exist() + expect(result.jobs).to.have.length(0) + }) +}) diff --git a/test/services/health/info.service.test.js b/test/services/health/info.service.test.js index cf1e3f61c6..d5fc3c2211 100644 --- a/test/services/health/info.service.test.js +++ b/test/services/health/info.service.test.js @@ -14,8 +14,8 @@ const servicesConfig = require('../../../config/services.config.js') // Things we need to stub const ChargingModuleRequestLib = require('../../../app/lib/charging-module-request.lib.js') -const CreateRedisClient = require('../../../app/services/health/create-redis-client.service.js') -const FetchImportJobs = require('../../../app/services/health/fetch-import-jobs.service.js') +const CreateRedisClientService = require('../../../app/services/health/create-redis-client.service.js') +const FetchImportJobsService = require('../../../app/services/health/fetch-import-jobs.service.js') const LegacyRequestLib = require('../../../app/lib/legacy-request.lib.js') const RequestLib = require('../../../app/lib/request.lib.js') @@ -65,10 +65,10 @@ describe('Info service', () => { beforeEach(() => { chargingModuleRequestLibStub = Sinon.stub(ChargingModuleRequestLib, 'get') - fetchImportJobsStub = Sinon.stub(FetchImportJobs, 'go') + fetchImportJobsStub = Sinon.stub(FetchImportJobsService, 'go') legacyRequestLibStub = Sinon.stub(LegacyRequestLib, 'get') requestLibStub = Sinon.stub(RequestLib, 'get') - redisStub = Sinon.stub(CreateRedisClient, 'go') + redisStub = Sinon.stub(CreateRedisClientService, 'go') // These requests will remain unchanged throughout the tests. We do alter the ones to the AddressFacade and the // water-api (foreground-service) though, which is why they are defined separately in each test. @@ -126,7 +126,7 @@ describe('Info service', () => { 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].name).to.equal('Import') expect(result.appData[0].serviceName).to.equal('import') expect(result.appData[0].version).to.equal('9.0.99') @@ -189,7 +189,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(2) @@ -232,7 +232,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(2) @@ -259,7 +259,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(2) @@ -301,7 +301,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(0) @@ -321,7 +321,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(0) @@ -365,7 +365,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(2) @@ -392,7 +392,7 @@ describe('Info service', () => { expect(result).to.include([ 'virusScannerData', 'redisConnectivityData', 'addressFacadeData', 'chargingModuleData', 'appData' ]) - expect(result.appData).to.have.length(10) + expect(result.appData).to.have.length(11) expect(result.appData[0].version).to.equal('9.0.99') expect(result.appData[0].jobs).to.have.length(2)