From 80ccf37714e82920983f79ac39404c359138eaf0 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:28:09 +0400 Subject: [PATCH 01/21] feat(package): update if-core version --- package-lock.json | 16 +++++++++------- package.json | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57230e0e6..df1de316d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.12", + "@grnsft/if-core": "^0.0.16", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1185,11 +1185,12 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.12.tgz", - "integrity": "sha512-wBn/mC/I7UPvzTVlhgr+ODEa6upYc9lUONqNiPXcn/6s8wXHUx0tHsxjwz6rpp3wUEnRxTMbcy0jV7+tjoK00Q==", + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.16.tgz", + "integrity": "sha512-Ep/YRk8rpFK7+kgD3iKon6PtY8jEj8H3ihYglw9Jli5lPszObwIMb4e6aHXmW2kcCndpBQKuSXaruGTgQ/d9ww==", "dependencies": { - "typescript": "^5.1.6" + "typescript": "^5.1.6", + "zod": "^3.23.8" }, "engines": { "node": ">=18", @@ -11870,8 +11871,9 @@ } }, "node_modules/zod": { - "version": "3.22.4", - "license": "MIT", + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 3a0f5af32..f8df2255f 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.12", + "@grnsft/if-core": "^0.0.16", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From e9390c22f2995f9a892a7595748d3ed72618a435 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:32:31 +0400 Subject: [PATCH 02/21] feat(types): add `PluginSettings` type --- src/common/types/manifest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 1b003be2c..fffcc69e1 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -7,6 +7,7 @@ export type Manifest = z.infer; export type GlobalPlugins = Manifest['initialize']['plugins']; export type PluginOptions = GlobalPlugins[string]; +export type PluginSettings = Omit; export type AggregationParams = Manifest['aggregation']; export type AggregationParamsSure = Extract; From 335c267e37a01722629d41c7b9b9fa8cae3f1884 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:33:44 +0400 Subject: [PATCH 03/21] feat(util): add `mapping` into manifest schema --- src/common/util/validations.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 5298d7d74..aeda691b2 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -57,6 +57,7 @@ export const manifestSchema = z.object({ z.object({ path: z.string(), method: z.string(), + mapping: z.record(z.string(), z.string()).optional(), 'global-config': z.record(z.string(), z.any()).optional(), 'parameter-metadata': z .object({ From 8ac10533e4bc1b1ac5ee95cdfd270072c6bb55c7 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:34:54 +0400 Subject: [PATCH 04/21] feat(util): add `mapOutput` helper function --- src/common/util/helpers.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index 01b87c79d..0778b9efa 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -2,6 +2,7 @@ import {createInterface} from 'node:readline/promises'; import {exec} from 'child_process'; import * as path from 'path'; import {promisify} from 'util'; +import {MappingParams, PluginParams} from '@grnsft/if-core/types'; /** * Promise version of Node's `exec` from `child-process`. @@ -63,3 +64,19 @@ export const parseManifestFromStdin = async () => { return match![1]; }; + +/** + * Maps the output of thr input if the `mapping` parameter is provided. + */ +export const mapOutput = (output: PluginParams, mapping: MappingParams) => { + if (!mapping) return output; + + return Object.entries(output).reduce((acc, [key, value]) => { + if (key in mapping) { + acc[mapping[key]] = value; + } else { + acc[key] = value; + } + return acc; + }, {} as PluginParams); +}; From e492532cf146c046ba89fb7a331b03510def4096 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:41:06 +0400 Subject: [PATCH 05/21] feat(lib): update init plugin logic to get an option attribute --- src/if-run/lib/initialize.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 5adcc2b18..956bb30d6 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -9,7 +9,11 @@ import {pluginStorage} from '../util/plugin-storage'; import {CONFIG, STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; -import {GlobalPlugins, PluginOptions} from '../../common/types/manifest'; +import { + GlobalPlugins, + PluginOptions, + PluginSettings, +} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; const { @@ -82,6 +86,7 @@ const initPlugin = async ( const { method, path, + mapping, 'global-config': globalConfig, 'parameter-metadata': parameterMetadata, } = initPluginParams; @@ -98,7 +103,12 @@ const initPlugin = async ( const plugin = await handModule(method, path); - return plugin(globalConfig, parameterMetadata); + const pluginOptions: PluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': parameterMetadata, + mapping, + }; + return plugin(pluginOptions); }; /** From 322caffb0d650722a35cdba5d6dea5eab5703ab4 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:44:22 +0400 Subject: [PATCH 06/21] feat(builtins): update plugins to accept mapping parameter --- src/if-run/builtins/coefficient/index.ts | 21 +++++++-- src/if-run/builtins/copy-param/index.ts | 33 +++++++++---- src/if-run/builtins/csv-lookup/index.ts | 29 ++++++++++-- src/if-run/builtins/divide/index.ts | 22 +++++++-- src/if-run/builtins/exponent/index.ts | 21 +++++++-- src/if-run/builtins/interpolation/index.ts | 21 +++++++-- .../builtins/mock-observations/index.ts | 46 +++++++++++++------ src/if-run/builtins/multiply/index.ts | 21 +++++++-- src/if-run/builtins/regex/index.ts | 22 +++++++-- src/if-run/builtins/sci-embodied/index.ts | 16 +++++-- src/if-run/builtins/sci/index.ts | 22 +++++++-- src/if-run/builtins/shell/index.ts | 26 +++++++++-- src/if-run/builtins/subtract/index.ts | 21 +++++++-- src/if-run/builtins/sum/index.ts | 23 +++++++--- src/if-run/builtins/time-sync.ts | 20 +++++++- 15 files changed, 283 insertions(+), 81 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index b6c743170..3457b093a 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -3,21 +3,30 @@ import {ERRORS} from '@grnsft/if-core/utils'; import { CoefficientConfig, ExecutePlugin, + MappingParams, PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Coefficient = ( - globalConfig: CoefficientConfig, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Coefficient = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': CoefficientConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { @@ -46,10 +55,12 @@ export const Coefficient = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - return { + const output = { ...input, [outputParameter]: calculateProduct(input, inputParameter, coefficient), }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 7f10bf696..84a16a5a2 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,25 +1,38 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; import { + ConfigParams, ExecutePlugin, + MappingParams, PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {MISSING_GLOBAL_CONFIG} = STRINGS; const {GlobalConfigError} = ERRORS; -// keep-existing: true/false (whether to remove the parameter you are copying from) -// from-param: the parameter you are copying from (e.g. cpu/name) -// to-field: the parameter you are copying to (e.g. cpu/processor-name) - -export const Copy = ( - globalConfig: Record, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { + +/** + * keep-existing: true/false (whether to remove the parameter you are copying from) + * from-param: the parameter you are copying from (e.g. cpu/name) + * to-field: the parameter you are copying to (e.g. cpu/processor-name) + */ + +export const Copy = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -85,10 +98,12 @@ export const Copy = ( } } - return { + const output = { ...safeInput, // need to return or what you provide won't be outputted, don't be evil! [to]: outputValue, }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 91e1739b3..e8de52fa5 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -5,9 +5,16 @@ import axios from 'axios'; import {z} from 'zod'; import {parse} from 'csv-parse/sync'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; - +import { + ExecutePlugin, + MappingParams, + PluginParametersMetadata, + PluginParams, +} from '@grnsft/if-core/types'; + +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -28,9 +35,21 @@ const { CSVParseError, } = ERRORS; -export const CSVLookup = (globalConfig: any): ExecutePlugin => { +export const CSVLookup = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': any; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** @@ -210,10 +229,12 @@ export const CSVLookup = (globalConfig: any): ExecutePlugin => { throw new QueryDataNotFoundError(NO_QUERY_DATA); } - return { + const result = { ...input, ...filterOutput(relatedData, {output, query}), }; + + return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 3d09c130c..730b975c5 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -5,19 +5,29 @@ import { PluginParams, ConfigParams, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; -export const Divide = ( - globalConfig: ConfigParams, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Divide = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -38,10 +48,12 @@ export const Divide = ( validateSingleInput(input, {numerator, denominator}) ); - return { + const result = { ...input, [output]: calculateDivide(safeInput, index, {numerator, denominator}), }; + + return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index a821c3a14..51e6bced4 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -4,14 +4,23 @@ import { PluginParams, ExponentConfig, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; -export const Exponent = ( - globalConfig: ExponentConfig, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Exponent = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ExponentConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -60,10 +69,12 @@ export const Exponent = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - return { + const output = { ...input, [outputParameter]: calculateExponent(input, inputParameter, exponent), }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 60fe90e5b..9c9a5a5a6 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -7,9 +7,12 @@ import { ConfigParams, Method, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -21,10 +24,16 @@ const { WITHIN_THE_RANGE, } = STRINGS; -export const Interpolation = ( - globalConfig: ConfigParams, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Interpolation = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -41,10 +50,12 @@ export const Interpolation = ( const safeInput = validateInput(input, index); const result = calculateResult(validatedConfig, safeInput); - return { + const output = { ...input, [validatedConfig['output-parameter']]: result, }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index ab090d7c8..4b998795b 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -5,18 +5,33 @@ import { PluginParams, ConfigParams, ObservationParams, + PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; -export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { +export const MockObservations = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** @@ -33,19 +48,24 @@ export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { const defaults = inputs && inputs[0]; - return Object.entries(components).reduce((acc: PluginParams[], item) => { - const component = item[1]; - timeBuckets.forEach(timeBucket => { - const observation = createObservation( - {duration, component, timeBucket, generators}, - generatorToHistory - ); - - acc.push(Object.assign({}, defaults, observation)); - }); + const outputs = Object.entries(components).reduce( + (acc: PluginParams[], item) => { + const component = item[1]; + timeBuckets.forEach(timeBucket => { + const observation = createObservation( + {duration, component, timeBucket, generators}, + generatorToHistory + ); + + acc.push(Object.assign({}, defaults, observation)); + }); + + return acc; + }, + [] + ); - return acc; - }, []); + return outputs.map(output => mapOutput(output, mapping)); }; /** diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index b51c1a426..a9b86995c 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -4,14 +4,23 @@ import { PluginParams, MultiplyConfig, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; -export const Multiply = ( - globalConfig: MultiplyConfig, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Multiply = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': MultiplyConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -67,10 +76,12 @@ export const Multiply = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - return { + const output = { ...input, [outputParameter]: calculateProduct(input, inputParameters), }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 0076b6cfe..d5281bda4 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -5,19 +5,29 @@ import { PluginParams, ConfigParams, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -export const Regex = ( - globalConfig: ConfigParams, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Regex = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -66,10 +76,12 @@ export const Regex = ( validateSingleInput(input, parameter) ); - return { + const result = { ...input, [output]: extractMatching(safeInput, parameter, match), }; + + return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index e2a60edd6..19b4bc577 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,19 +1,25 @@ import {z} from 'zod'; import { ExecutePlugin, + MappingParams, PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate, allDefined} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {SCI_EMBODIED_ERROR} = STRINGS; -export const SciEmbodied = ( - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const SciEmbodied = (options: PluginSettings): ExecutePlugin => { + const {'parameter-metadata': parametersMetadata, mapping} = options as { + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { @@ -66,10 +72,12 @@ export const SciEmbodied = ( inputs.map(input => { const safeInput = validateInput(input); - return { + const output = { ...input, 'carbon-embodied': calculateEmbodiedCarbon(safeInput), }; + + return mapOutput(output, mapping); }); /** diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 90cf55fb7..2b0a9e114 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -5,9 +5,12 @@ import { PluginParams, ConfigParams, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate, allDefined} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -19,10 +22,17 @@ const { ZERO_DIVISION, } = STRINGS; -export const Sci = ( - globalConfig: ConfigParams, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Sci = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { @@ -76,10 +86,12 @@ export const Sci = ( }; } - return { + const output = { ...input, sci: safeInput['carbon'] / functionalUnit, }; + + return mapOutput(output, mapping); }); /** diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 5fbea5f28..9ec7deab2 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -3,15 +3,34 @@ import {spawnSync, SpawnSyncReturns} from 'child_process'; import {loadAll, dump} from 'js-yaml'; import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + MappingParams, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; const {ProcessExecutionError} = ERRORS; -export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { +export const Shell = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': ConfigParams; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** @@ -22,8 +41,9 @@ export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { const command = inputWithConfig.command; const inputAsString: string = dump(inputs, {indent: 2}); const results = runModelInShell(inputAsString, command); + const outputs = results?.outputs?.flat() as PluginParams[]; - return results?.outputs?.flat(); + return outputs.map(output => mapOutput(output, mapping)); }; /** diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 2598ecb8a..d1aa1e249 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -1,17 +1,26 @@ import {z} from 'zod'; import { ExecutePlugin, + MappingParams, PluginParametersMetadata, PluginParams, SubtractConfig, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; -export const Subtract = ( - globalConfig: SubtractConfig, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Subtract = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': SubtractConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -68,10 +77,12 @@ export const Subtract = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - return { + const output = { ...input, [outputParameter]: calculateDiff(input, inputParameters), }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index da642dd13..ae1509d11 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -5,19 +5,29 @@ import { PluginParams, SumConfig, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; +import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; +import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Sum = ( - globalConfig: SumConfig, - parametersMetadata: PluginParametersMetadata -): ExecutePlugin => { +export const Sum = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': SumConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; + const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, @@ -34,11 +44,12 @@ export const Sum = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - - return { + const output = { ...input, [outputParameter]: calculateSum(input, inputParameters), }; + + return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index 9c14b63a4..7feba11f9 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -9,12 +9,16 @@ import { PaddingReceipt, TimeNormalizerConfig, TimeParams, + PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; import {validate} from '../../common/util/validations'; import {STRINGS} from '../config'; import {getAggregationMethod} from '../lib/aggregate'; +import {PluginSettings} from '../../common/types/manifest'; +import {mapOutput} from '../../common/util/helpers'; Settings.defaultZone = 'utc'; @@ -35,9 +39,20 @@ const { INVALID_DATETIME, } = STRINGS; -export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { +export const TimeSync = (options: PluginSettings): ExecutePlugin => { + const { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping, + } = options as { + 'global-config': TimeNormalizerConfig; + 'parameter-metadata': PluginParametersMetadata; + mapping: MappingParams; + }; const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** @@ -111,7 +126,8 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') ); - return resampleInputs(sortedInputs, timeParams) as PluginParams[]; + const outputs = resampleInputs(sortedInputs, timeParams) as PluginParams[]; + return outputs.map(output => mapOutput(output, mapping)); }; const parseDate = (date: Date | string) => { From a7c5c47938d8d29a85e319744151c743688ed29c Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:46:51 +0400 Subject: [PATCH 07/21] docs(builtins): update docs correspondingly --- src/if-run/builtins/coefficient/README.md | 26 ++++++++++++----- src/if-run/builtins/copy-param/README.md | 25 +++++++++++++---- src/if-run/builtins/csv-lookup/README.md | 16 ++++++++++- src/if-run/builtins/divide/README.md | 22 +++++++++++---- src/if-run/builtins/exponent/README.md | 21 ++++++++++---- src/if-run/builtins/interpolation/README.md | 28 +++++++++++++------ .../builtins/mock-observations/README.md | 25 +++++++++-------- src/if-run/builtins/multiply/README.md | 21 +++++++++++--- src/if-run/builtins/regex/README.md | 22 +++++++++++---- src/if-run/builtins/sci-embodied/README.md | 13 +++++++-- src/if-run/builtins/sci/README.md | 18 ++++++++++-- src/if-run/builtins/shell/README.md | 16 ++++++++++- src/if-run/builtins/subtract/README.md | 23 +++++++++++---- src/if-run/builtins/sum/README.md | 24 +++++++++++++--- 14 files changed, 231 insertions(+), 69 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index f0e16cb4b..64268eea9 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -18,8 +18,7 @@ Three parameters are required in global config: `input-parameter`, `coefficient` ### Plugin parameter metadata -The `parameter-metadata` section contains information about `description` and `unit` -of the parameters of the inputs and outputs +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `input-parameter` of the global config. Each parameter has: @@ -30,6 +29,15 @@ of the parameters of the inputs and outputs - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs All of `input-parameters` must be available in the input array. @@ -49,13 +57,17 @@ output = input * coefficient To run the plugin from a Typescript app, you must first create an instance of `Coefficient`. Then, you can call `execute()`. ```typescript -const config = { - 'input-parameter': 'carbon', - coefficient: 10, - 'output-parameter': 'carbon-product', +const pluginSettings = { + 'global-config': { + 'input-parameter': 'carbon', + coefficient: 10, + 'output-parameter': 'carbon-product', + }, + 'parameter-metadata': {}, + mapping: {}, }; -const coeff = Coefficient(config); +const coeff = Coefficient(pluginSettings); const result = coeff.execute([ { duration: 3600, diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 8e6ef563a..3c1341e86 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -52,6 +52,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. @@ -67,11 +76,17 @@ To run the plugin, you must first create an instance of `Copy`. Then, you can ca ```typescript import {Copy} from '.'; -const plugin = Copy({ - 'keep-existing': true, - from: 'from-param', - to: 'to-param', -}); +const pluginSettings = { + 'global-config': { + 'keep-existing': true, + from: 'from-param', + to: 'to-param', + }, + 'parameter-metadata': {}, + mapping: {}, +}; + +const plugin = Copy(pluginSettings); const result = plugin.execute([ { diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 317f3c897..273a2c568 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -53,6 +53,15 @@ All the following values are valid for the `output` field: - `["processor-name", "processor-model-id"]` - `[["processor-name", "processor-model-id"],["tdp","thermal-design-power"]]` +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs There are no strict requirements on input for this plugin because they depend upon the contents of the target CSV and your input data at the time the CSV lookup is invoked. Please make sure you are requesting data from columns that exist in the target csv file and that your query values are available in your `input` data. @@ -84,7 +93,12 @@ const globalConfig = { }, output: ['cpu-tdp', 'tdp'], }; -const csvLookup = CSVLookup(globalConfig); +const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {} + mapping: {} +}; +const csvLookup = CSVLookup(pluginSettings); const input = [ { diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 98e5c0314..147b1363f 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -22,9 +22,19 @@ The `parameter-metadata` section contains information about `description` and `u - `unit`: unit of the parameter - `outputs`: describe the parameter of the `denominator` of the global config. The parameter has the following attributes: + - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs - `numerator` - as input parameter, must be available in the input array @@ -50,12 +60,14 @@ output = input0 / input1 To run the plugin, you must first create an instance of `Divide`. Then, you can call `execute()`. ```typescript -const globalConfig = { - numerator: 'vcpus-allocated', - denominator: 2, - output: 'cpu/number-cores', +const pluginSettings = { + 'global-config': { + numerator: 'vcpus-allocated', + denominator: 2, + output: 'cpu/number-cores', + }, }; -const divide = Divide(globalConfig, parametersMetadata); +const divide = Divide(pluginSettings); const input = [ { diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index ed1c74b35..c73660b1c 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -29,6 +29,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs `input-parameter` and `exponent` must be available in the input array. @@ -50,13 +59,15 @@ To run the plugin, you must first create an instance of `Exponent`. Then, you ca ```typescript import {Exponent} from 'builtins'; -const config = { - inputParameter: ['cpu/energy'], - exponent: 2 - outputParameter: 'energy', +const pluginSettings = { + 'global-config': { + inputParameter: ['cpu/energy'], + exponent: 2 + outputParameter: 'energy', + }, }; -const exponent = Exponent(config); +const exponent = Exponent(pluginSettings); const result = await exponent.execute([ { duration: 3600, diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index dedcfe5e9..513fab2a8 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -38,6 +38,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ## Input Parameters The plugin expects the following input parameters: @@ -82,22 +91,23 @@ The plugin conducts input validation using the `zod` library and may throw error ### TypeScript Usage ```ts -const globalConfig = { - method: 'linear', - x: [0, 10, 50, 100], - y: [0.12, 0.32, 0.75, 1.02], - 'input-parameter': 'cpu/utilization' - 'output-parameter': 'cpu/energy' - +const pluginSettings = { + 'global-config': { + method: 'linear', + x: [0, 10, 50, 100], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': 'cpu/utilization', + 'output-parameter': 'cpu/energy', + }, }; -const interpolationPlugin = Interpolation(globalConfig); +const interpolationPlugin = Interpolation(pluginSettings); const inputs = [ { timestamp: '2024-04-16T12:00:00Z', duration: 3600, - 'cpu/utilization': 45 + 'cpu/utilization': 45, }, ]; diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 0da9211da..d0fcd826d 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -29,19 +29,22 @@ The plugin's `global-config` section in the manifest file determines its behavio ### Typescript Usage ```typescript -const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:10', - duration: 60, - components: { - 'instance-type': 'A1', - }, - generators: { - common: { - region: 'uk-west', +const pluginSettings = { + 'global-config': { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:10', + duration: 60, + components: { + 'instance-type': 'A1', + }, + generators: { + common: { + region: 'uk-west', + }, }, }, -}); +}; +const mockObservations = MockObservations(pluginSettings); const result = await mockObservations.execute([]); ``` diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 6acbb847a..0dcf6aeb2 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -28,6 +28,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs All of `input-parameters` must be available in the input array. @@ -49,12 +58,16 @@ To run the plugin, you must first create an instance of `Multiply`. Then, you ca ```typescript import {Multiply} from 'builtins'; -const config = { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'energy-product', +const pluginSettings = { + 'global-config': { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'energy-product', + }, + 'parameter-metadata': {}, + mapping: {}, }; -const multiply = Multiply(config, parametersMetadata); +const multiply = Multiply(pluginSettings); const result = await multiply.execute([ { duration: 3600, diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 9a0d388c2..1166c66ca 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -29,6 +29,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs - `parameter` - as input parameter, must be available in the input array @@ -37,18 +46,19 @@ The `parameter-metadata` section contains information about `description` and `u - `output`: The match of the `parameter` value using the `match` regex defined in the global config. If the `match` regex includes the global flag (`g`), a string containing all matches separated by spaces. - ## Implementation To run the plugin, you must first create an instance of `Regex`. Then, you can call `execute()`. ```typescript -const globalConfig = { - parameter: 'physical-processor', - match: '^[^,]+', - output: 'cpu/name', +const pluginSettings = { + 'global-config': { + parameter: 'physical-processor', + match: '^[^,]+', + output: 'cpu/name', + }, }; -const regex = Regex(globalConfig); +const regex = Regex(pluginSettings); const input = [ { diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 21266fba7..2bacdb704 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -23,6 +23,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs - `device/emissions-embodied`: the sum of Life Cycle Assessment (LCA) emissions for the component @@ -85,7 +94,7 @@ const results = await sciEmbodied.execute([ ## Example manifest -IF users will typically call the plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating the plugin is handled by `ie` and does not have to be done explicitly by the user. The following is an example `manifest` that calls `sci-embodied`: +IF users will typically call the plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating the plugin is handled by `if-run` and does not have to be done explicitly by the user. The following is an example `manifest` that calls `sci-embodied`: ```yaml name: sci-embodied @@ -130,4 +139,4 @@ This error class is used to describe a problem with one of the input values to ` You will receive a specific error message explaining which parameter is problematic, and you can check and replace where appropriate. -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors) diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 4d9544ad2..da460e49d 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -18,9 +18,19 @@ The `parameter-metadata` section contains information about `description` and `u - `unit`: unit of the parameter - `outputs`: describe the `sci` parameter which has the following attributes: + - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs - `carbon`: total carbon in gCO2eq (required) @@ -46,12 +56,14 @@ To run the plugin, you must first create an instance of `Sci`. Then, you can cal ```typescript import {Sci} from 'builtins'; - -const sci = Sci({'functional-unit': 'requests'}); +const pluginSettings = { + 'global-config': {'functional-unit': 'requests'} +} +const sci = Sci(); const results = await sci.execute( [ { - 'carbon': 5' + 'carbon': 5 duration: 1, requests: 100, }, diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index 962fb46d4..1fe9bcba7 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -29,6 +29,15 @@ The parameters included in the `inputs` field in the `manifest` depend entirely - `timestamp`: A timestamp for the specific input - `duration`: The length of time these specific inputs cover +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ## Returns The specific return types depend on the plugin being invoked. Typically, we would expect some kind of energy or carbon metric as an output, but it is also possible that plugins target different parts of the pipeline, such as data importers, adaptor plugins etc. Therefore, we do not specify return data for external plugins. @@ -38,7 +47,12 @@ The specific return types depend on the plugin being invoked. Typically, we woul To run the plugin, you must first create an instance of `Shell` and call its `execute()` to run the external plugin. ```typescript -const output = Shell({command: '/usr/local/bin/sampler'}); +const pluginSettings = { + 'global-config': { + command: '/usr/local/bin/sampler', + }, +}; +const output = Shell(pluginSettings); const result = await output.execute([ { timestamp: '2021-01-01T00:00:00Z', diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 9916404bc..dd70c2927 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -28,6 +28,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs All of `input-parameters` must be available in the input array. @@ -49,12 +58,14 @@ To run the plugin, you must first create an instance of `Subtract`. Then, you ca ```typescript import {Subtract} from 'builtins'; -const config = { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'offset/energy', -}; +const pluginSettings = { + 'global-config': { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'offset/energy', + } +} -const subtract = Subtract(config); +const subtract = Subtract(pluginSettings); const result = subtract subtract.execute([ { duration: 3600, @@ -112,4 +123,4 @@ The results will be saved to a new `yaml` file in `manifests/outputs`. This error arises when an invalid value is passed to `Subtract`. Typically, this can occur when a non-numeric value (such as a string made of alphabetic characters) is passed where a number or numeric string is expected. Please check that the types are correct for all the relevant fields in your `inputs` array. -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors) diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 4d861f2c9..613fd7830 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -28,6 +28,15 @@ The `parameter-metadata` section contains information about `description` and `u - `description`: description of the parameter - `unit`: unit of the parameter +### Mapping + +The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: + +```yaml +mapping: + 'old-name': 'new-name' +``` + ### Inputs All of `input-parameters` must be available in the input array. @@ -47,12 +56,19 @@ output = input0 + input1 + input2 ... inputN To run the plugin, you must first create an instance of `Sum`. Then, you can call `execute()`. ```typescript -const config = { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'energy', +const pluginSettings = { + 'global-config': { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'energy', + }, + 'parameter-metadata': {}, + mapping: { + 'cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', + }, }; -const sum = Sum(config, parametersMetadata); +const sum = Sum(pluginSettings); const result = sum.execute([ { timestamp: '2021-01-01T00:00:00Z', From e0f9d4bd93cedf9f246968eb7b3893b033169d56 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:49:15 +0400 Subject: [PATCH 08/21] test(util): add test for mapOutput function --- src/__tests__/common/util/helpers.test.ts | 57 ++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts index 92b4f9dab..490bfcca7 100644 --- a/src/__tests__/common/util/helpers.test.ts +++ b/src/__tests__/common/util/helpers.test.ts @@ -2,7 +2,7 @@ jest.mock('node:readline/promises', () => require('../../../__mocks__/readline') ); -import {parseManifestFromStdin} from '../../../common/util/helpers'; +import {parseManifestFromStdin, mapOutput} from '../../../common/util/helpers'; describe('common/util/helpers: ', () => { describe('parseManifestFromStdin(): ', () => { @@ -37,8 +37,61 @@ describe('common/util/helpers: ', () => { const response = await parseManifestFromStdin(); const expectedMessage = '\nname: mock-name\ndescription: mock-description\n'; - + expect.assertions(1); expect(response).toEqual(expectedMessage); }); }); + + describe('mapOutput(): ', () => { + const output = { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + }; + it('returns provided `output` if `mapping` is not valid.', () => { + const mapping = undefined; + const mappedOutput = mapOutput(output, mapping!); + + expect.assertions(1); + expect(mappedOutput).toEqual(output); + }); + + it('returns mapped output if `mapping` has data.', () => { + const mapping = { + 'cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', + }; + const expectedOutput = { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-from-cpu': 1, + 'energy-from-network': 1, + 'memory/energy': 1, + }; + const mappedOutput = mapOutput(output, mapping); + + expect.assertions(1); + expect(mappedOutput).toEqual(expectedOutput); + }); + + it('returns the correct mapped output if some properties are mismatched.', () => { + const mapping = { + 'mock-cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', + }; + const expectedOutput = { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'energy-from-network': 1, + 'memory/energy': 1, + }; + const mappedOutput = mapOutput(output, mapping); + + expect.assertions(1); + expect(mappedOutput).toEqual(expectedOutput); + }); + }); }); From 954c5c02ef7186bfdfd042255449da609ca4e7ad Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:51:02 +0400 Subject: [PATCH 09/21] test(lib): add missing `aggregation-method` into tests --- src/__tests__/if-run/lib/explain.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 509c3ba32..f4085d04e 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -34,16 +34,19 @@ describe('lib/explain: ', () => { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', }, 'network/energy': { unit: 'kWh', description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', }, }, outputs: { 'energy-sum': { unit: 'kWh', description: 'sum of energy components', + 'aggregation-method': 'sum', }, }, }, @@ -66,20 +69,29 @@ describe('lib/explain: ', () => { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', }, 'network/energy': { unit: 'kWh', description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', }, }, outputs: { - 'energy-sum': {unit: 'kWh', description: 'sum of energy components'}, + 'energy-sum': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, }, }, }; + // @ts-ignore addExplainData(mockData); + const result = explain(); + expect.assertions(1); expect(result).toEqual(expectedResult); }); From 6904da52814d04c3bf40e394b5b5968840718450 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:53:14 +0400 Subject: [PATCH 10/21] test(builtins): update test corespondingly --- .../if-run/builtins/coefficient.test.ts | 28 +- .../if-run/builtins/copy-param.test.ts | 28 +- .../if-run/builtins/csv-lookup.test.ts | 101 +- src/__tests__/if-run/builtins/divide.test.ts | 44 +- .../if-run/builtins/exponent.test.ts | 16 +- .../if-run/builtins/interpolation.test.ts | 58 +- .../if-run/builtins/mock-observations.test.ts | 82 +- .../if-run/builtins/multiply.test.ts | 12 +- src/__tests__/if-run/builtins/regex.test.ts | 21 +- .../if-run/builtins/sci-embodied.test.ts | 8 +- src/__tests__/if-run/builtins/sci.test.ts | 48 +- src/__tests__/if-run/builtins/shell.test.ts | 12 +- .../if-run/builtins/subtract.test.ts | 12 +- src/__tests__/if-run/builtins/sum.test.ts | 48 +- .../if-run/builtins/time-sync.test.ts | 1396 +++++++++-------- 15 files changed, 1096 insertions(+), 818 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 8d99c3e87..453f6954a 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -18,7 +18,12 @@ describe('builtins/coefficient: ', () => { inputs: {}, outputs: {}, }; - const coefficient = Coefficient(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const coefficient = Coefficient(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -55,7 +60,12 @@ describe('builtins/coefficient: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - const coefficient = Coefficient(config!, parametersMetadata); + const pluginSettings = { + 'global-config': config!, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const coefficient = Coefficient(pluginSettings); expect.assertions(1); @@ -80,7 +90,12 @@ describe('builtins/coefficient: ', () => { coefficient: 3, 'output-parameter': 'carbon-product', }; - const coefficient = Coefficient(invalidConfig, parametersMetadata); + const pluginSettings = { + 'global-config': invalidConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const coefficient = Coefficient(pluginSettings); const expectedMessage = '"input-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; @@ -107,7 +122,12 @@ describe('builtins/coefficient: ', () => { coefficient: 10, 'output-parameter': '', }; - const coefficient = Coefficient(invalidConfig, parametersMetadata); + const pluginSettings = { + 'global-config': invalidConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const coefficient = Coefficient(pluginSettings); const expectedMessage = '"output-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 952546505..7b8e2ffa3 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -18,7 +18,12 @@ describe('builtins/copy: ', () => { inputs: {}, outputs: {}, }; - const copy = Copy(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const copy = Copy(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -53,7 +58,12 @@ describe('builtins/copy: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - const copy = Copy(config!, parametersMetadata); + const pluginSettings = { + 'global-config': config!, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const copy = Copy(pluginSettings); expect.assertions(1); @@ -78,7 +88,12 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const copy = Copy(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const copy = Copy(pluginSettings); expect.assertions(1); try { @@ -103,7 +118,12 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const copy = Copy(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': parametersMetadata, + mapping: {}, + }; + const copy = Copy(pluginSettings); const expectedResult = [ { diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index b89c7572e..18270fa11 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -35,7 +35,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); expect(csvLookup).toHaveProperty('metadata'); expect(csvLookup).toHaveProperty('execute'); }); @@ -54,7 +59,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const responseData = `cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,gpu-count,gpu-model-name,Hardware Information on AWS Documentation & Comments,instance-class,instance-storage,memory-available,platform-memory,release-date,storage-drives 16,8,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.2xlarge,EBS-Only,16,32,November 2018,0 @@ -93,7 +103,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -126,7 +141,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const input = [ { timestamp: '2024-03-01', @@ -155,7 +175,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const input = [ { timestamp: '2024-03-01', @@ -187,7 +212,12 @@ describe('builtins/CSVLookup: ', () => { }; mock.onGet(globalConfig.filepath).reply(404); - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const input = [ { timestamp: '2024-03-01', @@ -217,7 +247,12 @@ describe('builtins/CSVLookup: ', () => { }, output: '*', }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -265,7 +300,12 @@ describe('builtins/CSVLookup: ', () => { ['gpu-model-name', 'gpumodel'], ], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -300,7 +340,12 @@ describe('builtins/CSVLookup: ', () => { }, output: 'gpu-count', }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -334,8 +379,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const input = [ { timestamp: '2024-03-01', @@ -360,7 +409,7 @@ describe('builtins/CSVLookup: ', () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - const csvLookup = CSVLookup(); + const csvLookup = CSVLookup({}); const input = [ { timestamp: '2024-03-01', @@ -392,7 +441,12 @@ describe('builtins/CSVLookup: ', () => { }, output: 'mock', }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const input = [ { timestamp: '2024-03-01', @@ -425,7 +479,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['gpu-count'], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -459,7 +518,12 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); const result = await csvLookup.execute([ { @@ -495,7 +559,12 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const csvLookup = CSVLookup(pluginSettings); try { await csvLookup.execute([ diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index e0a472998..3f5bc78a8 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -14,11 +14,12 @@ describe('builtins/divide: ', () => { denominator: 2, output: 'cpu/number-cores', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -58,7 +59,12 @@ describe('builtins/divide: ', () => { denominator: 'duration', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const divide = Divide(pluginSettings); const input = [ { @@ -90,7 +96,12 @@ describe('builtins/divide: ', () => { denominator: 3600, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const divide = Divide(pluginSettings); expect.assertions(1); @@ -111,7 +122,12 @@ describe('builtins/divide: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - const divide = Divide(config!, parametersMetadata); + const pluginSettings = { + 'global-config': config!, + 'parameter-metadata': {}, + mapping: {}, + }; + const divide = Divide(pluginSettings); expect.assertions(1); @@ -135,7 +151,12 @@ describe('builtins/divide: ', () => { denominator: 0, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const divide = Divide(pluginSettings); expect.assertions(1); @@ -163,7 +184,12 @@ describe('builtins/divide: ', () => { denominator: '10', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const divide = Divide(pluginSettings); expect.assertions(1); diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index 2e0419686..c8d00a255 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -11,11 +11,12 @@ describe('builtins/exponent: ', () => { exponent: 3, 'output-parameter': 'energy', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const exponent = Exponent(globalConfig, parametersMetadata); + const exponent = Exponent(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -95,7 +96,12 @@ describe('builtins/exponent: ', () => { exponent: 4, 'output-parameter': 'carbon', }; - const exponent = Exponent(newConfig, parametersMetadata); + const pluginSettings = { + 'global-config': newConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const exponent = Exponent(pluginSettings); const data = [ { diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index 6634556dd..1bd135aaa 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -22,9 +22,10 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; const inputs = [ { @@ -33,7 +34,7 @@ describe('builtins/interpolation: ', () => { 'cpu/utilization': 45, }, ]; - const plugin = Interpolation(globalConfig, parametersMetadata); + const plugin = Interpolation(pluginSettings); describe('init Interpolation: ', () => { it('initalizes object with properties.', async () => { @@ -63,7 +64,12 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const plugin = Interpolation(globalConfig, parametersMetadata); + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); const outputs = [ { @@ -79,7 +85,12 @@ describe('builtins/interpolation: ', () => { it('returns result when the `method` is `spline`.', () => { const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config, parametersMetadata); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); const outputs = [ { @@ -97,7 +108,12 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { method: Method.POLYNOMIAL, }); - const plugin = Interpolation(config, parametersMetadata); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); const outputs = [ { @@ -115,7 +131,12 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { x: [0, 10, 100, 50], }); - const plugin = Interpolation(config, parametersMetadata); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); const outputs = [ { @@ -151,7 +172,12 @@ describe('builtins/interpolation: ', () => { it('throws an when the global config is not provided.', () => { const config = undefined; - const plugin = Interpolation(config!, parametersMetadata); + const pluginSettings = { + 'global-config': config!, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); expect.assertions(2); try { @@ -167,7 +193,12 @@ describe('builtins/interpolation: ', () => { x: [0, 10, 100], }); - const plugin = Interpolation(config, parametersMetadata); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); expect.assertions(2); try { @@ -202,7 +233,12 @@ describe('builtins/interpolation: ', () => { 'output-parameter': 'interpolation-result', }; const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config, parametersMetadata); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const plugin = Interpolation(pluginSettings); const inputs = [ { timestamp: '2023-07-06T00:00', diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index 6b0fb22bd..ac2f2409a 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -10,7 +10,7 @@ const {INVALID_MIN_MAX} = STRINGS; describe('builtins/mock-observations: ', () => { describe('init: ', () => { it('successfully initalized.', () => { - const mockObservations = MockObservations({ + const globalConfig = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', duration: 5, @@ -25,7 +25,13 @@ describe('builtins/mock-observations: ', () => { 'memory/utilization': {min: 10, max: 85}, }, }, - }); + }; + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); expect(mockObservations).toHaveProperty('metadata'); expect(mockObservations).toHaveProperty('execute'); @@ -49,7 +55,12 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const mockObservations = MockObservations(config); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); const result = await mockObservations.execute([]); expect.assertions(1); @@ -106,10 +117,15 @@ describe('builtins/mock-observations: ', () => { }, }, }; + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; expect.assertions(2); - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(pluginSettings); try { await mockObservations.execute([]); } catch (error) { @@ -127,11 +143,16 @@ describe('builtins/mock-observations: ', () => { duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], }; + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; expect.assertions(2); try { - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(pluginSettings); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -161,11 +182,16 @@ describe('builtins/mock-observations: ', () => { }, }, }; + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; expect.assertions(2); try { - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(pluginSettings); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -177,7 +203,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ + const globalConfig = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -191,7 +217,13 @@ describe('builtins/mock-observations: ', () => { 'memory/utilization': {min: 10, max: 85}, }, }, - }); + }; + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -207,7 +239,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ + const globalConfig = { 'timestamp-from': '2023-07-06T00:00', duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -221,7 +253,13 @@ describe('builtins/mock-observations: ', () => { 'memory/utilization': {min: 10, max: 85}, }, }, - }); + }; + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -237,7 +275,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ + const globalConfig = { 'timestamp-to': '2023-07-06T00:01', duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -251,7 +289,13 @@ describe('builtins/mock-observations: ', () => { 'memory/utilization': {min: 10, max: 85}, }, }, - }); + }; + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -277,7 +321,12 @@ describe('builtins/mock-observations: ', () => { randint: null, }, }; - const mockObservations = MockObservations(config); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); expect.assertions(2); @@ -307,7 +356,12 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const mockObservations = MockObservations(config); + const pluginSettings = { + 'global-config': config, + 'parameter-metadata': {}, + mapping: {}, + }; + const mockObservations = MockObservations(pluginSettings); expect.assertions(2); diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index b3856dfd4..b07ff7734 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -10,11 +10,12 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const multiply = Multiply(globalConfig, parametersMetadata); + const multiply = Multiply(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -76,7 +77,8 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-product', }; - const multiply = Multiply(newConfig, parametersMetadata); + pluginSettings['global-config'] = newConfig; + const multiply = Multiply(pluginSettings); const data = [ { diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index ea45c49d1..df0383d89 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -14,11 +14,12 @@ describe('builtins/regex: ', () => { match: '^[^,]+', output: 'cpu/name', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const regex = Regex(globalConfig, parametersMetadata); + const regex = Regex(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -59,7 +60,8 @@ describe('builtins/regex: ', () => { match: '/(?<=_)[^_]+?(?=_|$)/g', output: 'cloud/instance-type', }; - const regex = Regex(globalConfig, parametersMetadata); + pluginSettings['global-config'] = globalConfig; + const regex = Regex(pluginSettings); const expectedResult = [ { @@ -90,7 +92,8 @@ describe('builtins/regex: ', () => { match: '[^,]+/', output: 'cpu/name', }; - const regex = Regex(globalConfig, parametersMetadata); + pluginSettings['global-config'] = globalConfig; + const regex = Regex(pluginSettings); const expectedResult = [ { @@ -121,7 +124,8 @@ describe('builtins/regex: ', () => { match: '^(^:)+', output: 'cpu/name', }; - const regex = Regex(globalConfig, parametersMetadata); + pluginSettings['global-config'] = globalConfig; + const regex = Regex(pluginSettings); expect.assertions(1); @@ -144,7 +148,8 @@ describe('builtins/regex: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - const regex = Regex(config!, parametersMetadata); + pluginSettings['global-config'] = config!; + const regex = Regex(pluginSettings); expect.assertions(1); diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 0e2c234f7..9daef9288 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -9,11 +9,11 @@ const {SCI_EMBODIED_ERROR} = STRINGS; describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'parameter-metadata': {}, + mapping: {}, }; - const sciEmbodied = SciEmbodied(parametersMetadata); + const sciEmbodied = SciEmbodied(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index 0360149a9..1c74ec4fc 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -6,11 +6,12 @@ const {MissingInputDataError} = ERRORS; describe('builtins/sci:', () => { describe('Sci: ', () => { - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': {'functional-unit': 'users'}, + 'parameter-metadata': {}, + mapping: {}, }; - const sci = Sci({'functional-unit': 'users'}, parametersMetadata); + const sci = Sci(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -21,12 +22,7 @@ describe('builtins/sci:', () => { describe('execute():', () => { it('returns a result with valid inputs.', async () => { - const sci = Sci( - { - 'functional-unit': 'users', - }, - parametersMetadata - ); + const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -55,12 +51,8 @@ describe('builtins/sci:', () => { }); it('returns the same result regardless of input duration.', async () => { - const sci = Sci( - { - 'functional-unit': 'requests', - }, - parametersMetadata - ); + pluginSettings['global-config'] = {'functional-unit': 'requests'}; + const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -106,12 +98,8 @@ describe('builtins/sci:', () => { }); it('throws exception on invalid functional unit data.', async () => { - const sci = Sci( - { - 'functional-unit': 'requests', - }, - parametersMetadata - ); + pluginSettings['global-config'] = {'functional-unit': 'requests'}; + const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -131,12 +119,8 @@ describe('builtins/sci:', () => { }); it('throws exception if functional unit value is not positive integer.', async () => { - const sci = Sci( - { - 'functional-unit': 'requests', - }, - parametersMetadata - ); + pluginSettings['global-config'] = {'functional-unit': 'requests'}; + const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -158,12 +142,8 @@ describe('builtins/sci:', () => { }); it('fallbacks to carbon value, if functional unit is 0.', async () => { - const sci = Sci( - { - 'functional-unit': 'requests', - }, - parametersMetadata - ); + pluginSettings['global-config'] = {'functional-unit': 'requests'}; + const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts index 379863052..ad5ce6689 100644 --- a/src/__tests__/if-run/builtins/shell.test.ts +++ b/src/__tests__/if-run/builtins/shell.test.ts @@ -11,7 +11,12 @@ jest.mock('js-yaml'); describe('builtins/shell', () => { describe('Shell', () => { - const shell = Shell({}); + const pluginSettings = { + 'global-config': {command: 'python3 /path/to/script.py'}, + 'parameter-metadata': {}, + mapping: {}, + }; + const shell = Shell({'global-config': {}}); describe('init: ', () => { it('successfully initalized.', () => { @@ -22,7 +27,7 @@ describe('builtins/shell', () => { describe('execute(): ', () => { it('execute with valid inputs and command', async () => { - const shell = Shell({command: 'python3 /path/to/script.py'}); + const shell = Shell(pluginSettings); const mockSpawnSync = spawnSync as jest.MockedFunction< typeof spawnSync >; @@ -57,6 +62,7 @@ describe('builtins/shell', () => { {duration: 3600, timestamp: '2022-01-01T00:00:00Z', command: 123}, ]; + expect.assertions(2); try { await shell.execute(invalidInputs); } catch (error) { @@ -70,7 +76,7 @@ describe('builtins/shell', () => { }); it('throw an error when shell could not run command.', async () => { - const shell = Shell({command: 'python3 /path/to/script.py'}); + const shell = Shell(pluginSettings); (spawnSync as jest.Mock).mockImplementation(() => { throw new InputValidationError('Could not run the command'); }); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index 134cebfa7..bd4b50e9e 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -10,11 +10,12 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const subtract = Subtract(globalConfig, parametersMetadata); + const subtract = Subtract(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -76,7 +77,8 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-diff', }; - const subtract = Subtract(newConfig, parametersMetadata); + pluginSettings['global-config'] = newConfig; + const subtract = Subtract(pluginSettings); const data = [ { diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 9ccc64378..10686471c 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -13,11 +13,12 @@ describe('builtins/sum: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const parametersMetadata = { - inputs: {}, - outputs: {}, + const pluginSettings = { + 'global-config': globalConfig, + 'parameter-metadata': {}, + mapping: {}, }; - const sum = Sum(globalConfig, parametersMetadata); + const sum = Sum(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -54,9 +55,43 @@ describe('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when mapping has valid data.', () => { + expect.assertions(1); + pluginSettings.mapping = { + 'cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', + }; + + const sum = Sum(pluginSettings); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-from-cpu': 1, + 'energy-from-network': 1, + 'memory/energy': 1, + energy: 3, + }, + ]; + + const result = sum.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error when global config is not provided.', () => { const config = undefined; - const sum = Sum(config!, parametersMetadata); + pluginSettings['global-config'] = config!; + const sum = Sum(pluginSettings); expect.assertions(1); @@ -102,7 +137,8 @@ describe('builtins/sum: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-sum', }; - const sum = Sum(newConfig, parametersMetadata); + pluginSettings['global-config'] = newConfig; + const sum = Sum(pluginSettings); const data = [ { diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index e216690df..10a2e3489 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -76,7 +76,12 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - const timeSync = TimeSync(basicConfig); + const pluginSettings = { + 'global-config': basicConfig, + 'parameter-metadata': {}, + mapping: {}, + }; + const timeSync = TimeSync(pluginSettings); describe('init: ', () => { it('successfully initalized.', () => { @@ -84,715 +89,726 @@ describe('builtins/time-sync:', () => { expect(timeSync).toHaveProperty('execute'); }); }); - }); -}); - -describe('execute(): ', () => { - it('throws error if `start-time` is missing.', async () => { - const invalidStartTimeConfig = { - 'start-time': '', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(invalidStartTimeConfig); - - expect.assertions(1); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"start-time" parameter is invalid datetime. Error code: invalid_string.' - ) - ); - } - }); - - it('throws error if `end-time` is missing.', async () => { - const errorMessage = - '"end-time" parameter is invalid datetime. Error code: invalid_string.,`start-time` should be lower than `end-time`'; - const invalidEndTimeConfig = { - 'start-time': '2023-12-12T00:01:00.000Z', - 'end-time': '', - interval: 5, - 'allow-padding': true, - }; - const timeModel = TimeSync(invalidEndTimeConfig); - - expect.assertions(1); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); - } - }); - - it('fails if `start-time` is not a valid ISO date.', async () => { - const invalidStartTimeConfig = { - 'start-time': '0023-X', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - const timeModel = TimeSync(invalidStartTimeConfig); - expect.assertions(1); - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"start-time" parameter is invalid datetime. Error code: invalid_string.' - ) - ); - } - }); - - it('fails if `end-time` is not a valid ISO date.', async () => { - const invalidEndTimeConfig = { - 'start-time': '2023-12-12T00:01:00.000Z', - 'end-time': '20XX', - interval: 5, - 'allow-padding': true, - }; - const timeModel = TimeSync(invalidEndTimeConfig); - - expect.assertions(1); - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"end-time" parameter is invalid datetime. Error code: invalid_string.' - ) - ); - } - }); - - it('throws error on missing global config.', async () => { - const config = undefined; - const timeModel = TimeSync(config!); - - expect.assertions(1); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(INVALID_TIME_NORMALIZATION) - ); - } - }); - - it('throws error if interval is invalid.', async () => { - const invalidIntervalConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 0, - 'allow-padding': true, - }; - - const timeModel = TimeSync(invalidIntervalConfig); - - expect.assertions(1); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InvalidInputError(INVALID_OBSERVATION_OVERLAP) - ); - } - }); - - it('throws error if timestamps overlap.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InvalidInputError(INVALID_OBSERVATION_OVERLAP) - ); - } - }); - - it('throws error if `timestamp` is missing.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - '"timestamp" parameter is required in input[0]. Error code: invalid_union.' - ) - ); - } - }); - - it('throws error if the seconds `timestamp` is above 60.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:90.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - '"timestamp" parameter is required in input[0]. Error code: invalid_union.' - ) - ); - } - }); - - it('throws an error if the `timestamp` is not valid date.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 10, - 'allow-padding': true, - }; - const data = [ - { - timestamp: 45, - duration: 10, - 'cpu/utilization': 10, - }, - ]; - - const timeModel = TimeSync(basicConfig); - expect.assertions(2); - - try { - await timeModel.execute(data); - } catch (error) { - expect(error).toBeInstanceOf(InvalidDateInInputError); - expect(error).toStrictEqual( - new InvalidDateInInputError(INVALID_DATE_TYPE(data[0].timestamp)) - ); - } - }); - - it('throws error if end is before start in global config.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:10.000Z', - 'end-time': '2023-12-12T00:00:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError('`start-time` should be lower than `end-time`') - ); - } - }); - - it('converts Date objects to string outputs.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:01.000Z', - interval: 1, - 'allow-padding': false, - }; - - const timeModel = TimeSync(basicConfig); - - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 1, - 'cpu/utilization': 10, - }, - { - timestamp: new Date('2023-12-12T00:00:01.000Z'), - duration: 1, - 'cpu/utilization': 10, - }, - ]); - - const expectedResult = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 1, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:01.000Z', - duration: 1, - 'cpu/utilization': 10, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('checks that metric (carbon) with aggregation-method == sum is properly spread over interpolated time points.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:10.000Z', - interval: 1, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - carbon: 10, - }, - ]); - - const expectedResult = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:01.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:02.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:03.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:04.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:06.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:07.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:08.000Z', - duration: 1, - carbon: 1, - }, - { - timestamp: '2023-12-12T00:00:09.000Z', - duration: 1, - carbon: 1, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('checks that constants are copied to results unchanged.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:09.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeModel = TimeSync(basicConfig); - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 3, - 'resources-total': 10, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 3, - 'resources-total': 10, - }, - ]); - - /**In each 5 second interval, 60% of the time cpu/utilization = 10, 40% of the time it is 0, so cpu/utilization in the averaged result be 6 */ - const expectedResult = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 5, - 'resources-total': 10, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, - 'resources-total': 10, - }, - ]; + describe('execute(): ', () => { + it('throws error if `start-time` is missing.', async () => { + const invalidStartTimeConfig = { + 'start-time': '', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = invalidStartTimeConfig; + const timeModel = TimeSync(pluginSettings); + + expect.assertions(1); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"start-time" parameter is invalid datetime. Error code: invalid_string.' + ) + ); + } + }); - expect(result).toStrictEqual(expectedResult); - }); + it('throws error if `end-time` is missing.', async () => { + const errorMessage = + '"end-time" parameter is invalid datetime. Error code: invalid_string.,`start-time` should be lower than `end-time`'; + const invalidEndTimeConfig = { + 'start-time': '2023-12-12T00:01:00.000Z', + 'end-time': '', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = invalidEndTimeConfig; + const timeModel = TimeSync(pluginSettings); + + expect.assertions(1); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual(new InputValidationError(errorMessage)); + } + }); - it('returns a result when `time-reserved` persists.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:09.000Z', - interval: 5, - 'allow-padding': true, - }; + it('fails if `start-time` is not a valid ISO date.', async () => { + const invalidStartTimeConfig = { + 'start-time': '0023-X', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = invalidStartTimeConfig; + const timeModel = TimeSync(pluginSettings); + expect.assertions(1); + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"start-time" parameter is invalid datetime. Error code: invalid_string.' + ) + ); + } + }); - const timeModel = TimeSync(basicConfig); + it('fails if `end-time` is not a valid ISO date.', async () => { + const invalidEndTimeConfig = { + 'start-time': '2023-12-12T00:01:00.000Z', + 'end-time': '20XX', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = invalidEndTimeConfig; + const timeModel = TimeSync(pluginSettings); + + expect.assertions(1); + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"end-time" parameter is invalid datetime. Error code: invalid_string.' + ) + ); + } + }); - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 3, - 'time-reserved': 5, - 'resources-total': 10, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 3, - 'time-reserved': 5, - 'resources-total': 10, - }, - ]); - - const expectedResult = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 5, - 'resources-total': 10, - 'time-reserved': 3.2, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, - 'resources-total': 10, - 'time-reserved': 3.2, - }, - ]; + it('throws error on missing global config.', async () => { + const config = undefined; + pluginSettings['global-config'] = config!; + const timeModel = TimeSync(pluginSettings); + + expect.assertions(1); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(INVALID_TIME_NORMALIZATION) + ); + } + }); - expect(result).toStrictEqual(expectedResult); - }); + it('throws error if interval is invalid.', async () => { + const invalidIntervalConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 0, + 'allow-padding': true, + }; + pluginSettings['global-config'] = invalidIntervalConfig; + const timeModel = TimeSync(pluginSettings); + + expect.assertions(1); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) + ); + } + }); - it('throws an error when `start-time` is wrong.', async () => { - process.env.MOCK_INTERVAL = 'true'; - const basicConfig = { - 'start-time': '2023-12-12T00:00:90.000Z', - 'end-time': '2023-12-12T00:01:09.000Z', - interval: 5, - 'allow-padding': true, - }; + it('throws error if timestamps overlap.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) + ); + } + }); - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - '"timestamp" parameter is invalid datetime in input[1]. Error code: invalid_string.' - ) - ); - } - }); + it('throws error if `timestamp` is missing.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + '"timestamp" parameter is required in input[0]. Error code: invalid_union.' + ) + ); + } + }); - it('returns a result when the first timestamp in the input has time padding.', async () => { - process.env.MOCK_INTERVAL = 'false'; - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:09.000Z', - interval: 5, - 'allow-padding': true, - }; + it('throws error if the seconds `timestamp` is above 60.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:90.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + '"timestamp" parameter is invalid datetime in input[0]. Error code: invalid_string.' + ) + ); + } + }); - const timeModel = TimeSync(basicConfig); + it('throws an error if the `timestamp` is not valid date.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 10, + 'allow-padding': true, + }; + const data = [ + { + timestamp: 45, + duration: 10, + 'cpu/utilization': 10, + }, + ]; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + expect.assertions(2); + + try { + await timeModel.execute(data); + } catch (error) { + expect(error).toBeInstanceOf(InvalidDateInInputError); + expect(error).toStrictEqual( + new InvalidDateInInputError(INVALID_DATE_TYPE(data[0].timestamp)) + ); + } + }); - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 3, - 'resources-total': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 3, - 'resources-total': 10, - }, - ]); + it('throws error if end is before start in global config.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:10.000Z', + 'end-time': '2023-12-12T00:00:00.000Z', + interval: 5, + 'allow-padding': true, + }; + + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '`start-time` should be lower than `end-time`' + ) + ); + } + }); - const expectedResult = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 5, - 'resources-total': 10, - }, - { - timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, - 'resources-total': 10, - }, - ]; + it('converts Date objects to string outputs.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:01.000Z', + interval: 1, + 'allow-padding': false, + }; + + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 1, + 'cpu/utilization': 10, + }, + { + timestamp: new Date('2023-12-12T00:00:01.000Z'), + duration: 1, + 'cpu/utilization': 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 1, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:01.000Z', + duration: 1, + 'cpu/utilization': 10, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); - expect(result).toStrictEqual(expectedResult); - }); + it('checks that metric (carbon) with aggregation-method == sum is properly spread over interpolated time points.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:10.000Z', + interval: 1, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + carbon: 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:01.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:02.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:03.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:04.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:06.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:07.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:08.000Z', + duration: 1, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:09.000Z', + duration: 1, + carbon: 1, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); - it('throws error if padding is required at start while allow-padding = false.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:10.000Z', - interval: 5, - 'allow-padding': false, - }; + it('checks that constants are copied to results unchanged.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:09.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 3, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 3, + 'resources-total': 10, + }, + ]); + + /**In each 5 second interval, 60% of the time cpu/utilization = 10, 40% of the time it is 0, so cpu/utilization in the averaged result be 6 */ + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + 'resources-total': 10, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:02.000Z', - duration: 15, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, false)) - ); - } - }); + it('returns a result when `time-reserved` persists.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:09.000Z', + interval: 5, + 'allow-padding': true, + }; + + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 3, + 'time-reserved': 5, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 3, + 'time-reserved': 5, + 'resources-total': 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + 'resources-total': 10, + 'time-reserved': 3.2, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + 'resources-total': 10, + 'time-reserved': 3.2, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); - it('throws error if padding is required at end while allow-padding = false.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:10.000Z', - interval: 5, - 'allow-padding': false, - }; + it('throws an error when `start-time` is wrong.', async () => { + process.env.MOCK_INTERVAL = 'true'; + const basicConfig = { + 'start-time': '2023-12-12T00:00:90.000Z', + 'end-time': '2023-12-12T00:01:09.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + '"start-time" parameter is invalid datetime. Error code: invalid_string.' + ) + ); + } + }); - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:10.000Z', - duration: 30, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError('Avoiding padding at end') - ); - } - }); + it('returns a result when the first timestamp in the input has time padding.', async () => { + process.env.MOCK_INTERVAL = 'false'; + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:09.000Z', + interval: 5, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 3, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 3, + 'resources-total': 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + 'resources-total': 10, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); - it('throws error if padding is required at start and end while allow-padding = false.', async () => { - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:10.000Z', - interval: 5, - 'allow-padding': false, - }; + it('throws error if padding is required at start while allow-padding = false.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:10.000Z', + interval: 5, + 'allow-padding': false, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:02.000Z', + duration: 15, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, false)) + ); + } + }); - const timeModel = TimeSync(basicConfig); - - try { - await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:02.000Z', - duration: 10, - 'cpu/utilization': 10, - }, - { - timestamp: '2023-12-12T00:00:08.000Z', - duration: 1, - 'cpu/utilization': 20, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, true)) - ); - } - }); + it('throws error if padding is required at end while allow-padding = false.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:10.000Z', + interval: 5, + 'allow-padding': false, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 30, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError('Avoiding padding at end') + ); + } + }); - it('checks that timestamps in return object are ISO 8061 and timezone UTC.', async () => { - process.env.MOCK_INTERVAL = 'false'; - const basicConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:03.000Z', - interval: 1, - 'allow-padding': true, - }; + it('throws error if padding is required at start and end while allow-padding = false.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:10.000Z', + interval: 5, + 'allow-padding': false, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:02.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + { + timestamp: '2023-12-12T00:00:08.000Z', + duration: 1, + 'cpu/utilization': 20, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, true)) + ); + } + }); - const timeModel = TimeSync(basicConfig); - const result = await timeModel.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 1, - carbon: 1, - }, - ]); - expect( - DateTime.fromISO(result[0].timestamp).zone.valueOf() === - 'FixedOffsetZone { fixed: 0 }' - ); - expect(DateTime.fromISO(result[0].timestamp).offset === 0); + it('checks that timestamps in return object are ISO 8061 and timezone UTC.', async () => { + process.env.MOCK_INTERVAL = 'false'; + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:03.000Z', + interval: 1, + 'allow-padding': true, + }; + pluginSettings['global-config'] = basicConfig; + const timeModel = TimeSync(pluginSettings); + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 1, + carbon: 1, + }, + ]); + expect( + DateTime.fromISO(result[0].timestamp).zone.valueOf() === + 'FixedOffsetZone { fixed: 0 }' + ); + expect(DateTime.fromISO(result[0].timestamp).offset === 0); + }); + }); }); }); From f5f8b9bfaa6741dc4f2ce093599b804737805c03 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:42:11 +0400 Subject: [PATCH 11/21] fix(types): remove `PluginSettings` type --- src/common/types/manifest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 7d75f1eca..c28fe7194 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -7,7 +7,6 @@ export type Manifest = z.infer; export type GlobalPlugins = Manifest['initialize']['plugins']; export type PluginOptions = GlobalPlugins[string]; -export type PluginSettings = Omit; export type AggregationParams = Manifest['aggregation']; export type AggregationParamsWithoutType = Omit< From d6d16d72a5ce7d1f71d5dc459b40be68fa74f295 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:45:57 +0400 Subject: [PATCH 12/21] fix(lib): spread object params to be arguments of the plugin --- src/if-run/lib/initialize.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 956bb30d6..5cae80310 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -9,11 +9,7 @@ import {pluginStorage} from '../util/plugin-storage'; import {CONFIG, STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; -import { - GlobalPlugins, - PluginOptions, - PluginSettings, -} from '../../common/types/manifest'; +import {GlobalPlugins, PluginOptions} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; const { @@ -103,12 +99,7 @@ const initPlugin = async ( const plugin = await handModule(method, path); - const pluginOptions: PluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': parameterMetadata, - mapping, - }; - return plugin(pluginOptions); + return plugin(globalConfig, parameterMetadata, mapping); }; /** From 4dbd1cd620374f0d2c52b31af7793deecfead4b8 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:49:05 +0400 Subject: [PATCH 13/21] fix(builtins): fix plugins to get 3 arguments --- src/if-run/builtins/coefficient/index.ts | 16 +++++----------- src/if-run/builtins/copy-param/index.ts | 16 +++++----------- src/if-run/builtins/csv-lookup/index.ts | 17 +++++------------ src/if-run/builtins/divide/index.ts | 17 +++++------------ src/if-run/builtins/exponent/index.ts | 16 +++++----------- src/if-run/builtins/interpolation/index.ts | 16 +++++----------- src/if-run/builtins/mock-observations/index.ts | 16 +++++----------- src/if-run/builtins/multiply/index.ts | 16 +++++----------- src/if-run/builtins/regex/index.ts | 17 +++++------------ src/if-run/builtins/sci-embodied/index.ts | 11 ++++------- src/if-run/builtins/sci/index.ts | 17 +++++------------ src/if-run/builtins/shell/index.ts | 16 +++++----------- src/if-run/builtins/subtract/index.ts | 16 +++++----------- src/if-run/builtins/sum/index.ts | 17 +++++------------ src/if-run/builtins/time-sync.ts | 16 +++++----------- 15 files changed, 74 insertions(+), 166 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 130c7d37c..6f98ed9d3 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -8,7 +8,6 @@ import { PluginParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -17,16 +16,11 @@ import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Coefficient = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': CoefficientConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Coefficient = ( + globalConfig: CoefficientConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 84a16a5a2..895cab87b 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -8,7 +8,6 @@ import { PluginParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -23,16 +22,11 @@ const {GlobalConfigError} = ERRORS; * to-field: the parameter you are copying to (e.g. cpu/processor-name) */ -export const Copy = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Copy = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index e8de52fa5..4b3bd9c96 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -12,7 +12,6 @@ import { PluginParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -35,17 +34,11 @@ const { CSVParseError, } = ERRORS; -export const CSVLookup = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': any; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const CSVLookup = ( + globalConfig: any, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 730b975c5..ae456eba8 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -8,7 +8,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -17,17 +16,11 @@ import {STRINGS} from '../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; -export const Divide = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const Divide = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 51e6bced4..d6477d74c 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -7,20 +7,14 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; -export const Exponent = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ExponentConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Exponent = ( + globalConfig: ExponentConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 9c9a5a5a6..8c3c9fb8c 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -10,7 +10,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -24,16 +23,11 @@ const { WITHIN_THE_RANGE, } = STRINGS; -export const Interpolation = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Interpolation = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index 4b998795b..b8382cda1 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -9,7 +9,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -18,16 +17,11 @@ import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; -export const MockObservations = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const MockObservations = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index a9b86995c..8ad5798d1 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -7,20 +7,14 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; -export const Multiply = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': MultiplyConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Multiply = ( + globalConfig: MultiplyConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index d5281bda4..943398902 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -8,7 +8,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -17,17 +16,11 @@ import {STRINGS} from '../../config'; const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -export const Regex = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const Regex = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 741344d63..17849ae1b 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -6,7 +6,6 @@ import { PluginParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate, allDefined} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -14,12 +13,10 @@ import {STRINGS} from '../../config'; const {SCI_EMBODIED_ERROR} = STRINGS; -export const SciEmbodied = (options: PluginSettings): ExecutePlugin => { - const {'parameter-metadata': parametersMetadata, mapping} = options as { - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const SciEmbodied = ( + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 5316c703e..506fbb69f 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -8,7 +8,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate, allDefined} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -22,17 +21,11 @@ const { ZERO_DIVISION, } = STRINGS; -export const Sci = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const Sci = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 9ec7deab2..630e65592 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -11,22 +11,16 @@ import { PluginParametersMetadata, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; const {ProcessExecutionError} = ERRORS; -export const Shell = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': ConfigParams; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Shell = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index d1aa1e249..197088fcc 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -7,20 +7,14 @@ import { SubtractConfig, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; -export const Subtract = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': SubtractConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const Subtract = ( + globalConfig: SubtractConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index ae1509d11..29af458cb 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -8,7 +8,6 @@ import { MappingParams, } from '@grnsft/if-core/types'; -import {PluginSettings} from '../../../common/types/manifest'; import {validate} from '../../../common/util/validations'; import {mapOutput} from '../../../common/util/helpers'; @@ -17,17 +16,11 @@ import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Sum = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': SumConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; - +export const Sum = ( + globalConfig: SumConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs, diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index 727788d4f..e0f748bb9 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -17,7 +17,6 @@ import {validate} from '../../common/util/validations'; import {STRINGS} from '../config'; import {getAggregationMethod} from '../lib/aggregate'; -import {PluginSettings} from '../../common/types/manifest'; import {mapOutput} from '../../common/util/helpers'; Settings.defaultZone = 'utc'; @@ -39,16 +38,11 @@ const { INVALID_DATETIME, } = STRINGS; -export const TimeSync = (options: PluginSettings): ExecutePlugin => { - const { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping, - } = options as { - 'global-config': TimeNormalizerConfig; - 'parameter-metadata': PluginParametersMetadata; - mapping: MappingParams; - }; +export const TimeSync = ( + globalConfig: TimeNormalizerConfig, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams +): ExecutePlugin => { const metadata = { kind: 'execute', inputs: parametersMetadata?.inputs || { From 9f6f8d2622781182296790d522796cebad6d00c2 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:53:20 +0400 Subject: [PATCH 14/21] docs(builtins): update readme files --- src/if-run/builtins/coefficient/README.md | 40 +++++++++------- src/if-run/builtins/copy-param/README.md | 27 ++++++----- src/if-run/builtins/csv-lookup/README.md | 20 ++++---- src/if-run/builtins/divide/README.md | 27 +++++++---- src/if-run/builtins/exponent/README.md | 19 +++++--- src/if-run/builtins/interpolation/README.md | 34 +++++++++----- .../builtins/mock-observations/README.md | 46 +++++++++++++------ src/if-run/builtins/multiply/README.md | 28 ++++++----- src/if-run/builtins/regex/README.md | 26 +++++++---- src/if-run/builtins/sci-embodied/README.md | 16 +++++-- src/if-run/builtins/sci/README.md | 19 ++++---- src/if-run/builtins/shell/README.md | 21 +++++---- src/if-run/builtins/subtract/README.md | 27 ++++++----- src/if-run/builtins/sum/README.md | 35 ++++++++------ 14 files changed, 238 insertions(+), 147 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 275f0bf3f..2cc1547b2 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -34,11 +34,14 @@ of the parameters of the inputs and outputs ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +coefficient: + method: Coefficient + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -60,17 +63,15 @@ output = input * coefficient To run the plugin from a Typescript app, you must first create an instance of `Coefficient`. Then, you can call `execute()`. ```typescript -const pluginSettings = { - 'global-config': { - 'input-parameter': 'carbon', - coefficient: 10, - 'output-parameter': 'carbon-product', - }, - 'parameter-metadata': {}, - mapping: {}, +const globalConfig = { + 'input-parameter': 'carbon', + coefficient: 10, + 'output-parameter': 'carbon-product', }; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; -const coeff = Coefficient(pluginSettings); +const coeff = Coefficient(globalConfig, parametersMetadata, mapping); const result = coeff.execute([ { duration: 3600, @@ -97,15 +98,20 @@ initialize: input-parameter: 'carbon' coefficient: 3 output-parameter: 'carbon-product' - parameter-metadata: + parameter-metadata: inputs: carbon: - description: "an amount of carbon emitted into the atmosphere" - unit: "gCO2e" + description: 'an amount of carbon emitted into the atmosphere' + unit: 'gCO2e' + aggregation-method: sum outputs: carbon-product: - description: "a product of cabon property and the coefficient" - unit: "gCO2e" + description: 'a product of cabon property and the coefficient' + unit: 'gCO2e' + aggregation-method: sum + mapping: + carbon-product: calculated-carbon + tree: children: child: diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 68acd6e22..b3e57600a 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -56,11 +56,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +copy-param: + path: builtin + method: Copy + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -78,17 +81,15 @@ To run the plugin, you must first create an instance of `Copy`. Then, you can ca ```typescript import {Copy} from '.'; -const pluginSettings = { - 'global-config': { - 'keep-existing': true, - from: 'from-param', - to: 'to-param', - }, - 'parameter-metadata': {}, - mapping: {}, +const globalConfig = { + 'keep-existing': true, + from: 'from-param', + to: 'to-param', }; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; -const plugin = Copy(pluginSettings); +const plugin = Copy(globalConfig, parametersMetadata, mapping); const result = plugin.execute([ { @@ -118,6 +119,8 @@ initialize: keep-existing: true from: original to: copy + mapping: + original: from tree: children: child-1: diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 708dfa87b..247155fd8 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -70,11 +70,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +cloud-metadata: + method: CSVLookup + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -108,12 +111,9 @@ const globalConfig = { }, output: ['cpu-tdp', 'tdp'], }; -const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {} - mapping: {} -}; -const csvLookup = CSVLookup(pluginSettings); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const csvLookup = CSVLookup(globalConfig); const input = [ { @@ -145,6 +145,8 @@ initialize: cloud-provider: 'cloud/provider' cloud-region: 'cloud/region' output: '*' + mapping: + cloud/region: cloud/area tree: children: child: diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 4c91f5c2e..dc2c37394 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -30,11 +30,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +divide: + method: Divide + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -62,14 +65,16 @@ output = input0 / input1 To run the plugin, you must first create an instance of `Divide`. Then, you can call `execute()`. ```typescript -const pluginSettings = { - 'global-config': { - numerator: 'vcpus-allocated', - denominator: 2, - output: 'cpu/number-cores', - }, +const globalConfig = { + numerator: 'vcpus-allocated', + denominator: 2, + output: 'cpu/number-cores', +}; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = { + 'vcpus-allocated': 'vcpus-distributed', }; -const divide = Divide(pluginSettings); +const divide = Divide(globalConfig, parametersMetadata, mapping); const input = [ { @@ -97,6 +102,8 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores + mapping: + vcpus-allocated: vcpus-distributed tree: children: child: diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index 0fb280f2e..d9f194f1f 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -33,11 +33,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +exponent: + method: Exponent + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -61,15 +64,15 @@ To run the plugin, you must first create an instance of `Exponent`. Then, you ca ```typescript import {Exponent} from 'builtins'; -const pluginSettings = { - 'global-config': { +const globalConfig = { inputParameter: ['cpu/energy'], exponent: 2 outputParameter: 'energy', - }, }; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; -const exponent = Exponent(pluginSettings); +const exponent = Exponent(globalConfig, parametersMetadata, mapping); const result = await exponent.execute([ { duration: 3600, @@ -97,6 +100,8 @@ initialize: input-parameter: 'cpu/energy' exponent: 2 output-parameter: 'energy' + mapping: + energy/base: energy/main tree: children: child: diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index af870a8e0..9c2850179 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -42,11 +42,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +interpolation: + method: Interpolation + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ## Input Parameters @@ -93,17 +96,21 @@ The plugin conducts input validation using the `zod` library and may throw error ### TypeScript Usage ```ts -const pluginSettings = { - 'global-config': { - method: 'linear', - x: [0, 10, 50, 100], - y: [0.12, 0.32, 0.75, 1.02], - 'input-parameter': 'cpu/utilization', - 'output-parameter': 'cpu/energy', - }, +const globalConfig = { + method: 'linear', + x: [0, 10, 50, 100], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': 'cpu/utilization', + 'output-parameter': 'cpu/energy', }; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; -const interpolationPlugin = Interpolation(pluginSettings); +const interpolationPlugin = Interpolation( + globalConfig, + parametersMetadata, + mapping +); const inputs = [ { @@ -137,6 +144,9 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: 'cpu/utilization' output-parameter: 'cpu/energy' + mapping: + cpu/utilization: cpu/util + interpolation-result: result tree: children: child: diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 629e1ef75..79e02710d 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -32,6 +32,19 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) +### Mapping + +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: + +```yaml +mock-observations: + kind: plugin + method: MockObservations + path: 'builtin' + mapping: + 'old-name': 'new-name' +``` + ### Authentication N/A @@ -44,22 +57,26 @@ The plugin's `global-config` section in the manifest file determines its behavio ### Typescript Usage ```typescript -const pluginSettings = { - 'global-config': { - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:10', - duration: 60, - components: { - 'instance-type': 'A1', - }, - generators: { - common: { - region: 'uk-west', - }, +const globalConfig = { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:10', + duration: 60, + components: { + 'instance-type': 'A1', + }, + generators: { + common: { + region: 'uk-west', }, }, }; -const mockObservations = MockObservations(pluginSettings); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const mockObservations = MockObservations( + globalConfig, + parametersMetadata, + mapping +); const result = await mockObservations.execute([]); ``` @@ -95,6 +112,9 @@ initialize: memory/utilization: min: 1 max: 99 + mapping: + cpu/utilization: cpu/util + tree: children: child: diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 6ecb40c08..31f12ba91 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -32,11 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +multiply: + method: Multiply + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -60,16 +63,14 @@ To run the plugin, you must first create an instance of `Multiply`. Then, you ca ```typescript import {Multiply} from 'builtins'; -const pluginSettings = { - 'global-config': { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'energy-product', - }, - 'parameter-metadata': {}, - mapping: {}, +const globalConfig = { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'energy-product', }; -const multiply = Multiply(pluginSettings); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const multiply = Multiply(globalConfig, parametersMetadata, mapping); const result = await multiply.execute([ { duration: 3600, @@ -82,7 +83,7 @@ const result = await multiply.execute([ ## Example manifest -IF users will typically call the plugin as part of a pipeline defined in a manifest file. In this case, instantiating the plugin is handled by `ie` and does not have to be done explicitly by the user. The following is an example manifest that calls `multiply`: +IF users will typically call the plugin as part of a pipeline defined in a manifest file. In this case, instantiating the plugin is handled by `if-run` and does not have to be done explicitly by the user. The following is an example manifest that calls `multiply`: ```yaml name: multiply-demo @@ -96,6 +97,9 @@ initialize: global-config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy-product' + mapping: + cpu/energy: energy-from-cpu + network/energy: energy-from-network tree: children: child: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 1234b003f..ee53316d1 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -33,11 +33,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +regex: + method: Regex + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -53,14 +56,14 @@ mapping: To run the plugin, you must first create an instance of `Regex`. Then, you can call `execute()`. ```typescript -const pluginSettings = { - 'global-config': { - parameter: 'physical-processor', - match: '^[^,]+', - output: 'cpu/name', - }, +const globalConfig = { + parameter: 'physical-processor', + match: '^[^,]+', + output: 'cpu/name', }; -const regex = Regex(pluginSettings); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const regex = Regex(globalConfig, parametersMetadata, mapping); const input = [ { @@ -89,6 +92,9 @@ initialize: parameter: physical-processor match: ^[^,]+ output: cpu/name + mapping: + physical-processor: processor + tree: children: child: diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index a546494d0..4e892fb97 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -27,11 +27,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +sci-embodied: + method: SciEmbodied + path: 'builtins' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -82,7 +85,9 @@ The following snippet demonstrates how to call the `sci-embodied` plugin from Ty ```typescript import {SciEmbodied} from 'builtins'; -const sciEmbodied = SciEmbodied(); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const sciEmbodied = SciEmbodied(parametersMetadata, mapping); const results = await sciEmbodied.execute([ { 'device/emissions-embodied': 200, // in gCO2e for total resource units @@ -107,6 +112,9 @@ initialize: sci-embodied: method: SciEmbodied path: 'builtins' + mapping: + device/emissions-embodied: device/carbon-footprint + carbon-embodied: carbon-footprint tree: children: child: diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index e67b88066..a3cbc3e9d 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -26,11 +26,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +sci: + method: Sci + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -58,10 +61,10 @@ To run the plugin, you must first create an instance of `Sci`. Then, you can cal ```typescript import {Sci} from 'builtins'; -const pluginSettings = { - 'global-config': {'functional-unit': 'requests'} -} -const sci = Sci(); +const globalConfig = {'functional-unit': 'requests'} +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const sci = Sci(globalConfig, parametersMetadata, mapping); const results = await sci.execute( [ { @@ -75,7 +78,7 @@ const results = await sci.execute( ## Example manifest -IF users will typically call the plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating the plugin is handled by `ie` and does not have to be done explicitly by the user. +IF users will typically call the plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating the plugin is handled by `if-run` and does not have to be done explicitly by the user. The following is an example `manifest` that calls `sci`: diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index b3e3f0c85..1daa15cbc 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -46,11 +46,14 @@ The parameters included in the `inputs` field in the `manifest` depend entirely ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +sampler: + method: Shell + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ## Returns @@ -62,12 +65,12 @@ The specific return types depend on the plugin being invoked. Typically, we woul To run the plugin, you must first create an instance of `Shell` and call its `execute()` to run the external plugin. ```typescript -const pluginSettings = { - 'global-config': { - command: '/usr/local/bin/sampler', - }, +const globalConfig = { + command: '/usr/local/bin/sampler', }; -const output = Shell(pluginSettings); +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const output = Shell(globalConfig, parametersMetadata, mapping); const result = await output.execute([ { timestamp: '2021-01-01T00:00:00Z', @@ -101,6 +104,8 @@ initialize: path: 'builtin' global-config: command: python3 /usr/local/bin/sampler + mapping: + cpu/energy: energy-for-cpu tree: children: child: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index f2829555d..f5024e4a8 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -32,11 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +subtract: + method: Subtract + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -60,14 +63,13 @@ To run the plugin, you must first create an instance of `Subtract`. Then, you ca ```typescript import {Subtract} from 'builtins'; -const pluginSettings = { - 'global-config': { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'offset/energy', - } -} - -const subtract = Subtract(pluginSettings); +const globalConfig = { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'offset/energy', +}; +const parametersMetadata = {inputs: {}, outputs: {}}; +const mapping = {}; +const subtract = Subtract(globalConfig, parametersMetadata, mapping); const result = subtract subtract.execute([ { duration: 3600, @@ -94,6 +96,9 @@ initialize: global-config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy/diff' + mapping: + cpu/energy: energy-for-cpu + tree: children: child: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index c52d5e6c4..b6fa9b9b5 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -32,11 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block allows to rename the parameters of the input and output with new names. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: ```yaml -mapping: - 'old-name': 'new-name' +sum: + method: Sum + path: 'builtin' + mapping: + 'old-name': 'new-name' ``` ### Inputs @@ -58,19 +61,17 @@ output = input0 + input1 + input2 ... inputN To run the plugin, you must first create an instance of `Sum`. Then, you can call `execute()`. ```typescript -const pluginSettings = { - 'global-config': { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'energy', - }, - 'parameter-metadata': {}, - mapping: { - 'cpu/energy': 'energy-from-cpu', - 'network/energy': 'energy-from-network', - }, +const globalConfig = { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'energy', +}; +const parametersMetadata = {inputs: {}, outputs: {}}; +const = mapping { + 'cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', }; -const sum = Sum(pluginSettings); +const sum = Sum(globalConfig, parametersMetadata, mapping); const result = sum.execute([ { timestamp: '2021-01-01T00:00:00Z', @@ -102,13 +103,19 @@ initialize: cpu/energy: description: energy consumed by the cpu unit: kWh + aggregation-method: sum network/energy: description: energy consumed by data ingress and egress unit: kWh + aggregation-method: sum outputs: energy: description: sum of energy components unit: kWh + aggregation-method: sum + mapping: + cpu/energy: energy-from-cpu + network/energy: energy-from-network tree: children: child: From 83bbe68f17427fc2e8c199750ff901bf7875ba85 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:57:08 +0400 Subject: [PATCH 15/21] test(builtins): update tests according to PRs --- .../if-run/builtins/coefficient.test.ts | 61 ++++--- .../if-run/builtins/copy-param.test.ts | 56 +++--- .../if-run/builtins/csv-lookup.test.ts | 144 +++++++-------- src/__tests__/if-run/builtins/divide.test.ts | 72 ++++---- .../if-run/builtins/exponent.test.ts | 42 +++-- .../if-run/builtins/interpolation.test.ts | 77 ++++---- .../if-run/builtins/mock-observations.test.ts | 164 +++++++++++------- .../if-run/builtins/multiply.test.ts | 45 ++++- src/__tests__/if-run/builtins/regex.test.ts | 54 ++++-- .../if-run/builtins/sci-embodied.test.ts | 59 ++++++- src/__tests__/if-run/builtins/sci.test.ts | 58 +++++-- src/__tests__/if-run/builtins/shell.test.ts | 73 ++++++-- .../if-run/builtins/subtract.test.ts | 43 ++++- src/__tests__/if-run/builtins/sum.test.ts | 21 +-- .../if-run/builtins/time-sync.test.ts | 141 +++++++++------ 15 files changed, 700 insertions(+), 410 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 453f6954a..9a0db46d1 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -18,12 +18,7 @@ describe('builtins/coefficient: ', () => { inputs: {}, outputs: {}, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const coefficient = Coefficient(pluginSettings); + const coefficient = Coefficient(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -58,14 +53,42 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('succcessfully executes when the mapping has data.', () => { + const mapping = { + carbon: 'carbon-for-production', + }; + const coefficient = Coefficient( + globalConfig, + parametersMetadata, + mapping + ); + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'carbon-for-production': 3, + 'carbon-product': 9, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = coefficient.execute([ + { + duration: 3600, + carbon: 3, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect.assertions(1); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error when global config is not provided.', () => { const config = undefined; - const pluginSettings = { - 'global-config': config!, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const coefficient = Coefficient(pluginSettings); + const coefficient = Coefficient(config!, parametersMetadata, {}); expect.assertions(1); @@ -90,12 +113,7 @@ describe('builtins/coefficient: ', () => { coefficient: 3, 'output-parameter': 'carbon-product', }; - const pluginSettings = { - 'global-config': invalidConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const coefficient = Coefficient(pluginSettings); + const coefficient = Coefficient(invalidConfig, parametersMetadata, {}); const expectedMessage = '"input-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; @@ -122,12 +140,7 @@ describe('builtins/coefficient: ', () => { coefficient: 10, 'output-parameter': '', }; - const pluginSettings = { - 'global-config': invalidConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const coefficient = Coefficient(pluginSettings); + const coefficient = Coefficient(invalidConfig, parametersMetadata, {}); const expectedMessage = '"output-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 7b8e2ffa3..9f64539c2 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -18,12 +18,7 @@ describe('builtins/copy: ', () => { inputs: {}, outputs: {}, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const copy = Copy(pluginSettings); + const copy = Copy(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -56,14 +51,37 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executed when `mapping` has valid data.', () => { + expect.assertions(1); + + const mapping = { + original: 'from', + }; + + const copy = Copy(globalConfig, parametersMetadata, mapping); + const expectedResult = [ + { + duration: 3600, + from: 'hello', + copy: 'hello', + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = copy.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + original: 'hello', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error when global config is not provided.', () => { const config = undefined; - const pluginSettings = { - 'global-config': config!, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const copy = Copy(pluginSettings); + const copy = Copy(config!, parametersMetadata, {}); expect.assertions(1); @@ -88,12 +106,7 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const copy = Copy(pluginSettings); + const copy = Copy(globalConfig, parametersMetadata, {}); expect.assertions(1); try { @@ -118,12 +131,7 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': parametersMetadata, - mapping: {}, - }; - const copy = Copy(pluginSettings); + const copy = Copy(globalConfig, parametersMetadata, {}); const expectedResult = [ { diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index 18270fa11..52198de47 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -22,6 +22,10 @@ describe('builtins/CSVLookup: ', () => { const mock = new AxiosMockAdapter(axios); describe('CSVLookup: ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; afterEach(() => { mock.reset(); }); @@ -35,12 +39,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); expect(csvLookup).toHaveProperty('metadata'); expect(csvLookup).toHaveProperty('execute'); }); @@ -59,12 +58,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const responseData = `cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,gpu-count,gpu-model-name,Hardware Information on AWS Documentation & Comments,instance-class,instance-storage,memory-available,platform-memory,release-date,storage-drives 16,8,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.2xlarge,EBS-Only,16,32,November 2018,0 @@ -103,12 +97,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -131,6 +120,45 @@ describe('builtins/CSVLookup: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when `mapping` has valid data.', async () => { + expect.assertions(1); + const globalConfig = { + filepath: './file.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + const parameterMetadata = {inputs: {}, outputs: {}}; + const mapping = { + tdp: 'cpu/tdp', + 'cpu/utilized': 'cpu/util', + }; + const csvLookup = CSVLookup(globalConfig, parameterMetadata, mapping); + + const result = await csvLookup.execute([ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]); + const expectedResult = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/util': 16, + 'cpu/manufacturer': 'AWS', + 'cpu/tdp': 150, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + it('rejects with file not found error.', async () => { const globalConfig = { filepath: './file-fail.csv', @@ -141,12 +169,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const input = [ { timestamp: '2024-03-01', @@ -175,12 +198,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const input = [ { timestamp: '2024-03-01', @@ -212,12 +230,7 @@ describe('builtins/CSVLookup: ', () => { }; mock.onGet(globalConfig.filepath).reply(404); - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const input = [ { timestamp: '2024-03-01', @@ -247,12 +260,7 @@ describe('builtins/CSVLookup: ', () => { }, output: '*', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -300,12 +308,7 @@ describe('builtins/CSVLookup: ', () => { ['gpu-model-name', 'gpumodel'], ], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -340,12 +343,7 @@ describe('builtins/CSVLookup: ', () => { }, output: 'gpu-count', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -379,12 +377,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const input = [ { timestamp: '2024-03-01', @@ -409,7 +402,7 @@ describe('builtins/CSVLookup: ', () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - const csvLookup = CSVLookup({}); + const csvLookup = CSVLookup(); const input = [ { timestamp: '2024-03-01', @@ -441,12 +434,8 @@ describe('builtins/CSVLookup: ', () => { }, output: 'mock', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const input = [ { timestamp: '2024-03-01', @@ -479,12 +468,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['gpu-count'], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -518,12 +502,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); const result = await csvLookup.execute([ { @@ -559,12 +538,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const csvLookup = CSVLookup(pluginSettings); + const csvLookup = CSVLookup(globalConfig, parametersMetadata, {}); try { await csvLookup.execute([ diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index 3f5bc78a8..1d616f7ab 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -14,12 +14,11 @@ describe('builtins/divide: ', () => { denominator: 2, output: 'cpu/number-cores', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const divide = Divide(pluginSettings); + const divide = Divide(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -52,6 +51,34 @@ describe('builtins/divide: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when `mapping` has valid data.', async () => { + expect.assertions(1); + const mapping = { + 'vcpus-allocated': 'vcpus-distributed', + }; + + const divide = Divide(globalConfig, parametersMetadata, mapping); + + const expectedResult = [ + { + duration: 3600, + 'vcpus-distributed': 24, + 'cpu/number-cores': 12, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = await divide.execute([ + { + duration: 3600, + 'vcpus-allocated': 24, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('returns a result when `denominator` is provded in input.', async () => { expect.assertions(1); const globalConfig = { @@ -59,12 +86,7 @@ describe('builtins/divide: ', () => { denominator: 'duration', output: 'vcpus-allocated-per-second', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const divide = Divide(pluginSettings); + const divide = Divide(globalConfig, parametersMetadata, {}); const input = [ { @@ -96,12 +118,7 @@ describe('builtins/divide: ', () => { denominator: 3600, output: 'vcpus-allocated-per-second', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const divide = Divide(pluginSettings); + const divide = Divide(globalConfig, parametersMetadata, {}); expect.assertions(1); @@ -122,12 +139,7 @@ describe('builtins/divide: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - const pluginSettings = { - 'global-config': config!, - 'parameter-metadata': {}, - mapping: {}, - }; - const divide = Divide(pluginSettings); + const divide = Divide(config!, parametersMetadata, {}); expect.assertions(1); @@ -151,12 +163,7 @@ describe('builtins/divide: ', () => { denominator: 0, output: 'vcpus-allocated-per-second', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const divide = Divide(pluginSettings); + const divide = Divide(globalConfig, parametersMetadata, {}); expect.assertions(1); @@ -184,12 +191,7 @@ describe('builtins/divide: ', () => { denominator: '10', output: 'vcpus-allocated-per-second', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const divide = Divide(pluginSettings); + const divide = Divide(globalConfig, parametersMetadata, {}); expect.assertions(1); diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index c8d00a255..3eef64c1e 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -11,12 +11,11 @@ describe('builtins/exponent: ', () => { exponent: 3, 'output-parameter': 'energy', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const exponent = Exponent(pluginSettings); + const exponent = Exponent(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -49,6 +48,32 @@ describe('builtins/exponent: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when `mapping` has valid data.', async () => { + expect.assertions(1); + const mapping = { + 'energy/base': 'energy/main', + }; + const exponent = Exponent(globalConfig, parametersMetadata, mapping); + const expectedResult = [ + { + duration: 3600, + 'energy/main': 2, + energy: 8, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = await exponent.execute([ + { + duration: 3600, + 'energy/base': 2, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error on missing params in input.', async () => { expect.assertions(1); @@ -96,12 +121,7 @@ describe('builtins/exponent: ', () => { exponent: 4, 'output-parameter': 'carbon', }; - const pluginSettings = { - 'global-config': newConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const exponent = Exponent(pluginSettings); + const exponent = Exponent(newConfig, parametersMetadata, {}); const data = [ { diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index 1bd135aaa..f5f1b7f27 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -22,10 +22,9 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; const inputs = [ { @@ -34,7 +33,7 @@ describe('builtins/interpolation: ', () => { 'cpu/utilization': 45, }, ]; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(globalConfig, parametersMetadata, {}); describe('init Interpolation: ', () => { it('initalizes object with properties.', async () => { @@ -57,6 +56,24 @@ describe('builtins/interpolation: ', () => { expect(plugin.execute(inputs)).toEqual(outputs); }); + it('returns result when `mapping` has valid data.', () => { + const mapping = { + 'cpu/utilization': 'cpu/util', + 'interpolation-result': 'result', + }; + const plugin = Interpolation(globalConfig, parametersMetadata, mapping); + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/util': 45, + result: 0.69625, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + it('returns result when the `method` is not provided in the global config.', () => { const globalConfig = { x: [0, 10, 50, 100], @@ -64,12 +81,7 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(globalConfig, parametersMetadata, {}); const outputs = [ { @@ -85,12 +97,7 @@ describe('builtins/interpolation: ', () => { it('returns result when the `method` is `spline`.', () => { const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config, parametersMetadata, {}); const outputs = [ { @@ -108,12 +115,7 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { method: Method.POLYNOMIAL, }); - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config, parametersMetadata, {}); const outputs = [ { @@ -131,12 +133,7 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { x: [0, 10, 100, 50], }); - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config, parametersMetadata, {}); const outputs = [ { @@ -172,12 +169,7 @@ describe('builtins/interpolation: ', () => { it('throws an when the global config is not provided.', () => { const config = undefined; - const pluginSettings = { - 'global-config': config!, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config!, parametersMetadata, {}); expect.assertions(2); try { @@ -192,13 +184,7 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { x: [0, 10, 100], }); - - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config, parametersMetadata, {}); expect.assertions(2); try { @@ -233,12 +219,7 @@ describe('builtins/interpolation: ', () => { 'output-parameter': 'interpolation-result', }; const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const plugin = Interpolation(pluginSettings); + const plugin = Interpolation(config, parametersMetadata, {}); const inputs = [ { timestamp: '2023-07-06T00:00', diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index ac2f2409a..3c43040e7 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -8,6 +8,10 @@ const {InputValidationError, GlobalConfigError} = ERRORS; const {INVALID_MIN_MAX} = STRINGS; describe('builtins/mock-observations: ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; describe('init: ', () => { it('successfully initalized.', () => { const globalConfig = { @@ -26,12 +30,11 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + globalConfig, + parametersMetadata, + {} + ); expect(mockObservations).toHaveProperty('metadata'); expect(mockObservations).toHaveProperty('execute'); @@ -55,12 +58,7 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations(config, parametersMetadata, {}); const result = await mockObservations.execute([]); expect.assertions(1); @@ -101,6 +99,70 @@ describe('builtins/mock-observations: ', () => { ]); }); + it('executes successfully when `mapping` is provided.', async () => { + const config = { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + duration: 30, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 11}, + }, + }, + }; + const mapping = { + 'cpu/utilization': 'cpu/util', + }; + const mockObservations = MockObservations( + config, + parametersMetadata, + mapping + ); + const result = await mockObservations.execute([]); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2023-07-06T00:00:00.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'A1', + region: 'uk-west', + 'cpu/util': 10, + }, + { + timestamp: '2023-07-06T00:00:30.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'A1', + region: 'uk-west', + 'cpu/util': 10, + }, + { + timestamp: '2023-07-06T00:00:00.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'B1', + region: 'uk-west', + 'cpu/util': 10, + }, + { + timestamp: '2023-07-06T00:00:30.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'B1', + region: 'uk-west', + 'cpu/util': 10, + }, + ]); + }); + it('throws an error when the `min` is greater then `max` of `randint` config.', async () => { const config = { 'timestamp-from': '2023-07-06T00:00', @@ -117,15 +179,10 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; expect.assertions(2); - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations(config, parametersMetadata, {}); try { await mockObservations.execute([]); } catch (error) { @@ -143,16 +200,14 @@ describe('builtins/mock-observations: ', () => { duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - expect.assertions(2); try { - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + config, + parametersMetadata, + {} + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -182,16 +237,14 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - expect.assertions(2); try { - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + config, + parametersMetadata, + {} + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -218,12 +271,11 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + globalConfig, + parametersMetadata, + {} + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -254,12 +306,11 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + globalConfig, + parametersMetadata, + {} + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -290,12 +341,11 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations( + globalConfig, + parametersMetadata, + {} + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -321,12 +371,7 @@ describe('builtins/mock-observations: ', () => { randint: null, }, }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations(config, parametersMetadata, {}); expect.assertions(2); @@ -356,12 +401,7 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const pluginSettings = { - 'global-config': config, - 'parameter-metadata': {}, - mapping: {}, - }; - const mockObservations = MockObservations(pluginSettings); + const mockObservations = MockObservations(config, parametersMetadata, {}); expect.assertions(2); diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index b07ff7734..ec6571863 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -10,12 +10,11 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const multiply = Multiply(pluginSettings); + const multiply = Multiply(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -52,6 +51,39 @@ describe('builtins/multiply: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when `mapping` is provided.', async () => { + expect.assertions(1); + const mapping = { + 'cpu/energy': 'energy-from-cpu', + 'network/energy': 'energy-from-network', + 'memory/energy': 'energy-from-memory', + }; + const multiply = Multiply(globalConfig, parametersMetadata, mapping); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-from-cpu': 2, + 'energy-from-network': 2, + 'energy-from-memory': 2, + energy: 8, + }, + ]; + + const result = await multiply.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error on missing params in input.', async () => { expect.assertions(1); @@ -77,8 +109,7 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-product', }; - pluginSettings['global-config'] = newConfig; - const multiply = Multiply(pluginSettings); + const multiply = Multiply(newConfig, parametersMetadata, {}); const data = [ { diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index df0383d89..1fc5070a8 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -14,12 +14,11 @@ describe('builtins/regex: ', () => { match: '^[^,]+', output: 'cpu/name', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const regex = Regex(pluginSettings); + const regex = Regex(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -54,14 +53,13 @@ describe('builtins/regex: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully applies regex strategy with multiple matches', async () => { + it('successfully applies regex strategy with multiple matches.', async () => { const globalConfig = { parameter: 'cloud/instance-type', match: '/(?<=_)[^_]+?(?=_|$)/g', output: 'cloud/instance-type', }; - pluginSettings['global-config'] = globalConfig; - const regex = Regex(pluginSettings); + const regex = Regex(globalConfig, parametersMetadata, {}); const expectedResult = [ { @@ -82,6 +80,37 @@ describe('builtins/regex: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully applies regex when `mapping` has valid data.', async () => { + const globalConfig = { + parameter: 'cloud/instance-type', + match: '/(?<=_)[^_]+?(?=_|$)/g', + output: 'cloud/instance-type', + }; + + const mapping = { + 'cloud/instance-type': 'instance-type', + }; + const regex = Regex(globalConfig, parametersMetadata, mapping); + + const expectedResult = [ + { + timestamp: '2023-08-06T00:00', + duration: 3600, + 'instance-type': 'DS1 v2', + }, + ]; + + const result = await regex.execute([ + { + timestamp: '2023-08-06T00:00', + duration: 3600, + 'cloud/instance-type': 'Standard_DS1_v2', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('returns a result when regex is not started and ended with ``.', async () => { const physicalProcessor = 'Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz,Intel® Xeon® E5-2673 v3 2.4 GHz'; @@ -92,8 +121,7 @@ describe('builtins/regex: ', () => { match: '[^,]+/', output: 'cpu/name', }; - pluginSettings['global-config'] = globalConfig; - const regex = Regex(pluginSettings); + const regex = Regex(globalConfig, parametersMetadata, {}); const expectedResult = [ { @@ -124,8 +152,7 @@ describe('builtins/regex: ', () => { match: '^(^:)+', output: 'cpu/name', }; - pluginSettings['global-config'] = globalConfig; - const regex = Regex(pluginSettings); + const regex = Regex(globalConfig, parametersMetadata, {}); expect.assertions(1); @@ -148,8 +175,7 @@ describe('builtins/regex: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - pluginSettings['global-config'] = config!; - const regex = Regex(pluginSettings); + const regex = Regex(config!, parametersMetadata, {}); expect.assertions(1); diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 9daef9288..47cc028d5 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -9,11 +9,11 @@ const {SCI_EMBODIED_ERROR} = STRINGS; describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { - const pluginSettings = { - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const sciEmbodied = SciEmbodied(pluginSettings); + const sciEmbodied = SciEmbodied(parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -69,6 +69,57 @@ describe('builtins/sci-embodied:', () => { ]); }); + it('executes when `mapping` has valid data.', async () => { + const mapping = { + 'device/emissions-embodied': 'device/carbon-footprint', + 'carbon-embodied': 'carbon-footprint', + }; + const sciEmbodied = SciEmbodied(parametersMetadata, mapping); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + }, + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30 * 2, + 'device/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + }, + ]; + + const result = await sciEmbodied.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/carbon-footprint': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + 'carbon-footprint': 4.10958904109589, + }, + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30 * 2, + 'device/carbon-footprint': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + 'carbon-footprint': 4.10958904109589 * 2, + }, + ]); + }); + it('returns a result when `vcpus-allocated` and `vcpus-total` are in the input.', async () => { const inputs = [ { diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index 1c74ec4fc..37826ecc8 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -6,12 +6,9 @@ const {MissingInputDataError} = ERRORS; describe('builtins/sci:', () => { describe('Sci: ', () => { - const pluginSettings = { - 'global-config': {'functional-unit': 'users'}, - 'parameter-metadata': {}, - mapping: {}, - }; - const sci = Sci(pluginSettings); + const config = {'functional-unit': 'users'}; + const parametersMetadata = {inputs: {}, outputs: {}}; + const sci = Sci(config, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -22,7 +19,6 @@ describe('builtins/sci:', () => { describe('execute():', () => { it('returns a result with valid inputs.', async () => { - const sci = Sci(pluginSettings); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -50,9 +46,41 @@ describe('builtins/sci:', () => { ]); }); + it('successfully executes when `mapping` has valid data.', async () => { + const mapping = { + 'carbon-embodied': 'carbon-footprint', + }; + const sci = Sci(config, parametersMetadata, mapping); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 1, + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-footprint': 5, + carbon: 5.02, + users: 100, + duration: 1, + sci: 0.050199999999999995, + }, + ]); + }); + it('returns the same result regardless of input duration.', async () => { - pluginSettings['global-config'] = {'functional-unit': 'requests'}; - const sci = Sci(pluginSettings); + const config = {'functional-unit': 'requests'}; + const sci = Sci(config, parametersMetadata, {}); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -98,8 +126,8 @@ describe('builtins/sci:', () => { }); it('throws exception on invalid functional unit data.', async () => { - pluginSettings['global-config'] = {'functional-unit': 'requests'}; - const sci = Sci(pluginSettings); + const config = {'functional-unit': 'requests'}; + const sci = Sci(config, parametersMetadata, {}); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -119,8 +147,8 @@ describe('builtins/sci:', () => { }); it('throws exception if functional unit value is not positive integer.', async () => { - pluginSettings['global-config'] = {'functional-unit': 'requests'}; - const sci = Sci(pluginSettings); + const config = {'functional-unit': 'requests'}; + const sci = Sci(config, parametersMetadata, {}); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -142,8 +170,8 @@ describe('builtins/sci:', () => { }); it('fallbacks to carbon value, if functional unit is 0.', async () => { - pluginSettings['global-config'] = {'functional-unit': 'requests'}; - const sci = Sci(pluginSettings); + const config = {'functional-unit': 'requests'}; + const sci = Sci(config, parametersMetadata, {}); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts index ad5ce6689..4febe9f93 100644 --- a/src/__tests__/if-run/builtins/shell.test.ts +++ b/src/__tests__/if-run/builtins/shell.test.ts @@ -11,12 +11,12 @@ jest.mock('js-yaml'); describe('builtins/shell', () => { describe('Shell', () => { - const pluginSettings = { - 'global-config': {command: 'python3 /path/to/script.py'}, - 'parameter-metadata': {}, - mapping: {}, + const globalConfig = {command: 'python3 /path/to/script.py'}; + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const shell = Shell({'global-config': {}}); + const shell = Shell(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -26,8 +26,7 @@ describe('builtins/shell', () => { }); describe('execute(): ', () => { - it('execute with valid inputs and command', async () => { - const shell = Shell(pluginSettings); + it('executes with valid inputs and command.', async () => { const mockSpawnSync = spawnSync as jest.MockedFunction< typeof spawnSync >; @@ -57,7 +56,61 @@ describe('builtins/shell', () => { expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); }); - it('throw an error if validation fails', async () => { + it('executes when `mapping` is provided.', async () => { + const mapping = { + 'cpu/energy': 'energy-for-cpu', + }; + const shell = Shell(globalConfig, parametersMetadata, mapping); + const mockSpawnSync = spawnSync as jest.MockedFunction< + typeof spawnSync + >; + mockSpawnSync.mockReturnValueOnce({stdout: 'mocked stdout'} as any); + + const mockLoadAll = loadAll as jest.MockedFunction; + mockLoadAll.mockReturnValueOnce([ + { + timestamp: '2023-11-02T10:35:31.820Z', + duration: 3600, + 'energy-for-cpu': 0.002, + 'memory/energy': 0.000005, + energy: 1, + }, + ] as any); + + const inputs = [ + { + timestamp: '2023-11-02T10:35:31.820Z', + duration: 3600, + 'cpu/energy': 0.002, + 'memory/energy': 0.000005, + }, + ]; + + expect.assertions(3); + + const result = await shell.execute(inputs); + expect(result).toEqual([ + { + timestamp: '2023-11-02T10:35:31.820Z', + duration: 3600, + 'energy-for-cpu': 0.002, + 'memory/energy': 0.000005, + energy: 1, + }, + ]); + + expect(mockSpawnSync).toHaveBeenCalledWith( + 'python3', + ['/path/to/script.py'], + { + encoding: 'utf8', + } + ); + expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); + }); + + it('throws an error if validation fails.', async () => { + const shell = Shell({}, parametersMetadata, {}); const invalidInputs = [ {duration: 3600, timestamp: '2022-01-01T00:00:00Z', command: 123}, ]; @@ -75,8 +128,8 @@ describe('builtins/shell', () => { } }); - it('throw an error when shell could not run command.', async () => { - const shell = Shell(pluginSettings); + it('throws an error when shell could not run command.', async () => { + const shell = Shell(globalConfig, parametersMetadata, {}); (spawnSync as jest.Mock).mockImplementation(() => { throw new InputValidationError('Could not run the command'); }); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index bd4b50e9e..eef766867 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -10,12 +10,11 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const subtract = Subtract(pluginSettings); + const subtract = Subtract(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -52,6 +51,37 @@ describe('builtins/subtract: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when `mapping` is provided.', async () => { + const mapping = { + 'cpu/energy': 'energy-for-cpu', + }; + const subtract = Subtract(globalConfig, parametersMetadata, mapping); + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'energy-for-cpu': 4, + 'network/energy': 2, + 'memory/energy': 1, + 'energy/diff': 1, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = await subtract.execute([ + { + duration: 3600, + 'cpu/energy': 4, + 'network/energy': 2, + 'memory/energy': 1, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error on missing params in input.', async () => { expect.assertions(1); @@ -77,8 +107,7 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-diff', }; - pluginSettings['global-config'] = newConfig; - const subtract = Subtract(pluginSettings); + const subtract = Subtract(newConfig, parametersMetadata, {}); const data = [ { diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 10686471c..b377ca3b4 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -13,12 +13,11 @@ describe('builtins/sum: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const pluginSettings = { - 'global-config': globalConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const sum = Sum(pluginSettings); + const sum = Sum(globalConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -55,14 +54,14 @@ describe('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when mapping has valid data.', () => { + it('successfully executes when `mapping` has valid data.', () => { expect.assertions(1); - pluginSettings.mapping = { + const mapping = { 'cpu/energy': 'energy-from-cpu', 'network/energy': 'energy-from-network', }; - const sum = Sum(pluginSettings); + const sum = Sum(globalConfig, parametersMetadata, mapping); const expectedResult = [ { @@ -90,8 +89,7 @@ describe('builtins/sum: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - pluginSettings['global-config'] = config!; - const sum = Sum(pluginSettings); + const sum = Sum(config!, parametersMetadata, {}); expect.assertions(1); @@ -137,8 +135,7 @@ describe('builtins/sum: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-sum', }; - pluginSettings['global-config'] = newConfig; - const sum = Sum(pluginSettings); + const sum = Sum(newConfig, parametersMetadata, {}); const data = [ { diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index ddf2116d8..2bb342eda 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -76,12 +76,11 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - const pluginSettings = { - 'global-config': basicConfig, - 'parameter-metadata': {}, - mapping: {}, + const parametersMetadata = { + inputs: {}, + outputs: {}, }; - const timeSync = TimeSync(pluginSettings); + const timeSync = TimeSync(basicConfig, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -98,8 +97,11 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = invalidStartTimeConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync( + invalidStartTimeConfig, + parametersMetadata, + {} + ); expect.assertions(1); @@ -134,8 +136,11 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = invalidEndTimeConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync( + invalidEndTimeConfig, + parametersMetadata, + {} + ); expect.assertions(1); @@ -164,8 +169,11 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = invalidStartTimeConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync( + invalidStartTimeConfig, + parametersMetadata, + {} + ); expect.assertions(1); try { await timeModel.execute([ @@ -191,8 +199,11 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = invalidEndTimeConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync( + invalidEndTimeConfig, + parametersMetadata, + {} + ); expect.assertions(1); try { @@ -214,8 +225,7 @@ describe('builtins/time-sync:', () => { it('throws error on missing global config.', async () => { const config = undefined; - pluginSettings['global-config'] = config!; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(config!, parametersMetadata, {}); expect.assertions(1); @@ -246,8 +256,11 @@ describe('builtins/time-sync:', () => { interval: 0, 'allow-padding': true, }; - pluginSettings['global-config'] = invalidIntervalConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync( + invalidIntervalConfig, + parametersMetadata, + {} + ); expect.assertions(1); @@ -278,9 +291,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -309,9 +320,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -342,8 +351,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -382,8 +390,7 @@ describe('builtins/time-sync:', () => { 'cpu/utilization': 10, }, ]; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); expect.assertions(2); try { @@ -403,9 +410,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -436,9 +441,7 @@ describe('builtins/time-sync:', () => { interval: 1, 'allow-padding': false, }; - - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { @@ -476,8 +479,7 @@ describe('builtins/time-sync:', () => { interval: 1, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { @@ -550,8 +552,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { @@ -590,9 +591,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { @@ -626,6 +625,50 @@ describe('builtins/time-sync:', () => { expect(result).toStrictEqual(expectedResult); }); + it('returns a result when `mapping` has valid data.', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:09.000Z', + interval: 5, + 'allow-padding': true, + }; + const mapping = { + 'time-reserved': 'time-allocated', + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, mapping); + + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 3, + 'time-reserved': 5, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 3, + 'time-reserved': 5, + 'resources-total': 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + 'resources-total': 10, + 'time-allocated': 3.2, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + 'resources-total': 10, + 'time-allocated': 3.2, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); it('throws an error when `start-time` is wrong.', async () => { process.env.MOCK_INTERVAL = 'true'; @@ -635,8 +678,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -664,8 +706,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { @@ -703,8 +744,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': false, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -733,8 +773,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': false, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -763,8 +802,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': false, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); try { await timeModel.execute([ @@ -794,8 +832,7 @@ describe('builtins/time-sync:', () => { interval: 1, 'allow-padding': true, }; - pluginSettings['global-config'] = basicConfig; - const timeModel = TimeSync(pluginSettings); + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { timestamp: '2023-12-12T00:00:00.000Z', From fa379a51627bc97aead66d96d4ea4b0eadf1ca05 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 16:43:17 +0400 Subject: [PATCH 16/21] fix(util): remove `mapOutput` function and add `mapConfigIfNeeded` and `mapInputIfNeeded` functions --- src/common/util/helpers.ts | 50 +++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index 0778b9efa..f9cc69db4 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -66,17 +66,49 @@ export const parseManifestFromStdin = async () => { }; /** - * Maps the output of thr input if the `mapping` parameter is provided. + * Maps input data if the mapping has valid data. */ -export const mapOutput = (output: PluginParams, mapping: MappingParams) => { - if (!mapping) return output; +export const mapInputIfNeeded = ( + input: PluginParams, + mapping: MappingParams +) => { + const newInput = Object.assign({}, input); + + Object.entries(mapping || {}).forEach(([key, value]) => { + if (value in newInput) { + const mappedKey = input[value]; + newInput[key] = mappedKey; + delete newInput[value]; + } + }); + + return newInput; +}; + +/** + * Maps config data if the mapping hass valid data. + */ +export const mapConfigIfNeeded = (config: any, mapping: MappingParams) => { + if (!mapping) { + return config; + } + + if (typeof config !== 'object' || config === null) { + return config; + } + + const result: Record = Array.isArray(config) ? [] : {}; - return Object.entries(output).reduce((acc, [key, value]) => { - if (key in mapping) { - acc[mapping[key]] = value; + Object.entries(config).forEach(([key, value]) => { + const mappedKey = mapping[key] || key; + + if (typeof value === 'object' && value !== null) { + result[mappedKey] = mapConfigIfNeeded(value, mapping); } else { - acc[key] = value; + result[mappedKey] = + typeof value === 'string' && value in mapping ? mapping[value] : value; } - return acc; - }, {} as PluginParams); + }); + + return result; }; From b4e62c2f218cccd1d90301402c9cead532286f6c Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 17:15:34 +0400 Subject: [PATCH 17/21] fix(builtins): update plugins to map config or inputs if the mapping is provided --- src/if-run/builtins/coefficient/index.ts | 8 ++--- src/if-run/builtins/copy-param/index.ts | 8 ++--- src/if-run/builtins/csv-lookup/index.ts | 8 ++--- src/if-run/builtins/divide/index.ts | 8 ++--- src/if-run/builtins/exponent/index.ts | 8 ++--- src/if-run/builtins/interpolation/index.ts | 8 ++--- .../builtins/mock-observations/index.ts | 33 +++++++++---------- src/if-run/builtins/multiply/index.ts | 8 ++--- src/if-run/builtins/regex/index.ts | 8 ++--- src/if-run/builtins/sci-embodied/index.ts | 10 +++--- src/if-run/builtins/sci/index.ts | 15 ++++----- src/if-run/builtins/shell/index.ts | 8 ++--- src/if-run/builtins/subtract/index.ts | 8 ++--- src/if-run/builtins/sum/index.ts | 9 ++--- src/if-run/builtins/time-sync/index.ts | 23 +++++++++---- 15 files changed, 87 insertions(+), 83 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 935f4bdf4..a77966546 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -9,7 +9,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -31,6 +31,8 @@ export const Coefficient = ( * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const inputParameter = safeGlobalConfig['input-parameter']; const outputParameter = safeGlobalConfig['output-parameter']; @@ -39,12 +41,10 @@ export const Coefficient = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - const output = { + return { ...input, [outputParameter]: calculateProduct(input, inputParameter, coefficient), }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 895cab87b..903c5a1ee 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -9,9 +9,9 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; const {MISSING_GLOBAL_CONFIG} = STRINGS; const {GlobalConfigError} = ERRORS; @@ -77,6 +77,8 @@ export const Copy = ( }; const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const keepExisting = safeGlobalConfig['keep-existing'] === true; const from = safeGlobalConfig['from']; @@ -92,12 +94,10 @@ export const Copy = ( } } - const output = { + return { ...safeInput, // need to return or what you provide won't be outputted, don't be evil! [to]: outputValue, }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 4b3bd9c96..3a6aef002 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -13,9 +13,9 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; const { FILE_FETCH_FAILED, @@ -200,6 +200,8 @@ export const CSVLookup = ( * 4. Filters requested information from CSV. */ const execute = async (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const {filepath, query, output} = safeGlobalConfig; @@ -222,12 +224,10 @@ export const CSVLookup = ( throw new QueryDataNotFoundError(NO_QUERY_DATA); } - const result = { + return { ...input, ...filterOutput(relatedData, {output, query}), }; - - return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index ae456eba8..dfe1f282b 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -9,9 +9,9 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; @@ -31,6 +31,8 @@ export const Divide = ( * Calculate the division of each input parameter. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const {numerator, denominator, output} = safeGlobalConfig; @@ -41,12 +43,10 @@ export const Divide = ( validateSingleInput(input, {numerator, denominator}) ); - const result = { + return { ...input, [output]: calculateDivide(safeInput, index, {numerator, denominator}), }; - - return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index d6477d74c..4bead24f9 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -8,7 +8,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; export const Exponent = ( globalConfig: ExponentConfig, @@ -54,6 +54,8 @@ export const Exponent = ( * Calculate the input param raised by to the power of the given exponent. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const { 'input-parameter': inputParameter, exponent, @@ -63,12 +65,10 @@ export const Exponent = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - const output = { + return { ...input, [outputParameter]: calculateExponent(input, inputParameter, exponent), }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 8c3c9fb8c..f8ac27353 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -11,7 +11,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -38,18 +38,18 @@ export const Interpolation = ( * Executes the energy consumption calculation for an array of input parameters. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const validatedConfig = validateConfig(); return inputs.map((input, index) => { const safeInput = validateInput(input, index); const result = calculateResult(validatedConfig, safeInput); - const output = { + return { ...input, [validatedConfig['output-parameter']]: result, }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index b8382cda1..62c72c00c 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -10,7 +10,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; @@ -32,6 +32,8 @@ export const MockObservations = ( * Generate sets of mocked observations based on config. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const {duration, timeBuckets, components, generators} = generateParamsFromConfig(); const generatorToHistory = new Map(); @@ -42,24 +44,19 @@ export const MockObservations = ( const defaults = inputs && inputs[0]; - const outputs = Object.entries(components).reduce( - (acc: PluginParams[], item) => { - const component = item[1]; - timeBuckets.forEach(timeBucket => { - const observation = createObservation( - {duration, component, timeBucket, generators}, - generatorToHistory - ); - - acc.push(Object.assign({}, defaults, observation)); - }); - - return acc; - }, - [] - ); + return Object.entries(components).reduce((acc: PluginParams[], item) => { + const component = item[1]; + timeBuckets.forEach(timeBucket => { + const observation = createObservation( + {duration, component, timeBucket, generators}, + generatorToHistory + ); + + acc.push(Object.assign({}, defaults, observation)); + }); - return outputs.map(output => mapOutput(output, mapping)); + return acc; + }, []); }; /** diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 8ad5798d1..a409b40e6 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -8,7 +8,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; export const Multiply = ( globalConfig: MultiplyConfig, @@ -63,6 +63,8 @@ export const Multiply = ( * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const inputParameters = safeGlobalConfig['input-parameters']; const outputParameter = safeGlobalConfig['output-parameter']; @@ -70,12 +72,10 @@ export const Multiply = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - const output = { + return { ...input, [outputParameter]: calculateProduct(input, inputParameters), }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 943398902..4d4b2b0be 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -9,7 +9,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -59,6 +59,8 @@ export const Regex = ( * Executes the regex of the given parameter. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const {parameter: parameter, match, output} = safeGlobalConfig; @@ -69,12 +71,10 @@ export const Regex = ( validateSingleInput(input, parameter) ); - const result = { + return { ...input, [output]: extractMatching(safeInput, parameter, match), }; - - return mapOutput(result, mapping); }); }; diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 6a18fd961..b18410454 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -8,13 +8,14 @@ import { } from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; +import {mapInputIfNeeded} from '../../../common/util/helpers'; const {SCI_EMBODIED_ERROR} = STRINGS; export const SciEmbodied = ( + _config: undefined, parametersMetadata: PluginParametersMetadata, mapping: MappingParams ): ExecutePlugin => { @@ -79,14 +80,13 @@ export const SciEmbodied = ( */ const execute = (inputs: PluginParams[]) => inputs.map(input => { - const safeInput = validateInput(input); + const mappedInput = mapInputIfNeeded(input, mapping); + const safeInput = validateInput(mappedInput); - const output = { + return { ...input, 'carbon-embodied': calculateEmbodiedCarbon(safeInput), }; - - return mapOutput(output, mapping); }); /** diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 6f65e066b..bdd8d5715 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -10,7 +10,7 @@ import { } from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapInputIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -72,9 +72,10 @@ export const Sci = ( /** * Calculate the total emissions for a list of inputs. */ - const execute = (inputs: PluginParams[]): PluginParams[] => - inputs.map((input, index) => { - const safeInput = validateInput(input); + const execute = (inputs: PluginParams[]): PluginParams[] => { + return inputs.map((input, index) => { + const mappedInput = mapInputIfNeeded(input, mapping); + const safeInput = validateInput(mappedInput); const functionalUnit = input[globalConfig['functional-unit']]; if (functionalUnit === 0) { @@ -86,14 +87,12 @@ export const Sci = ( }; } - const output = { + return { ...input, sci: safeInput['carbon'] / functionalUnit, }; - - return mapOutput(output, mapping); }); - + }; /** * Checks for fields in input. */ diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 630e65592..1531b6eee 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -7,19 +7,16 @@ import { ExecutePlugin, PluginParams, ConfigParams, - MappingParams, PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; const {ProcessExecutionError} = ERRORS; export const Shell = ( globalConfig: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams + parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { kind: 'execute', @@ -35,9 +32,8 @@ export const Shell = ( const command = inputWithConfig.command; const inputAsString: string = dump(inputs, {indent: 2}); const results = runModelInShell(inputAsString, command); - const outputs = results?.outputs?.flat() as PluginParams[]; - return outputs.map(output => mapOutput(output, mapping)); + return results?.outputs?.flat() as PluginParams[]; }; /** diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 197088fcc..a5c2b8ab7 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -8,7 +8,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; export const Subtract = ( globalConfig: SubtractConfig, @@ -63,6 +63,8 @@ export const Subtract = ( * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, @@ -71,12 +73,10 @@ export const Subtract = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - const output = { + return { ...input, [outputParameter]: calculateDiff(input, inputParameters), }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 29af458cb..f2f0acb91 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -9,7 +9,7 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutput} from '../../../common/util/helpers'; +import {mapConfigIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -31,18 +31,19 @@ export const Sum = ( * Calculate the sum of each input-paramters. */ const execute = (inputs: PluginParams[]) => { + globalConfig = mapConfigIfNeeded(globalConfig, mapping); + const safeGlobalConfig = validateGlobalConfig(); const inputParameters = safeGlobalConfig['input-parameters']; const outputParameter = safeGlobalConfig['output-parameter']; return inputs.map(input => { validateSingleInput(input, inputParameters); - const output = { + + return { ...input, [outputParameter]: calculateSum(input, inputParameters), }; - - return mapOutput(output, mapping); }); }; diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index f10dceb3a..b923f2b44 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -18,6 +18,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {getAggregationMethod} from '../../lib/aggregate'; +import {mapInputIfNeeded} from '../../../common/util/helpers'; Settings.defaultZone = 'utc'; @@ -56,7 +57,7 @@ const { export const TimeSync = ( globalConfig: TimeNormalizerConfig, parametersMetadata: PluginParametersMetadata, - _mapping: MappingParams + mapping: MappingParams ): ExecutePlugin => { const metadata = { kind: 'execute', @@ -97,7 +98,12 @@ export const TimeSync = ( const flattenInputs = paddedInputs.reduce( (acc: PluginParams[], input, index) => { - const safeInput = Object.assign({}, input, validateInput(input, index)); + const mappedInput = mapInputIfNeeded(input, mapping); + const safeInput = Object.assign( + {}, + mappedInput, + validateInput(mappedInput, index) + ); const currentMoment = parseDate(safeInput.timestamp); /** Checks if not the first input, then check consistency with previous ones. */ @@ -128,14 +134,14 @@ export const TimeSync = ( ...getZeroishInputPerSecondBetweenRange( compareableTime, currentMoment, - safeInput + input ) ); } } /** Break down current observation. */ - for (let i = 0; i < safeInput.duration; i++) { - const normalizedInput = breakDownInput(safeInput, i); + for (let i = 0; i < input.duration; i++) { + const normalizedInput = breakDownInput(input, i); acc.push(normalizedInput); } @@ -287,7 +293,12 @@ export const TimeSync = ( return acc; } - if (metric === 'time-reserved') { + if ( + metric === 'time-reserved' || + (mapping && + mapping['time-reserved'] && + metric === mapping['time-reserved']) + ) { acc[metric] = acc['duration']; return acc; From fd73d1e1ea01dd8b300787bf78a8f8c80ca78881 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 17:17:17 +0400 Subject: [PATCH 18/21] fix(manifests): remove dublicated interpolation manifest --- .../builtins/interpolation/interpolation.yml | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 manifests/examples/builtins/interpolation/interpolation.yml diff --git a/manifests/examples/builtins/interpolation/interpolation.yml b/manifests/examples/builtins/interpolation/interpolation.yml deleted file mode 100644 index 394946467..000000000 --- a/manifests/examples/builtins/interpolation/interpolation.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: interpolation-demo -description: simple demo of interpolation plugin -tags: -initialize: - plugins: - interpolation: - method: Interpolation - path: "builtin" - global-config: - method: linear - x: [0, 10, 50, 100] - y: [0.12, 0.32, 0.75, 1.02] - input-parameter: "cpu/utilization" - output-parameter: "result" -tree: - children: - child: - pipeline: - compute: - - interpolation - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 - cpu/utilization: 45 From 783e966744bd7b640c416fc0a08e414310b67c13 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 17:23:13 +0400 Subject: [PATCH 19/21] docs(builtins): update docs --- src/if-run/builtins/coefficient/README.md | 7 ++----- src/if-run/builtins/copy-param/README.md | 6 ++---- src/if-run/builtins/csv-lookup/README.md | 8 ++++---- src/if-run/builtins/divide/README.md | 6 +++--- src/if-run/builtins/exponent/README.md | 6 ++---- src/if-run/builtins/interpolation/README.md | 7 ++----- src/if-run/builtins/mock-observations/README.md | 7 ++----- src/if-run/builtins/multiply/README.md | 7 ++----- src/if-run/builtins/regex/README.md | 7 ++----- src/if-run/builtins/sci-embodied/README.md | 9 ++++----- src/if-run/builtins/sci/README.md | 4 ++-- src/if-run/builtins/shell/README.md | 17 +---------------- src/if-run/builtins/subtract/README.md | 7 ++----- src/if-run/builtins/sum/README.md | 7 ++----- 14 files changed, 32 insertions(+), 73 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 91b7dd0e7..9196691f8 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -34,14 +34,14 @@ of the parameters of the inputs and outputs ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml coefficient: method: Coefficient path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -109,9 +109,6 @@ initialize: description: 'a product of cabon property and the coefficient' unit: 'gCO2e' aggregation-method: sum - mapping: - carbon-product: calculated-carbon - tree: children: child: diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index c8cbbbfef..78e8ca116 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -56,14 +56,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml copy-param: path: builtin method: Copy mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -119,8 +119,6 @@ initialize: keep-existing: true from: original to: copy - mapping: - original: from tree: children: child-1: diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 813acb085..f8f4fa440 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -70,14 +70,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml cloud-metadata: method: CSVLookup path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -113,7 +113,7 @@ const globalConfig = { }; const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const csvLookup = CSVLookup(globalConfig); +const csvLookup = CSVLookup(globalConfig, parametersMetadata, mapping); const input = [ { @@ -157,7 +157,7 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 cloud/provider: Google Cloud - cloud/region: europe-north1 + cloud/area: europe-north1 ``` You can run this example by saving it as `./examples/manifests/csv-lookup.yml` and executing the following command from the project root: diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index d9aa97549..f4045f71b 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -30,14 +30,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml divide: method: Divide path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -113,7 +113,7 @@ tree: inputs: - timestamp: 2023-08-06T00:00 duration: 3600 - vcpus-allocated: 24 + vcpus-distributed: 24 ``` You can run this example by saving it as `./examples/manifests/divide.yml` and executing the following command from the project root: diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index faae04100..716913a41 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -33,14 +33,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml exponent: method: Exponent path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -100,8 +100,6 @@ initialize: input-parameter: 'cpu/energy' exponent: 2 output-parameter: 'energy' - mapping: - energy/base: energy/main tree: children: child: diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index b1b13cf0e..29f8d92b4 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -42,14 +42,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml interpolation: method: Interpolation path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ## Input Parameters @@ -144,9 +144,6 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: 'cpu/utilization' output-parameter: 'cpu/energy' - mapping: - cpu/utilization: cpu/util - interpolation-result: result tree: children: child: diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 917001510..c37542a0e 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -34,7 +34,7 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml mock-observations: @@ -42,7 +42,7 @@ mock-observations: method: MockObservations path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Authentication @@ -112,9 +112,6 @@ initialize: memory/utilization: min: 1 max: 99 - mapping: - cpu/utilization: cpu/util - tree: children: child: diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index dd60b4357..5431fd058 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -32,14 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml multiply: method: Multiply path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -97,9 +97,6 @@ initialize: global-config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy-product' - mapping: - cpu/energy: energy-from-cpu - network/energy: energy-from-network tree: children: child: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 171ec8bc0..0d0c4e66a 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -33,14 +33,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml regex: method: Regex path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -92,9 +92,6 @@ initialize: parameter: physical-processor match: ^[^,]+ output: cpu/name - mapping: - physical-processor: processor - tree: children: child: diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 9908e0683..dd75dea6c 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -27,14 +27,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml sci-embodied: method: SciEmbodied path: 'builtins' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -87,7 +87,7 @@ import {SciEmbodied} from 'builtins'; const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const sciEmbodied = SciEmbodied(parametersMetadata, mapping); +const sciEmbodied = SciEmbodied(undefined, parametersMetadata, mapping); const results = await sciEmbodied.execute([ { 'device/emissions-embodied': 200, // in gCO2e for total resource units @@ -114,7 +114,6 @@ initialize: path: 'builtins' mapping: device/emissions-embodied: device/carbon-footprint - carbon-embodied: carbon-footprint tree: children: child: @@ -122,7 +121,7 @@ tree: compute: - sci-embodied # duration & config -> embodied defaults: - device/emissions-embodied: 1533.120 # gCO2eq + device/carbon-footprint: 1533.120 # gCO2eq device/expected-lifespan: 3 # 3 years in seconds resources-reserved: 1 resources-total: 8 diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 61afb6e12..29b03f0d6 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -26,14 +26,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml sci: method: Sci path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index fada69242..28bd843a6 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -44,18 +44,6 @@ The parameters included in the `inputs` field in the `manifest` depend entirely - `timestamp`: A timestamp for the specific input - `duration`: The length of time these specific inputs cover -### Mapping - -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: - -```yaml -sampler: - method: Shell - path: 'builtin' - mapping: - 'old-name': 'new-name' -``` - ## Returns The specific return types depend on the plugin being invoked. Typically, we would expect some kind of energy or carbon metric as an output, but it is also possible that plugins target different parts of the pipeline, such as data importers, adaptor plugins etc. Therefore, we do not specify return data for external plugins. @@ -69,8 +57,7 @@ const globalConfig = { command: '/usr/local/bin/sampler', }; const parametersMetadata = {inputs: {}, outputs: {}}; -const mapping = {}; -const output = Shell(globalConfig, parametersMetadata, mapping); +const output = Shell(globalConfig, parametersMetadata); const result = await output.execute([ { timestamp: '2021-01-01T00:00:00Z', @@ -104,8 +91,6 @@ initialize: path: 'builtin' global-config: command: python3 /usr/local/bin/sampler - mapping: - cpu/energy: energy-for-cpu tree: children: child: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 2f7cf0cf4..44505662e 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -32,14 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml subtract: method: Subtract path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -96,9 +96,6 @@ initialize: global-config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy/diff' - mapping: - cpu/energy: energy-for-cpu - tree: children: child: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index b3a653c01..9e5f4251e 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -32,14 +32,14 @@ The `parameter-metadata` section contains information about `description`, `unit ### Mapping -The `mapping` block is an optional block. It is added in the plugin section and allows renaming the parameters of the input and output. The parameter with the new name will persist in the outputs. The structure of the `mapping` block is: +The `mapping` block is an optional block. It is added in the plugin section and allows the plugin to receive a parameter from the input with a different name than the one the plugin uses for data manipulation. The parameter with the mapped name will not appear in the outputs. The structure of the `mapping` block is: ```yaml sum: method: Sum path: 'builtin' mapping: - 'old-name': 'new-name' + 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` ### Inputs @@ -115,9 +115,6 @@ initialize: description: sum of energy components unit: kWh aggregation-method: sum - mapping: - cpu/energy: energy-from-cpu - network/energy: energy-from-network tree: children: child: From e3bf7c6027d647436fb218ffc04d541217894dbc Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 17:24:46 +0400 Subject: [PATCH 20/21] test(util): add unit tests for `mapConfigIfNeeded` and `mapInputIfNeeded` helpers function --- src/__tests__/common/util/helpers.test.ts | 120 +++++++++++++++------- 1 file changed, 83 insertions(+), 37 deletions(-) diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts index 490bfcca7..b73e638ef 100644 --- a/src/__tests__/common/util/helpers.test.ts +++ b/src/__tests__/common/util/helpers.test.ts @@ -2,7 +2,11 @@ jest.mock('node:readline/promises', () => require('../../../__mocks__/readline') ); -import {parseManifestFromStdin, mapOutput} from '../../../common/util/helpers'; +import { + parseManifestFromStdin, + mapInputIfNeeded, + mapConfigIfNeeded, +} from '../../../common/util/helpers'; describe('common/util/helpers: ', () => { describe('parseManifestFromStdin(): ', () => { @@ -42,56 +46,98 @@ describe('common/util/helpers: ', () => { }); }); - describe('mapOutput(): ', () => { - const output = { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'cpu/energy': 1, - 'network/energy': 1, - 'memory/energy': 1, - }; - it('returns provided `output` if `mapping` is not valid.', () => { - const mapping = undefined; - const mappedOutput = mapOutput(output, mapping!); + describe('mapInputIfNeeded(): ', () => { + it('returns a new object with no changes when mapping is empty.', () => { + const input = { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/carbon-footprint': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + }; + const mapping = {}; - expect.assertions(1); - expect(mappedOutput).toEqual(output); + const result = mapInputIfNeeded(input, mapping); + + expect(result).toEqual(input); }); - it('returns mapped output if `mapping` has data.', () => { - const mapping = { - 'cpu/energy': 'energy-from-cpu', - 'network/energy': 'energy-from-network', + it('returns a new object with keys remapped according to the mapping.', () => { + const input = { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/carbon-footprint': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, }; + const mapping = {'device/emissions-embodied': 'device/carbon-footprint'}; + const expectedOutput = { timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'energy-from-cpu': 1, - 'energy-from-network': 1, - 'memory/energy': 1, + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, }; - const mappedOutput = mapOutput(output, mapping); - expect.assertions(1); - expect(mappedOutput).toEqual(expectedOutput); + const result = mapInputIfNeeded(input, mapping); + + expect(result).toEqual(expectedOutput); + expect(result).not.toHaveProperty('device/carbon-footprint'); }); + }); - it('returns the correct mapped output if some properties are mismatched.', () => { + describe('mapConfigIfNeeded', () => { + it('returns the config as is if no mapping is provided.', () => { + const config = { + filepath: './file.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + + const nullMapping = null; + expect(mapConfigIfNeeded(config, nullMapping!)).toEqual(config); + + const undefinedMapping = undefined; + expect(mapConfigIfNeeded(config, undefinedMapping!)).toEqual(config); + }); + + it('recursively maps config keys and values according to the mapping.', () => { + const config = { + filepath: './file.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; const mapping = { - 'mock-cpu/energy': 'energy-from-cpu', - 'network/energy': 'energy-from-network', + 'cpu/utilized': 'cpu/util', }; - const expectedOutput = { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'cpu/energy': 1, - 'energy-from-network': 1, - 'memory/energy': 1, + + const expected = { + filepath: './file.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/util', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], }; - const mappedOutput = mapOutput(output, mapping); + expect(mapConfigIfNeeded(config, mapping)).toEqual(expected); + }); - expect.assertions(1); - expect(mappedOutput).toEqual(expectedOutput); + it('returns an empty object or array when config is an empty object or array.', () => { + expect(mapConfigIfNeeded({}, {})).toEqual({}); + expect(mapConfigIfNeeded([], {})).toEqual([]); }); }); }); From 8dc3c76ea21fe4d298cb5f202607608284cc14f5 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 17:29:27 +0400 Subject: [PATCH 21/21] test(builtins): update test accorgind to changes --- .../if-run/builtins/coefficient.test.ts | 3 +- .../if-run/builtins/copy-param.test.ts | 2 +- .../if-run/builtins/csv-lookup.test.ts | 5 +- src/__tests__/if-run/builtins/divide.test.ts | 2 +- .../if-run/builtins/exponent.test.ts | 7 ++- .../if-run/builtins/interpolation.test.ts | 14 +++++ .../if-run/builtins/mock-observations.test.ts | 2 +- .../if-run/builtins/multiply.test.ts | 10 +++- src/__tests__/if-run/builtins/regex.test.ts | 2 +- .../if-run/builtins/sci-embodied.test.ts | 13 ++-- src/__tests__/if-run/builtins/sci.test.ts | 4 +- src/__tests__/if-run/builtins/shell.test.ts | 59 +------------------ .../if-run/builtins/subtract.test.ts | 6 +- src/__tests__/if-run/builtins/sum.test.ts | 9 ++- .../if-run/builtins/time-sync.test.ts | 10 +++- 15 files changed, 65 insertions(+), 83 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 9a0db46d1..40bc2d2cf 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -57,6 +57,7 @@ describe('builtins/coefficient: ', () => { const mapping = { carbon: 'carbon-for-production', }; + const coefficient = Coefficient( globalConfig, parametersMetadata, @@ -76,7 +77,7 @@ describe('builtins/coefficient: ', () => { const result = coefficient.execute([ { duration: 3600, - carbon: 3, + 'carbon-for-production': 3, timestamp: '2021-01-01T00:00:00Z', }, ]); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 9f64539c2..4b893b60b 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -72,7 +72,7 @@ describe('builtins/copy: ', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - original: 'hello', + from: 'hello', }, ]); diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index 52198de47..546771e71 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -133,7 +133,6 @@ describe('builtins/CSVLookup: ', () => { }; const parameterMetadata = {inputs: {}, outputs: {}}; const mapping = { - tdp: 'cpu/tdp', 'cpu/utilized': 'cpu/util', }; const csvLookup = CSVLookup(globalConfig, parameterMetadata, mapping); @@ -142,7 +141,7 @@ describe('builtins/CSVLookup: ', () => { { timestamp: '2024-03-01', 'cpu/available': 16, - 'cpu/utilized': 16, + 'cpu/util': 16, 'cpu/manufacturer': 'AWS', }, ]); @@ -152,7 +151,7 @@ describe('builtins/CSVLookup: ', () => { 'cpu/available': 16, 'cpu/util': 16, 'cpu/manufacturer': 'AWS', - 'cpu/tdp': 150, + tdp: 150, }, ]; diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index 1d616f7ab..895259dc2 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -71,7 +71,7 @@ describe('builtins/divide: ', () => { const result = await divide.execute([ { duration: 3600, - 'vcpus-allocated': 24, + 'vcpus-distributed': 24, timestamp: '2021-01-01T00:00:00Z', }, ]); diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index 3eef64c1e..9af6c0e4e 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -53,6 +53,11 @@ describe('builtins/exponent: ', () => { const mapping = { 'energy/base': 'energy/main', }; + const globalConfig = { + 'input-parameter': 'energy/base', + exponent: 3, + 'output-parameter': 'energy', + }; const exponent = Exponent(globalConfig, parametersMetadata, mapping); const expectedResult = [ { @@ -66,7 +71,7 @@ describe('builtins/exponent: ', () => { const result = await exponent.execute([ { duration: 3600, - 'energy/base': 2, + 'energy/main': 2, timestamp: '2021-01-01T00:00:00Z', }, ]); diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index f5f1b7f27..f48ef8dd3 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -61,6 +61,20 @@ describe('builtins/interpolation: ', () => { 'cpu/utilization': 'cpu/util', 'interpolation-result': 'result', }; + const globalConfig = { + method: Method.LINEAR, + x: [0, 10, 50, 100], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': 'cpu/utilization', + 'output-parameter': 'interpolation-result', + }; + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/util': 45, + }, + ]; const plugin = Interpolation(globalConfig, parametersMetadata, mapping); const outputs = [ { diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index 3c43040e7..e548a7d46 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -111,7 +111,7 @@ describe('builtins/mock-observations: ', () => { 'common-key': 'common-val', }, randint: { - 'cpu/utilization': {min: 10, max: 11}, + 'cpu/util': {min: 10, max: 11}, }, }, }; diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index ec6571863..8e2eab6af 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -58,6 +58,10 @@ describe('builtins/multiply: ', () => { 'network/energy': 'energy-from-network', 'memory/energy': 'energy-from-memory', }; + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; const multiply = Multiply(globalConfig, parametersMetadata, mapping); const expectedResult = [ @@ -75,9 +79,9 @@ describe('builtins/multiply: ', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - 'cpu/energy': 2, - 'network/energy': 2, - 'memory/energy': 2, + 'energy-from-cpu': 2, + 'energy-from-network': 2, + 'energy-from-memory': 2, }, ]); diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index 1fc5070a8..a139a5635 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -104,7 +104,7 @@ describe('builtins/regex: ', () => { { timestamp: '2023-08-06T00:00', duration: 3600, - 'cloud/instance-type': 'Standard_DS1_v2', + 'instance-type': 'Standard_DS1_v2', }, ]); diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 47cc028d5..bf3ebfb1e 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -13,7 +13,7 @@ describe('builtins/sci-embodied:', () => { inputs: {}, outputs: {}, }; - const sciEmbodied = SciEmbodied(parametersMetadata, {}); + const sciEmbodied = SciEmbodied(undefined, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -72,14 +72,13 @@ describe('builtins/sci-embodied:', () => { it('executes when `mapping` has valid data.', async () => { const mapping = { 'device/emissions-embodied': 'device/carbon-footprint', - 'carbon-embodied': 'carbon-footprint', }; - const sciEmbodied = SciEmbodied(parametersMetadata, mapping); + const sciEmbodied = SciEmbodied(undefined, parametersMetadata, mapping); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, + 'device/carbon-footprint': 200, 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, 'resources-reserved': 1, 'resources-total': 1, @@ -87,7 +86,7 @@ describe('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 60 * 60 * 24 * 30 * 2, - 'device/emissions-embodied': 200, + 'device/carbon-footprint': 200, 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, 'resources-reserved': 1, 'resources-total': 1, @@ -106,7 +105,7 @@ describe('builtins/sci-embodied:', () => { 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, 'resources-reserved': 1, 'resources-total': 1, - 'carbon-footprint': 4.10958904109589, + 'carbon-embodied': 4.10958904109589, }, { timestamp: '2021-01-01T00:00:00Z', @@ -115,7 +114,7 @@ describe('builtins/sci-embodied:', () => { 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, 'resources-reserved': 1, 'resources-total': 1, - 'carbon-footprint': 4.10958904109589 * 2, + 'carbon-embodied': 4.10958904109589 * 2, }, ]); }); diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index 37826ecc8..143d34757 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -48,7 +48,7 @@ describe('builtins/sci:', () => { it('successfully executes when `mapping` has valid data.', async () => { const mapping = { - 'carbon-embodied': 'carbon-footprint', + 'carbon-footprint': 'carbon-embodied', }; const sci = Sci(config, parametersMetadata, mapping); const inputs = [ @@ -69,7 +69,7 @@ describe('builtins/sci:', () => { { timestamp: '2021-01-01T00:00:00Z', 'carbon-operational': 0.02, - 'carbon-footprint': 5, + 'carbon-embodied': 5, carbon: 5.02, users: 100, duration: 1, diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts index 4febe9f93..125595ced 100644 --- a/src/__tests__/if-run/builtins/shell.test.ts +++ b/src/__tests__/if-run/builtins/shell.test.ts @@ -16,7 +16,7 @@ describe('builtins/shell', () => { inputs: {}, outputs: {}, }; - const shell = Shell(globalConfig, parametersMetadata, {}); + const shell = Shell(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -56,61 +56,8 @@ describe('builtins/shell', () => { expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); }); - it('executes when `mapping` is provided.', async () => { - const mapping = { - 'cpu/energy': 'energy-for-cpu', - }; - const shell = Shell(globalConfig, parametersMetadata, mapping); - const mockSpawnSync = spawnSync as jest.MockedFunction< - typeof spawnSync - >; - mockSpawnSync.mockReturnValueOnce({stdout: 'mocked stdout'} as any); - - const mockLoadAll = loadAll as jest.MockedFunction; - mockLoadAll.mockReturnValueOnce([ - { - timestamp: '2023-11-02T10:35:31.820Z', - duration: 3600, - 'energy-for-cpu': 0.002, - 'memory/energy': 0.000005, - energy: 1, - }, - ] as any); - - const inputs = [ - { - timestamp: '2023-11-02T10:35:31.820Z', - duration: 3600, - 'cpu/energy': 0.002, - 'memory/energy': 0.000005, - }, - ]; - - expect.assertions(3); - - const result = await shell.execute(inputs); - expect(result).toEqual([ - { - timestamp: '2023-11-02T10:35:31.820Z', - duration: 3600, - 'energy-for-cpu': 0.002, - 'memory/energy': 0.000005, - energy: 1, - }, - ]); - - expect(mockSpawnSync).toHaveBeenCalledWith( - 'python3', - ['/path/to/script.py'], - { - encoding: 'utf8', - } - ); - expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); - }); - it('throws an error if validation fails.', async () => { - const shell = Shell({}, parametersMetadata, {}); + const shell = Shell({}, parametersMetadata); const invalidInputs = [ {duration: 3600, timestamp: '2022-01-01T00:00:00Z', command: 123}, ]; @@ -129,7 +76,7 @@ describe('builtins/shell', () => { }); it('throws an error when shell could not run command.', async () => { - const shell = Shell(globalConfig, parametersMetadata, {}); + const shell = Shell(globalConfig, parametersMetadata); (spawnSync as jest.Mock).mockImplementation(() => { throw new InputValidationError('Could not run the command'); }); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index eef766867..751d1a820 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -55,6 +55,10 @@ describe('builtins/subtract: ', () => { const mapping = { 'cpu/energy': 'energy-for-cpu', }; + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy/diff', + }; const subtract = Subtract(globalConfig, parametersMetadata, mapping); expect.assertions(1); @@ -72,7 +76,7 @@ describe('builtins/subtract: ', () => { const result = await subtract.execute([ { duration: 3600, - 'cpu/energy': 4, + 'energy-for-cpu': 4, 'network/energy': 2, 'memory/energy': 1, timestamp: '2021-01-01T00:00:00Z', diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index b377ca3b4..1baf2acac 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -56,10 +56,15 @@ describe('builtins/sum: ', () => { it('successfully executes when `mapping` has valid data.', () => { expect.assertions(1); + const mapping = { 'cpu/energy': 'energy-from-cpu', 'network/energy': 'energy-from-network', }; + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; const sum = Sum(globalConfig, parametersMetadata, mapping); @@ -78,8 +83,8 @@ describe('builtins/sum: ', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - 'cpu/energy': 1, - 'network/energy': 1, + 'energy-from-cpu': 1, + 'energy-from-network': 1, 'memory/energy': 1, }, ]); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index b21ef03c8..9a3507599 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -632,7 +632,7 @@ describe('builtins/time-sync:', () => { expect(result).toStrictEqual(expectedResult); }); - it.skip('returns a result when `mapping` has valid data.', async () => { + it('returns a result when `mapping` has valid data.', async () => { const basicConfig = { 'start-time': '2023-12-12T00:00:00.000Z', 'end-time': '2023-12-12T00:00:09.000Z', @@ -642,19 +642,23 @@ describe('builtins/time-sync:', () => { const mapping = { 'time-reserved': 'time-allocated', }; + + storeAggregationMetrics({'time-allocated': 'avg'}); + storeAggregationMetrics({'resources-total': 'sum'}); + const timeModel = TimeSync(basicConfig, parametersMetadata, mapping); const result = await timeModel.execute([ { timestamp: '2023-12-12T00:00:00.000Z', duration: 3, - 'time-reserved': 5, + 'time-allocated': 5, 'resources-total': 10, }, { timestamp: '2023-12-12T00:00:05.000Z', duration: 3, - 'time-reserved': 5, + 'time-allocated': 5, 'resources-total': 10, }, ]);