From 3498c1913c0662878b1c3dbee6a99a1f47763976 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:46:25 +0100 Subject: [PATCH 001/863] feat(lib): add callout to mailing list --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 707969488..c9b86602a 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,10 @@ Watch this video to learn how to create and run a `manifest`. [![Watch the walk-through video](https://i3.ytimg.com/vi/R-6eDM8AsvY/maxresdefault.jpg)](https://youtu.be/GW37Qd4AQbU) +## Join our mailing list + +We have a public mailing list at if-community@greensoftware.foundation. We send out weekly updates that explains what we've shipped, what we're working on and how you can get involved each week! + ## Contributing From c6770020cc00406083ae0eae26ddecc7891bd45d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:49:39 +0100 Subject: [PATCH 002/863] fix(lib): update mailer list --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9b86602a..68729d1e8 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Watch this video to learn how to create and run a `manifest`. ## Join our mailing list -We have a public mailing list at if-community@greensoftware.foundation. We send out weekly updates that explains what we've shipped, what we're working on and how you can get involved each week! +We have a public mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that explain what we've shipped, what we're working on and how you can get involved each week! ## Contributing From ee7123b85be11176f81d995a87f33c2f0da8e3a3 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:50:30 +0100 Subject: [PATCH 003/863] feat(lib): add mailing list to contributing.md --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ac010c51..3974becb0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,11 +20,14 @@ The following document is a rule set of guidelines for contributing. - [Naming conventions](#naming-conventions) - [Documentation](#documentation) - [Writing tests](#writing-tests) + - [How to report issues (bugs)](#how-to-report-issues-bugs) ## What and when to contribute You can contribute anything to the IF, but we are likely to close out unsolicited PRs without merging them. Our issue board is completely open and we have tags (`help-wanted`, `good-first-issue`) to help contributors to choose tasks to work on. We recommend speaking to the core team on Github before starting working on an issue. You can do this by raising an issue or commenting on an existing issue. This helps us to direct your energy in directions that are aligned with our roadmap, prevent multiple people working on the same task, and better manage our board. This all makes it much more likely that your work will get merged. +You can also contribute by participating in discussions on our mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that includes what we've shipped, what we're working on and how you can get involved each week. + ## Reporting bugs We appreciate bug reports! If you experience an issue with IF or one of our plugins, you can report it using our bug reporting template. To do this: From 316f20f5399447b06c4976744960a6316b41ad08 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:32:10 +0100 Subject: [PATCH 004/863] feat(lib): add example manifest for tdp finder --- manifests/examples/tdp-finder.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 manifests/examples/tdp-finder.yml diff --git a/manifests/examples/tdp-finder.yml b/manifests/examples/tdp-finder.yml new file mode 100644 index 000000000..f0d8751c6 --- /dev/null +++ b/manifests/examples/tdp-finder.yml @@ -0,0 +1,23 @@ +name: csv-demo +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: instance-id + output: "tdp" +tree: + children: + child: + pipeline: + - cloud-instance-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + instance-id: "AMD A10-9700" From d74fa639919c1dc8be88dcb13eed5bd5185d1fbb Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:45:54 +0100 Subject: [PATCH 005/863] fix(lib): rename instance to tdp-finder --- manifests/examples/tdp-finder.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/examples/tdp-finder.yml b/manifests/examples/tdp-finder.yml index f0d8751c6..5ce1b5903 100644 --- a/manifests/examples/tdp-finder.yml +++ b/manifests/examples/tdp-finder.yml @@ -3,7 +3,7 @@ description: tags: initialize: plugins: - cloud-instance-metadata: + tdp-finder: method: CSVLookup path: "builtin" global-config: @@ -15,7 +15,7 @@ tree: children: child: pipeline: - - cloud-instance-metadata + - tdp-finder inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 36b7e1e4db411e1b0f233c842c576804a4f7af5c Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:02:48 +0100 Subject: [PATCH 006/863] feat(lib): add example manifest for region-metadata --- manifests/examples/region-metadata.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 manifests/examples/region-metadata.yml diff --git a/manifests/examples/region-metadata.yml b/manifests/examples/region-metadata.yml new file mode 100644 index 000000000..d43b5bc65 --- /dev/null +++ b/manifests/examples/region-metadata.yml @@ -0,0 +1,26 @@ +name: csv-demo +description: +tags: +initialize: + plugins: + cloud-region-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud-provider + cloud-region: cloud-region + output: "*" +tree: + children: + child: + pipeline: + - cloud-region-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + instance-id: AMD A10-9700 + cloud-provider: "Google Cloud" + cloud-region: "asia-east1" From cb63b7093bc4b0265a2a51d1cf9578c15091da87 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:36:03 +0100 Subject: [PATCH 007/863] feat(lib): add example manifest for instance metadata --- manifests/examples/instance-metadata.yml | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 manifests/examples/instance-metadata.yml diff --git a/manifests/examples/instance-metadata.yml b/manifests/examples/instance-metadata.yml new file mode 100644 index 000000000..dc4da68f1 --- /dev/null +++ b/manifests/examples/instance-metadata.yml @@ -0,0 +1,33 @@ +name: csv-demo +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: "cloud/instance-type" + output: "*" + extract-processor-name: + method: Regex + path: "builtin" + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 From 1adbf1d469747b113f8e43776dabd2029118b2e4 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:47:39 +0400 Subject: [PATCH 008/863] feat(util): add function to check if the file exists in the given path --- src/util/helpers.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b15863cef..99291f81d 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,3 +1,5 @@ +import * as fs from 'fs/promises'; + import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; @@ -182,3 +184,15 @@ export const parseManifestFromStdin = async () => { return match![1]; }; + +/** + * Checks if file exists with the given `filePath`. + */ +export const isFileExists = async (filePath: string) => { + try { + await fs.stat(filePath); + return true; + } catch (error) { + return false; + } +}; From 152cfe3f2c87a88d024af21c4e89cfa070c6c248 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:49:18 +0400 Subject: [PATCH 009/863] feat(config): add 'MANIFEST_NOT_FOUND' string --- src/config/strings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index 04551b9b9..d0693c120 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -56,4 +56,5 @@ Note that for the '--output' option you also need to define the output type in y TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', + MANIFEST_NOT_FOUND: 'Manifest file not found.', }; From 5fd1e79d4fccffa0952992bec6c20139faf33758 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:51:03 +0400 Subject: [PATCH 010/863] feat(types): adds IFEnvArgs interface --- src/types/process-args.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 7dfdcb929..e0d9bcc0f 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -10,6 +10,11 @@ export interface IFDiffArgs { target: string; } +export interface IFEnvArgs { + manifest?: string; + install?: boolean; +} + export interface Options { outputPath?: string; stdout?: boolean; From 33ef812286201cebe9aa99f80adeaed13f443ede Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:53:20 +0400 Subject: [PATCH 011/863] feat(util): add if-env releated functions --- src/util/args.ts | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 56466fd48..753145022 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -2,21 +2,28 @@ import * as path from 'path'; import {parse} from 'ts-command-line-args'; import {checkIfFileIsYaml} from './yaml'; +import {isFileExists} from './helpers'; import {ERRORS} from './errors'; import {logger} from './logger'; import {CONFIG, STRINGS} from '../config'; -import {IFDiffArgs, IEArgs, ProcessArgsOutputs} from '../types/process-args'; +import { + IFDiffArgs, + IEArgs, + ProcessArgsOutputs, + IFEnvArgs, +} from '../types/process-args'; import {LoadDiffParams} from '../types/util/args'; const {CliInputError} = ERRORS; -const {IE, IF_DIFF} = CONFIG; +const {IE, IF_DIFF, IF_ENV} = CONFIG; const { FILE_IS_NOT_YAML, MANIFEST_IS_MISSING, + MANIFEST_NOT_FOUND, NO_OUTPUT, SOURCE_IS_NOT_YAML, TARGET_IS_NOT_YAML, @@ -134,3 +141,45 @@ export const parseIfDiffArgs = () => { throw new CliInputError(INVALID_TARGET); }; + +/** -- IF Env -- */ + +/** + * Parses `if-env` process arguments. + */ +const validateAndParseIfEnvArgs = () => { + try { + return parse(IF_ENV.ARGS, IF_ENV.HELP); + } catch (error) { + if (error instanceof Error) { + throw new CliInputError(error.message); + } + + throw error; + } +}; + +/** + * Checks if the `manifest` command is provided and it is valid manifest file. + */ +export const parseIfEnvArgs = async () => { + const {manifest, install} = validateAndParseIfEnvArgs(); + + if (manifest) { + const isManifestFileExists = await isFileExists(manifest); + + if (!isManifestFileExists) { + throw new CliInputError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + const response = prependFullFilePath(manifest); + + return {manifest: response, install}; + } + + throw new CliInputError(FILE_IS_NOT_YAML); + } + + return; +}; From 69867927018ca8518ee95fa5d6acfdc48d061a0c Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:55:49 +0400 Subject: [PATCH 012/863] test(util): add args test --- src/__tests__/unit/util/args.test.ts | 106 ++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index d40d36cae..ac91f8a3a 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -1,5 +1,14 @@ const processRunningPath = process.cwd(); +jest.mock('../../../util/helpers', () => ({ + isFileExists: () => { + if (process.env.fileExists === 'true') { + return true; + } + return false; + }, +})); + jest.mock('ts-command-line-args', () => ({ __esModule: true, parse: () => { @@ -60,6 +69,22 @@ jest.mock('ts-command-line-args', () => ({ throw new Error('mock-error'); case 'diff-throw': throw 'mock-error'; + /** If-env mocks */ + // case 'env-manifest-is-missing': + // return; + case 'manifest-install-provided': + return { + install: true, + manifest: 'mock-manifest.yaml', + }; + case 'manifest-is-not-yaml': + return {manifest: 'manifest'}; + case 'manifest-path-invalid': + throw new Error(MANIFEST_NOT_FOUND); + case 'env-throw-error': + throw new Error('mock-error'); + case 'env-throw': + throw 'mock-error'; default: return { manifest: 'mock-manifest.yaml', @@ -71,7 +96,11 @@ jest.mock('ts-command-line-args', () => ({ import path = require('path'); -import {parseIEProcessArgs, parseIfDiffArgs} from '../../../util/args'; +import { + parseIEProcessArgs, + parseIfDiffArgs, + parseIfEnvArgs, +} from '../../../util/args'; import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; @@ -84,6 +113,7 @@ const { TARGET_IS_NOT_YAML, INVALID_TARGET, SOURCE_IS_NOT_YAML, + MANIFEST_NOT_FOUND, } = STRINGS; describe('util/args: ', () => { @@ -299,5 +329,79 @@ describe('util/args: ', () => { }); }); + describe('parseIfEnvArgs(): ', () => { + it('executes if `manifest` is missing.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-missing'; + const response = await parseIfEnvArgs(); + + expect.assertions(1); + + expect(response).toEqual(undefined); + }); + + it('executes if `manifest` and `install` are provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-install-provided'; + + const response = await parseIfEnvArgs(); + + expect.assertions(2); + expect(response).toHaveProperty('install'); + expect(response).toHaveProperty('manifest'); + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliInputError(FILE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliInputError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliInputError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + process.env = originalEnv; }); From 13a1ab22bedd3034695929c522ad178d1cf5a93a Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:56:54 +0400 Subject: [PATCH 013/863] feat(config): add `IF_ENV` config --- src/config/config.ts | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index 4b23f9aa5..11f11eb86 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -2,7 +2,7 @@ import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; import {STRINGS} from './strings'; -import {IFDiffArgs, IEArgs} from '../types/process-args'; +import {IFDiffArgs, IEArgs, IFEnvArgs} from '../types/process-args'; const {DISCLAIMER_MESSAGE} = STRINGS; @@ -77,6 +77,36 @@ export const CONFIG = { SUCCESS_MESSAGE: 'Files match!', FAILURE_MESSAGE: 'Files do not match!', }, + IF_ENV: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + install: { + type: Boolean, + optional: true, + alias: 'i', + description: '[commant to install package.json]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + SUCCESS_MESSAGE: 'The environment is successfully setup!', + FAILURE_MESSAGE: 'Faied to create the environment!', + FAILURE_MESSAGE_TEMPLATE: + 'Faied to create the environment with the template manifest!', + FAILURE_MESSAGE_DEPENDENCIES: 'Manifest dependencies are not available!', + }, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], From 9d0d73c6c881ca3065dc37f09df073c092dfde90 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:58:07 +0400 Subject: [PATCH 014/863] feat(src): add if-env template manifest file --- src/env/template.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/env/template.yml diff --git a/src/env/template.yml b/src/env/template.yml new file mode 100644 index 000000000..f5fd65a6a --- /dev/null +++ b/src/env/template.yml @@ -0,0 +1,24 @@ +name: template manifest # rename me! +description: auto-generated template # update description! +tags: # add any tags that will help you to track your manifests +initialize: + outputs: + - yaml # you can add - csv to export to csv + plugins: # add more plugins for your use-case + memory-energy-from-memory-util: # you can name this any way you like! + method: Coefficient # the name of the function exported from the plugin + path: "builtin" # the import path + global-config: # anmy config required by the plugin + input-parameter: "memory/utilization" + coefficient: 0.0001 #kwH/GB + output-parameter: "memory/energy" +tree: + children: # add a chile for each distinct component you want to measure + child: + pipeline: # the pipeline is an ordered list of plugins you want to execute + - memory-energy-from-memory-util # must match the name in initialize! + config: # any plugin specific, node-level config + inputs: + - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string + duration: 3600 # units of seconds + memory/utilization: 10 From f9d4de702955429986dd274441492d54d2ba3abd Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 17:59:24 +0400 Subject: [PATCH 015/863] feat(src): add if-env functionality --- src/env/env.ts | 211 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/env/env.ts diff --git a/src/env/env.ts b/src/env/env.ts new file mode 100644 index 000000000..0964d095d --- /dev/null +++ b/src/env/env.ts @@ -0,0 +1,211 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {execPromise, isFileExists} from '../util/helpers'; +import {parseIfEnvArgs} from '../util/args'; +import {logger} from '../util/logger'; + +import {load} from '../lib/load'; + +import {CONFIG} from '../config'; + +const packageJson = require('../../package.json'); + +const {IF_ENV} = CONFIG; +const { + SUCCESS_MESSAGE, + FAILURE_MESSAGE, + FAILURE_MESSAGE_TEMPLATE, + FAILURE_MESSAGE_DEPENDENCIES, +} = IF_ENV; + +const FOLDER_NAME = 'if-environment'; + +type EnvironmentOptions = { + folderPath: string; + install: boolean; + dependencies: {[path: string]: string}; +}; + +const IfEnv = async () => { + const commandArgs = await parseIfEnvArgs(); + const options: EnvironmentOptions = { + folderPath: path.resolve(__dirname, FOLDER_NAME), + install: true, + dependencies: {'@grnsft/if': packageJson.version}, + }; + + if (commandArgs) { + const {folderPath, install, dependencies} = + await getOptionsFromArgs(commandArgs); + options.folderPath = folderPath; + options.install = !!install; + options.dependencies = {...options.dependencies, ...dependencies}; + } + + await initializeAndInstallLibs(options); + + if (!commandArgs) { + await addTemplateManifest(); + } + + console.log(SUCCESS_MESSAGE); + process.exit(0); +}; + +/** + * Gets the folder path of manifest file, dependencies from manifest file and install argument from the given arguments. + */ +const getOptionsFromArgs = async (commandArgs: { + manifest: string; + install: boolean | undefined; +}) => { + const {manifest: manifestPath, install} = commandArgs; + + const folderPath = path.dirname(manifestPath); + + const manifest = await load(manifestPath); + const plugins = manifest.rawManifest?.initialize?.plugins || {}; + const dependencies = + manifest.rawManifest?.execution?.environment.dependencies || []; + + if (!dependencies.length) { + throw new Error(FAILURE_MESSAGE_DEPENDENCIES); + } + + const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); + + return { + folderPath, + dependencies: pathsWithVersion, + install, + }; +}; + +/** + * Gets depencecies with versions. + */ +const extractPathsWithVersion = ( + plugins: any, + dependencies: string[] +): {[path: string]: string} => { + const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); + const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); + const pathsWithVersion: {[path: string]: string} = {}; + + uniquePaths.forEach(pluginPath => { + const dependency = dependencies.find((dependency: string) => + dependency.startsWith(pluginPath) + ); + + if (dependency) { + const splittedDependency = dependency.split('@'); + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[pluginPath] = `^${version}`; + } + }); + + return pathsWithVersion; +}; + +/** + * Creates folder if not exists, installs dependencies if required, update depenedencies. + */ +async function initializeAndInstallLibs(options: EnvironmentOptions) { + try { + const {folderPath, install, dependencies} = options; + + await fs.mkdir(folderPath, {recursive: true}); + + const packageJsonPath = await ensurePackageJsonExists(folderPath); + + if (install) { + await installDependencies(folderPath, dependencies); + } else { + await updatePackageJsonDependencies(packageJsonPath, dependencies); + } + } catch (error) { + console.log(FAILURE_MESSAGE); + } +} + +/** + * Checks if the package.json is exists, if not, inisializes it. + */ +async function ensurePackageJsonExists(folderPath: string) { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + const isPackageJsonExists = await isFileExists(packageJsonPath); + + if (!isPackageJsonExists) { + await execPromise('npm init -y', {cwd: folderPath}); + } + + return packageJsonPath; +} + +/** + * Installs packages from the specified dependencies in the specified folder. + */ +async function installDependencies( + folderPath: string, + dependencies: {[path: string]: string} +) { + const packages = Object.entries(dependencies).map( + ([dependency, version]) => `${dependency}@${version.replace('^', '')}` + ); + + await execPromise(`npm install ${packages.join(' ')}`, { + cwd: folderPath, + }); +} + +/** + * Updates package.json dependencies. + */ +async function updatePackageJsonDependencies( + packageJsonPath: string, + dependencies: {[path: string]: string} +) { + const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); + const packageJson = JSON.parse(packageJsonContent); + + packageJson.dependencies = { + ...packageJson.dependencies, + ...dependencies, + }; + + await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); +} + +/** + * Adds a manifest template to the folder where the if-env CLI command runs. + */ +async function addTemplateManifest() { + try { + const templateManifest = path.resolve(__dirname, 'template.yml'); + const destinationPath = path.resolve( + __dirname, + FOLDER_NAME, + 'manifest.yml' + ); + + const data = await fs.readFile(templateManifest, 'utf-8'); + await fs.writeFile(destinationPath, '', 'utf-8'); + await fs.writeFile(destinationPath, data, 'utf-8'); + } catch (error) { + console.log(FAILURE_MESSAGE_TEMPLATE); + } +} + +IfEnv().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 41397045bef3e312414bcb96c318ee7cf6f1494a Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 7 Jun 2024 18:02:17 +0400 Subject: [PATCH 016/863] feat(package): add `if-env` into bin and scripts --- package-lock.json | 3 ++- package.json | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c4cd07c8..8f0f4b40f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,8 @@ }, "bin": { "ie": "build/index.js", - "if-diff": "build/diff.js" + "if-diff": "build/diff.js", + "if-env": "build/env/env.js" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/package.json b/package.json index ded9a8331..434e1894a 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ }, "bin": { "ie": "./build/index.js", - "if-diff": "./build/diff.js" + "if-diff": "./build/diff.js", + "if-env": "./build/env/env.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -71,6 +72,7 @@ "fix:package": "fixpack", "ie": "npx ts-node src/index.ts", "if-diff": "npx ts-node src/diff.ts", + "if-env": "npx ts-node src/env/env.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", @@ -81,4 +83,4 @@ }, "stability": "stable", "types": "src/index.d.ts" -} +} \ No newline at end of file From 9da09b6ba3db0af434095fde0e22266d549fc2bc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:15:59 +0400 Subject: [PATCH 017/863] feat(util): update error usage in plugin storage --- src/util/plugin-storage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/plugin-storage.ts b/src/util/plugin-storage.ts index 7667d5e07..15582e9f3 100644 --- a/src/util/plugin-storage.ts +++ b/src/util/plugin-storage.ts @@ -4,7 +4,7 @@ import {STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; import {PluginStorage} from '../types/plugin-storage'; -const {PluginInitalizationError} = ERRORS; +const {PluginInitializationError} = ERRORS; const {NOT_INITALIZED_PLUGIN} = STRINGS; /** @@ -21,7 +21,7 @@ export const pluginStorage = () => { const plugin = storage[name]; if (!plugin) { - throw new PluginInitalizationError(NOT_INITALIZED_PLUGIN(name)); + throw new PluginInitializationError(NOT_INITALIZED_PLUGIN(name)); } return plugin; From e769eaaed7c4d22b04399fe483fdee0caa9383b5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:16:40 +0400 Subject: [PATCH 018/863] feat(util): drop build error message helper --- src/util/helpers.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b15863cef..c2b644d32 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,24 +1,16 @@ import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; -import {ErrorFormatParams} from '../types/helpers'; + import {ERRORS} from './errors'; import {logger} from './logger'; + import {STRINGS} from '../config'; import {Difference} from '../types/lib/compare'; -const {ISSUE_TEMPLATE} = STRINGS; - -/** - * Formats given error according to class instance, scope and message. - */ -export const buildErrorMessage = - (classInstanceName: string) => (params: ErrorFormatParams) => { - const {scope, message} = params; - - return `${classInstanceName}${scope ? `(${scope})` : ''}: ${message}.`; - }; +const {ISSUE_TEMPLATE, MISSING_MANIFEST_IN_STDIN} = STRINGS; +const {CliInputError} = ERRORS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -177,7 +169,7 @@ export const parseManifestFromStdin = async () => { const match = regex.exec(pipedSourceManifest); if (!match) { - throw new Error('Manifest not found in STDIN.'); + throw new CliInputError(MISSING_MANIFEST_IN_STDIN); } return match![1]; From 4251823d72d00dfd295841c5ded980009c65d1c4 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:17:20 +0400 Subject: [PATCH 019/863] feat(util): make error classes granular --- src/util/errors.ts | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/util/errors.ts b/src/util/errors.ts index a65a603be..f4f067d77 100644 --- a/src/util/errors.ts +++ b/src/util/errors.ts @@ -1,19 +1,33 @@ const CUSTOM_ERRORS = [ 'CliInputError', - 'ConfigNotFoundError', - 'ConfigValidationError', - 'ExhaustError', - 'FileNotFoundError', - 'MakeDirectoryError', 'ManifestValidationError', - 'ModuleInitializationError', 'InputValidationError', - 'InvalidAggregationParamsError', 'InvalidGroupingError', - 'PluginCredentialError', - 'PluginInitalizationError', 'WriteFileError', - 'ConfigNotFoundError', + /** More specific errors */ + 'ParseCliParamsError', + 'CliSourceFileError', + 'CliTargetFileError', + 'InvalidAggregationMethodError', + 'MissingAggregationParamError', + 'MissingPluginMethodError', + 'MissingPluginPathError', + 'PluginInitializationError', + 'InvalidExhaustPluginError', + /** Plugins */ + 'GlobalConfigError', + 'MissingInputDataError', + 'ProcessExecutionError', + 'RegexMismatchError', + 'FetchingFileError', + 'ReadFileError', + 'MissingCSVColumnError', + 'QueryDataNotFoundError', + 'InvalidDateInInputError', + 'InvalidPaddingError', + 'InvalidInputError', + 'ExhaustOutputArgError', + 'CSVParseError', ] as const; type CustomErrors = { From 78972b1cd8d84fe66699462b45799f7a626ec950 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:17:54 +0400 Subject: [PATCH 020/863] feat(util): update errors usage in args --- src/util/args.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 56466fd48..06ee99e93 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -10,7 +10,12 @@ import {CONFIG, STRINGS} from '../config'; import {IFDiffArgs, IEArgs, ProcessArgsOutputs} from '../types/process-args'; import {LoadDiffParams} from '../types/util/args'; -const {CliInputError} = ERRORS; +const { + CliInputError, + ParseCliParamsError, + CliTargetFileError, + CliSourceFileError, +} = ERRORS; const {IE, IF_DIFF} = CONFIG; @@ -83,10 +88,10 @@ export const parseIEProcessArgs = (): ProcessArgsOutputs => { }; } - throw new CliInputError(FILE_IS_NOT_YAML); + throw new CliSourceFileError(FILE_IS_NOT_YAML); } - throw new CliInputError(MANIFEST_IS_MISSING); + throw new CliSourceFileError(MANIFEST_IS_MISSING); }; /** -- IF Diff -- */ @@ -99,7 +104,7 @@ const validateAndParseIfDiffArgs = () => { return parse(IF_DIFF.ARGS, IF_DIFF.HELP); } catch (error) { if (error instanceof Error) { - throw new CliInputError(error.message); + throw new ParseCliParamsError(error.message); } throw error; @@ -114,7 +119,7 @@ export const parseIfDiffArgs = () => { if (target) { if (source && !checkIfFileIsYaml(source)) { - throw new CliInputError(SOURCE_IS_NOT_YAML); + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); } if (checkIfFileIsYaml(target)) { @@ -129,7 +134,7 @@ export const parseIfDiffArgs = () => { return response; } - throw new CliInputError(TARGET_IS_NOT_YAML); + throw new CliTargetFileError(TARGET_IS_NOT_YAML); } throw new CliInputError(INVALID_TARGET); From 62f70d5123eaa5a4fd12fed9cbe01fcdc0916ecc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:18:22 +0400 Subject: [PATCH 021/863] feat(util): update errors usage in aggregation helper --- src/util/aggregation-helper.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/aggregation-helper.ts b/src/util/aggregation-helper.ts index 3be503ffc..0a8b3c136 100644 --- a/src/util/aggregation-helper.ts +++ b/src/util/aggregation-helper.ts @@ -6,7 +6,7 @@ import {CONFIG, STRINGS} from '../config'; import {AggregationResult} from '../types/aggregation'; import {PluginParams} from '../types/interface'; -const {InvalidAggregationParamsError} = ERRORS; +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; @@ -19,7 +19,7 @@ const checkIfMetricsAreValid = (metrics: string[]) => { const method = parameterize.getAggregationMethod(metric); if (method === 'none') { - throw new InvalidAggregationParamsError( + throw new InvalidAggregationMethodError( INVALID_AGGREGATION_METHOD(metric) ); } @@ -41,7 +41,7 @@ export const aggregateInputsIntoOne = ( return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { if (!(metric in input)) { - throw new InvalidAggregationParamsError(METRIC_MISSING(metric, index)); + throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); } /** Checks if metric is timestamp or duration, then adds to aggregated value. */ From 3269fc9b62347945f6f5048d06bfa75e67337ba7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:22:12 +0400 Subject: [PATCH 022/863] revert(types): drop helpers --- src/types/helpers.ts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 src/types/helpers.ts diff --git a/src/types/helpers.ts b/src/types/helpers.ts deleted file mode 100644 index ed413174b..000000000 --- a/src/types/helpers.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type ErrorFormatParams = { - scope?: string; - message: string; -}; From 1c826ea2a3e563c332fd745557e2415c1505a052 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:25:44 +0400 Subject: [PATCH 023/863] feat(lib): update errors usage in load --- src/lib/load.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/load.ts b/src/lib/load.ts index 447153068..e1a0cb465 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -12,7 +12,7 @@ import {Parameters} from '../types/parameters'; import {LoadDiffParams} from '../types/util/args'; import {Manifest} from '../types/manifest'; -const {CliInputError} = ERRORS; +const {CliSourceFileError} = ERRORS; const {INVALID_SOURCE} = STRINGS; @@ -43,7 +43,7 @@ export const loadIfDiffFiles = async (params: LoadDiffParams) => { const pipedSourceManifest = await parseManifestFromStdin(); if (!sourcePath && !pipedSourceManifest) { - throw new CliInputError(INVALID_SOURCE); + throw new CliSourceFileError(INVALID_SOURCE); } const loadFromSource = From 85a66dd93e9a79b75e1774c32443b00bbf1a698e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:26:03 +0400 Subject: [PATCH 024/863] feat(lib): update errors usage in initalize --- src/lib/initialize.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/lib/initialize.ts b/src/lib/initialize.ts index d6bf7c184..e20d5f53b 100644 --- a/src/lib/initialize.ts +++ b/src/lib/initialize.ts @@ -11,7 +11,11 @@ import {PluginInterface} from '../types/interface'; import {GlobalPlugins, PluginOptions} from '../types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; -const {ModuleInitializationError, PluginCredentialError} = ERRORS; +const { + PluginInitializationError, + MissingPluginMethodError, + MissingPluginPathError, +} = ERRORS; const {GITHUB_PATH, NATIVE_PLUGIN} = CONFIG; const {MISSING_METHOD, MISSING_PATH, NOT_NATIVE_PLUGIN, INVALID_MODULE_PATH} = @@ -21,14 +25,11 @@ const {MISSING_METHOD, MISSING_PATH, NOT_NATIVE_PLUGIN, INVALID_MODULE_PATH} = * Imports module by given `path`. */ const importModuleFrom = async (path: string) => { - try { - const module = await import(path); + const module = await import(path).catch(error => { + throw new PluginInitializationError(INVALID_MODULE_PATH(path, error)); + }); - return module; - } catch (error) { - logger.error(error); - throw new ModuleInitializationError(INVALID_MODULE_PATH(path)); - } + return module; }; /** @@ -71,11 +72,11 @@ const initPlugin = async ( const {method, path, 'global-config': globalConfig} = initPluginParams; if (!method) { - throw new PluginCredentialError(MISSING_METHOD); + throw new MissingPluginMethodError(MISSING_METHOD); } if (!path) { - throw new PluginCredentialError(MISSING_PATH); + throw new MissingPluginPathError(MISSING_PATH); } const plugin = await handModule(method, path); From c39cbab19fd81a24a09e8974fd736683350a155b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 01:26:21 +0400 Subject: [PATCH 025/863] feat(lib): update errors usage in exhaust --- src/lib/exhaust.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 5c80b0a5a..98eaf7625 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -14,7 +14,7 @@ import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; import {Options} from '../types/process-args'; -const {ExhaustError} = ERRORS; +const {InvalidExhaustPluginError} = ERRORS; const {INVALID_EXHAUST_PLUGIN} = STRINGS; /** @@ -35,7 +35,7 @@ const initializeExhaustPlugin = (name: string): ExhaustPluginInterface => { case 'csv-raw': return ExportCSVRaw(); default: - throw new ExhaustError(INVALID_EXHAUST_PLUGIN(name)); + throw new InvalidExhaustPluginError(INVALID_EXHAUST_PLUGIN(name)); } }; From 731670336963afd75b2e9167f9ebb46cb1c0ab71 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 12:26:58 +0400 Subject: [PATCH 026/863] feat(config): update strings to include all messages --- src/config/strings.ts | 59 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 04551b9b9..a96e11184 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -17,12 +17,12 @@ Incubation projects are experimental, offer no support guarantee, have minimal g NOT_NATIVE_PLUGIN: (path: string) => ` You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, - SOMETHING_WRONG: 'Something wrong with cli arguments. Please check docs.', ISSUE_TEMPLATE: ` Impact Framework is an alpha release from the Green Software Foundation and is released to capture early feedback. If you'd like to offer some feedback, please use this issue template: https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+`, - INVALID_MODULE_PATH: (path: string) => - `Provided module: '${path}' is invalid or not found.`, + INVALID_MODULE_PATH: (path: string, error?: any) => + `Provided module \`${path}\` is invalid or not found. ${error ?? ''} +`, INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', UNEXPECTED_TIME_CONFIG: 'Unexpected node-level config provided for time-sync plugin.', @@ -33,7 +33,6 @@ https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=fee `Avoiding padding at ${ start && end ? 'start and end' : start ? 'start' : 'end' }`, - INVALID_OBSERVATION_OVERLAP: 'Observation timestamps overlap.', INVALID_AGGREGATION_METHOD: (metric: string) => `Aggregation is not possible for given ${metric} since method is 'none'.`, METRIC_MISSING: (metric: string, index: number) => @@ -56,4 +55,56 @@ Note that for the '--output' option you also need to define the output type in y TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', + MISSING_MANIFEST_IN_STDIN: 'Manifest not found in STDIN.', + /** Plugin messages */ + MISSING_GLOBAL_CONFIG: 'Global config is not provided.', + MISSING_INPUT_DATA: (param: string) => + `${param} is missing from the input array.`, + NOT_NUMERIC_VALUE: (str: any) => `${str} is not numberic.`, + MISSING_FUNCTIONAL_UNIT_CONFIG: + '`functional-unit` should be provided in your global config', + MISSING_FUNCTIONAL_UNIT_INPUT: + '`functional-unit` value is missing from input data or it is not a positive integer', + REGEX_MISMATCH: (input: any, match: string) => + `\`${input}\` does not match the ${match} regex expression`, + SCI_EMBODIED_ERROR: (unit: string) => + `invalid number. please provide it as \`${unit}\` to input`, + MISSING_MIN_MAX: 'Config is missing min or max value', + INVALID_MIN_MAX: (name: string) => + `Min value should not be greater than or equal to max value of ${name}`, + FILE_FETCH_FAILED: ( + filepath: string, + message: string + ) => `Failed fetching the file: ${filepath}. +${message}`, + FILE_READ_FAILED: ( + filepath: string, + error: string + ) => `Failed reading the file: ${filepath}. +${error}`, + MISSING_CSV_COLUMN: (columnName: string) => + `There is no column with the name: ${columnName}.`, + NO_QUERY_DATA: + 'One or more of the given query parameters are not found in the target CSV file column headers.', + INVALID_DATE_TYPE: (date: any) => + `Unexpected date datatype: ${typeof date}: ${date}`, + INVALID_OBSERVATION_OVERLAP: + 'Observation timestamps overlap, please check inputs.', + /** Exhaust messages */ + OUTPUT_REQUIRED: + 'Output path is required, please make sure output is configured properly.', + CSV_EXPORT: + 'CSV export criteria is not found in output path. Please append it after --output #.', + WRITE_CSV_ERROR: (outputPath: string, error: any) => + `Failed to write CSV file to ${outputPath}: ${error}`, + INVALID_NAME: + '`name` global config parameter is empty or contains all spaces', + START_LOWER_END: '`start-time` should be lower than `end-time`', + TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, + INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, + X_Y_EQUAL: 'The length of `x` and `y` should be equal', + ARRAY_LENGTH_NON_EMPTY: + 'the length of the input arrays must be greater than 1', + WITHIN_THE_RANGE: + 'The target x value must be within the range of the given x values', }; From d9c047ef49b59e44f360eef6b43d664369421b27 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:54:20 +0400 Subject: [PATCH 027/863] feat(builtins): update errors usage in sum --- src/builtins/sum/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts index 8eec61c37..9944373a8 100644 --- a/src/builtins/sum/index.ts +++ b/src/builtins/sum/index.ts @@ -1,13 +1,15 @@ import {z} from 'zod'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; - import {validate} from '../../util/validations'; import {ERRORS} from '../../util/errors'; +import {STRINGS} from '../../config'; + +import {ExecutePlugin, PluginParams} from '../../types/interface'; import {SumConfig} from './types'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_INPUT_DATA, MISSING_GLOBAL_CONFIG} = STRINGS; export const Sum = (globalConfig: SumConfig): ExecutePlugin => { const metadata = { @@ -37,7 +39,7 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ @@ -60,9 +62,7 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { ) => { inputParameters.forEach(metricToSum => { if (!input[metricToSum]) { - throw new InputValidationError( - `${metricToSum} is missing from the input array.` - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(metricToSum)); } }); From d0452663110a6b71f3f6ca1a4a1e162ccf99d79d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:54:49 +0400 Subject: [PATCH 028/863] feat(builtins): update errors usage in mock observations, do cosmetic fixes --- .../helpers/common-generator.ts | 27 ++++----- .../helpers/rand-int-generator.ts | 56 ++++++++----------- src/builtins/mock-observations/index.ts | 6 +- 3 files changed, 35 insertions(+), 54 deletions(-) diff --git a/src/builtins/mock-observations/helpers/common-generator.ts b/src/builtins/mock-observations/helpers/common-generator.ts index 24bea4c94..ee4909dcd 100644 --- a/src/builtins/mock-observations/helpers/common-generator.ts +++ b/src/builtins/mock-observations/helpers/common-generator.ts @@ -1,37 +1,30 @@ -import {KeyValuePair} from '../../../types/common'; import {ERRORS} from '../../../util/errors'; -import {buildErrorMessage} from '../../../util/helpers'; -import {Generator} from '../interfaces'; - -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; -export const CommonGenerator = (config: KeyValuePair): Generator => { - const errorBuilder = buildErrorMessage(CommonGenerator.name); +import {Generator} from '../interfaces'; - /** - * Creates new copy of the given `object`. - */ - const copyObject = (object: T): T => ({...object}); +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; +export const CommonGenerator = (config: Record): Generator => { /** + * Generates next value by copying the validated config. * Validates the provided config is not null or empty. - * returns a copy of the validated config, otherwise throws an InputValidationError. + * Returns a copy of the validated config, otherwise throws an GlobalConfigError. */ const validateConfig = (config: object) => { if (!config || Object.keys(config).length === 0) { - throw new InputValidationError( - errorBuilder({message: 'Config must not be null or empty'}) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } - return copyObject(config); + return structuredClone(config); }; /** * Generates next value by copying the validated config. */ - const next = (): Object => copyObject(validateConfig(config)); + const next = (): Object => validateConfig(config); return { next, diff --git a/src/builtins/mock-observations/helpers/rand-int-generator.ts b/src/builtins/mock-observations/helpers/rand-int-generator.ts index e27d694c3..a48e399c8 100644 --- a/src/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/builtins/mock-observations/helpers/rand-int-generator.ts @@ -1,70 +1,57 @@ -import {KeyValuePair} from '../../../types/common'; import {ERRORS} from '../../../util/errors'; -import {buildErrorMessage} from '../../../util/helpers'; + +import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; import {RandIntGeneratorParams} from '../types'; -const {InputValidationError} = ERRORS; +const {GlobalConfigError} = ERRORS; + +const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = + STRINGS; export const RandIntGenerator = ( name: string, - config: KeyValuePair + config: Record ): Generator => { - const errorBuilder = buildErrorMessage(RandIntGenerator.name); - const next = () => ({ [validatedName]: generateRandInt(getFieldToPopulate()), }); const validateName = (name: string | null): string => { if (!name || name.trim() === '') { - throw new InputValidationError( - errorBuilder({ - message: '`name` is empty or all spaces', - }) - ); + throw new GlobalConfigError(INVALID_NAME); } + return name; }; - const validateConfig = (config: KeyValuePair): {min: number; max: number} => { + const validateConfig = ( + config: Record + ): {min: number; max: number} => { if (!config || Object.keys(config).length === 0) { - throw new InputValidationError( - errorBuilder({ - message: 'Config must not be null or empty', - }) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } if (!config.min || !config.max) { - throw new InputValidationError( - errorBuilder({ - message: 'Config is missing min or max', - }) - ); + throw new GlobalConfigError(MISSING_MIN_MAX); } if (config.min >= config.max) { - throw new InputValidationError( - errorBuilder({ - message: `Min value should not be greater than or equal to max value of ${validatedName}`, - }) - ); + throw new GlobalConfigError(INVALID_MIN_MAX(validatedName)); } + return {min: config.min, max: config.max}; }; const validatedName = validateName(name); const validatedConfig = validateConfig(config); - const getFieldToPopulate = () => { - return { - name: validatedName, - min: validatedConfig.min, - max: validatedConfig.max, - }; - }; + const getFieldToPopulate = () => ({ + name: validatedName, + min: validatedConfig.min, + max: validatedConfig.max, + }); const generateRandInt = ( randIntGenerator: RandIntGeneratorParams @@ -73,6 +60,7 @@ export const RandIntGenerator = ( const scaledNumber = randomNumber * (randIntGenerator.max - randIntGenerator.min) + randIntGenerator.min; + return Math.trunc(scaledNumber); }; diff --git a/src/builtins/mock-observations/index.ts b/src/builtins/mock-observations/index.ts index 2d65f4643..b535da757 100644 --- a/src/builtins/mock-observations/index.ts +++ b/src/builtins/mock-observations/index.ts @@ -1,13 +1,13 @@ import {DateTime, Duration} from 'luxon'; import {z} from 'zod'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams, KeyValuePair} from '../../types/common'; - import {validate} from '../../util/validations'; import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; + +import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ConfigParams, KeyValuePair} from '../../types/common'; import {Generator} from './interfaces/index'; import {ObservationParams} from './types'; From c4ed3d87726c386c74194ba20a825759438c64e1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:55:20 +0400 Subject: [PATCH 029/863] feat(builtins): update errors usage in subtract --- src/builtins/subtract/index.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts index 0af02898a..25f5d8522 100644 --- a/src/builtins/subtract/index.ts +++ b/src/builtins/subtract/index.ts @@ -1,16 +1,17 @@ import {z} from 'zod'; import {ERRORS} from '../../util/errors'; -import {buildErrorMessage} from '../../util/helpers'; import {validate} from '../../util/validations'; +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams} from '../../types/interface'; import {SubtractConfig} from './types'; const {InputValidationError} = ERRORS; +const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Subtract.name); const metadata = { kind: 'execute', }; @@ -47,21 +48,13 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { const validateParamExists = (input: PluginParams, param: string) => { if (input[param] === undefined) { - throw new InputValidationError( - errorBuilder({ - message: `${param} is missing from the input array`, - }) - ); + throw new InputValidationError(MISSING_INPUT_DATA(param)); } }; const validateNumericString = (str: string) => { if (isNaN(+Number(str))) { - throw new InputValidationError( - errorBuilder({ - message: `${str} is not numberic`, - }) - ); + throw new InputValidationError(NOT_NUMERIC_VALUE(str)); } }; @@ -73,6 +66,7 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { 'input-parameters': inputParameters, 'output-parameter': outputParameter, } = validateGlobalConfig(); + return inputs.map(input => { validateSingleInput(input, inputParameters); @@ -88,6 +82,7 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { */ const calculateDiff = (input: PluginParams, inputParameters: string[]) => { const [firstItem, ...restItems] = inputParameters; + return restItems.reduce( (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], input[firstItem] // Starting accumulator with the value of the first item From c21fb0f01f3d23c7652c3e3c9e0b080697659c17 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:55:42 +0400 Subject: [PATCH 030/863] feat(builtins): update errors usage in shell --- src/builtins/shell/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/builtins/shell/index.ts b/src/builtins/shell/index.ts index 43b1c224c..c78f668e2 100644 --- a/src/builtins/shell/index.ts +++ b/src/builtins/shell/index.ts @@ -8,7 +8,7 @@ import {ConfigParams} from '../../types/common'; import {validate} from '../../util/validations'; import {ERRORS} from '../../util/errors'; -const {InputValidationError} = ERRORS; +const {ProcessExecutionError} = ERRORS; export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -55,7 +55,7 @@ export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { return {outputs}; } catch (error: any) { - throw new InputValidationError(error.message); + throw new ProcessExecutionError(error.message); } }; From 8c3990189e56ac0541b1cee9f0f901d2f4bc3b9f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:55:51 +0400 Subject: [PATCH 031/863] feat(builtins): update errors usage in sci-embodied --- src/builtins/sci-embodied/index.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/builtins/sci-embodied/index.ts b/src/builtins/sci-embodied/index.ts index 162099860..02f897584 100644 --- a/src/builtins/sci-embodied/index.ts +++ b/src/builtins/sci-embodied/index.ts @@ -1,8 +1,12 @@ import {z} from 'zod'; +import {validate, allDefined} from '../../util/validations'; + +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {validate, allDefined} from '../../util/validations'; +const {SCI_EMBODIED_ERROR} = STRINGS; export const SciEmbodied = (): ExecutePlugin => { const metadata = { @@ -55,9 +59,6 @@ export const SciEmbodied = (): ExecutePlugin => { * Checks for required fields in input. */ const validateInput = (input: PluginParams) => { - const errorMessage = (unit: string) => - `not a valid number in input. Please provide it as \`${unit}\``; - const commonSchemaPart = (errorMessage: (unit: string) => string) => ({ 'device/emissions-embodied': z .number({ @@ -81,13 +82,13 @@ export const SciEmbodied = (): ExecutePlugin => { const vcpusSchemaPart = { 'vcpus-allocated': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), 'vcpus-total': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), @@ -96,24 +97,24 @@ export const SciEmbodied = (): ExecutePlugin => { const resourcesSchemaPart = { 'resources-reserved': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), 'resources-total': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), }; const schemaWithVcpus = z.object({ - ...commonSchemaPart(errorMessage), + ...commonSchemaPart(SCI_EMBODIED_ERROR), ...vcpusSchemaPart, }); const schemaWithResources = z.object({ - ...commonSchemaPart(errorMessage), + ...commonSchemaPart(SCI_EMBODIED_ERROR), ...resourcesSchemaPart, }); From 0d978f48bd07c05fe8a8bd29628d22731f386437 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:00 +0400 Subject: [PATCH 032/863] feat(builtins): update errors usage in sci --- src/builtins/sci/index.ts | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index 7a60db439..a39e33c94 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -1,16 +1,17 @@ import {z} from 'zod'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; - import {validate, allDefined} from '../../util/validations'; -import {buildErrorMessage} from '../../util/helpers'; import {ERRORS} from '../../util/errors'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../config'; + +import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ConfigParams} from '../../types/common'; + +const {MissingInputDataError} = ERRORS; +const {MISSING_FUNCTIONAL_UNIT_CONFIG, MISSING_FUNCTIONAL_UNIT_INPUT} = STRINGS; export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Sci.name); const metadata = { kind: 'execute', }; @@ -19,15 +20,12 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { * Validates node and gloabl configs. */ const validateConfig = (config?: ConfigParams) => { - const errorMessage = - '`functional-unit` should be provided in your global config'; - const schema = z .object({ 'functional-unit': z.string(), }) .refine(data => data['functional-unit'], { - message: errorMessage, + message: MISSING_FUNCTIONAL_UNIT_CONFIG, }); return validate>(schema, config); @@ -36,19 +34,19 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { /** * Calculate the total emissions for a list of inputs. */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - return inputs.map(input => { + const execute = (inputs: PluginParams[]): PluginParams[] => + inputs.map(input => { const safeInput = validateInput(input); const sci = safeInput['carbon'] > 0 ? safeInput['carbon'] / input[globalConfig['functional-unit']] : 0; + return { ...input, sci, }; }); - }; /** * Checks for fields in input. @@ -64,12 +62,7 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { input[validatedConfig['functional-unit']] > 0 ) ) { - throw new InputValidationError( - errorBuilder({ - message: - 'functional-unit value is missing from input data or it is not a positive integer', - }) - ); + throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); } const schema = z From 296734aca0ca72addea6a4acdcf3f6bb40d12fd5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:06 +0400 Subject: [PATCH 033/863] feat(builtins): update errors usage in regex --- src/builtins/regex/index.ts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/builtins/regex/index.ts b/src/builtins/regex/index.ts index 7dc854461..5730697cc 100644 --- a/src/builtins/regex/index.ts +++ b/src/builtins/regex/index.ts @@ -1,16 +1,17 @@ import {z} from 'zod'; -import {buildErrorMessage} from '../../util/helpers'; import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams} from '../../types/interface'; import {ConfigParams} from '../../types/common'; -const {InputValidationError, ConfigValidationError} = ERRORS; +const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Regex.name); const metadata = { kind: 'execute', }; @@ -20,10 +21,9 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigValidationError( - errorBuilder({message: 'Configuration data is missing'}) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } + const schema = z.object({ parameter: z.string().min(1), match: z.string().min(1), @@ -38,11 +38,7 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateSingleInput = (input: PluginParams, parameter: string) => { if (!input[parameter]) { - throw new InputValidationError( - errorBuilder({ - message: `\`${parameter}\` is missing from the input`, - }) - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); } return input; @@ -89,11 +85,7 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { const matchedItem = input[parameter].match(regex); if (!matchedItem || !matchedItem[0]) { - throw new InputValidationError( - errorBuilder({ - message: `\`${input[parameter]}\` does not match the ${match} regex expression`, - }) - ); + throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); } return matchedItem[0]; From c60a1ab3504222b100c734c041168f11fa53e8fb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:13 +0400 Subject: [PATCH 034/863] feat(builtins): update errors usage in multiply --- src/builtins/multiply/index.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts index 5666a6093..ffcf4d14c 100644 --- a/src/builtins/multiply/index.ts +++ b/src/builtins/multiply/index.ts @@ -1,16 +1,17 @@ import {z} from 'zod'; -import {buildErrorMessage} from '../../util/helpers'; import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams} from '../../types/interface'; import {MultiplyConfig} from './types'; -const {InputValidationError} = ERRORS; +const {MissingInputDataError} = ERRORS; +const {MISSING_INPUT_DATA} = STRINGS; export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Multiply.name); const metadata = { kind: 'execute', }; @@ -42,11 +43,7 @@ export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { input[metricToMultiply] === undefined || isNaN(input[metricToMultiply]) ) { - throw new InputValidationError( - errorBuilder({ - message: `${metricToMultiply} is missing from the input array`, - }) - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(metricToMultiply)); } }); From 58bdc8e45539d4ebcd8377c7a57c0ccf243a8068 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:20 +0400 Subject: [PATCH 035/863] feat(builtins): update errors usage in interpolation --- src/builtins/interpolation/index.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/builtins/interpolation/index.ts b/src/builtins/interpolation/index.ts index 3c0e0381b..35f88788b 100644 --- a/src/builtins/interpolation/index.ts +++ b/src/builtins/interpolation/index.ts @@ -6,9 +6,17 @@ import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; import {validate} from '../../util/validations'; import {ERRORS} from '../../util/errors'; +import {STRINGS} from '../../config'; + import {Method} from './types'; -const {ConfigNotFoundError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + X_Y_EQUAL, + ARRAY_LENGTH_NON_EMPTY, + WITHIN_THE_RANGE, +} = STRINGS; export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { /** @@ -118,7 +126,7 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z @@ -130,10 +138,10 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { 'output-parameter': z.string(), }) .refine(data => data.x && data.y && data.x.length === data.y.length, { - message: 'The length of `x` and `y` should be equal', + message: X_Y_EQUAL, }) .refine(data => data.x.length > 1 && data.y.length > 1, { - message: 'the length of the input arrays must be greater than 1', + message: ARRAY_LENGTH_NON_EMPTY, }); const defaultMethod = globalConfig.method ?? Method.LINEAR; @@ -171,8 +179,7 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { data[inputParameter] >= globalConfig.x[0] && data[inputParameter] <= globalConfig.x[globalConfig.x.length - 1], { - message: - 'The target x value must be within the range of the given x values', + message: WITHIN_THE_RANGE, } ); From b11aa7e1566de4e63ff2bfc5347c0e8d428dd6f1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:26 +0400 Subject: [PATCH 036/863] feat(builtins): update errors usage in exponent --- src/builtins/exponent/index.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 404161e63..0de914fda 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -1,16 +1,17 @@ import {z} from 'zod'; import {ERRORS} from '../../util/errors'; -import {buildErrorMessage} from '../../util/helpers'; import {validate} from '../../util/validations'; +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams} from '../../types/interface'; import {ExponentConfig} from './types'; -const {InputValidationError} = ERRORS; +const {MissingInputDataError, InputValidationError} = ERRORS; +const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Exponent.name); const metadata = { kind: 'execute', }; @@ -41,21 +42,13 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const validateParamExists = (input: PluginParams, param: string) => { if (input[param] === undefined) { - throw new InputValidationError( - errorBuilder({ - message: `${param} is missing from the input array`, - }) - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(param)); } }; const validateNumericString = (str: string) => { if (isNaN(+Number(str))) { - throw new InputValidationError( - errorBuilder({ - message: `${str} is not numeric`, - }) - ); + throw new InputValidationError(NOT_NUMERIC_VALUE(str)); } }; From 2e2b07fc252f773f52f5fd3d9335489d08afad6f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:32 +0400 Subject: [PATCH 037/863] feat(builtins): update errors usage in divide --- src/builtins/divide/index.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts index b91d4c9fa..e50ca81f9 100644 --- a/src/builtins/divide/index.ts +++ b/src/builtins/divide/index.ts @@ -3,9 +3,12 @@ import {z} from 'zod'; import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; +import {STRINGS} from '../../config'; + import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -38,7 +41,7 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z.object({ @@ -65,9 +68,7 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { }) .refine(() => { if (typeof denominator === 'string' && !input[denominator]) { - throw new InputValidationError( - `\`${denominator}\` is missing from the input.` - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(denominator)); } return true; }); From c16f46c36a4e8ad258bfff11cc3256955552167d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:56:52 +0400 Subject: [PATCH 038/863] feat(builtins): update errors usage in csv lookup, optimize strategy --- src/builtins/csv-lookup/index.ts | 106 +++++++++++++++++++------------ 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts index 2539a14cf..4f7df52be 100644 --- a/src/builtins/csv-lookup/index.ts +++ b/src/builtins/csv-lookup/index.ts @@ -5,12 +5,29 @@ import axios from 'axios'; import {z} from 'zod'; import {parse} from 'csv-parse/sync'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; - import {validate} from '../../util/validations'; import {ERRORS} from '../../util/errors'; -const {ConfigNotFoundError, FileNotFoundError, InputValidationError} = ERRORS; +import {STRINGS} from '../../config'; + +import {ExecutePlugin, PluginParams} from '../../types/interface'; + +const { + FILE_FETCH_FAILED, + FILE_READ_FAILED, + MISSING_CSV_COLUMN, + NO_QUERY_DATA, + MISSING_GLOBAL_CONFIG, +} = STRINGS; + +const { + FetchingFileError, + ReadFileError, + MissingCSVColumnError, + QueryDataNotFoundError, + GlobalConfigError, + CSVParseError, +} = ERRORS; export const CSVLookup = (globalConfig: any): ExecutePlugin => { const metadata = { @@ -36,18 +53,16 @@ export const CSVLookup = (globalConfig: any): ExecutePlugin => { const retrieveFile = async (filepath: string) => { if (isURL(filepath)) { const {data} = await axios.get(filepath).catch(error => { - throw new FileNotFoundError(`Something went wrong while reading the file: ${filepath}. - ${error.response.message}`); + throw new FetchingFileError( + FILE_FETCH_FAILED(filepath, error.response.message) + ); }); return data; } return readFile(filepath).catch(error => { - throw new FileNotFoundError( - `Something went wrong while reading the file: ${filepath}. -${error}` - ); + throw new ReadFileError(FILE_READ_FAILED(filepath, error)); }); }; @@ -81,7 +96,7 @@ ${error}` */ const fieldAccessor = (field: string, object: any) => { if (!(`${field}` in object)) { - throw new InputValidationError(`There is no column with name: ${field}.`); + throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); } return nanifyEmptyValues(object[field]); @@ -149,6 +164,24 @@ ${error}` return ifMatchesCriteria.every(value => value === true); }; + /** + * Parses CSV file. + */ + const parseCSVFile = (file: string | Buffer) => { + try { + const parsedCSV: any[] = parse(file, { + columns: true, + skip_empty_lines: true, + cast: true, + }); + + return parsedCSV; + } catch (error: any) { + console.error(error); + throw new CSVParseError(error); + } + }; + /** * 1. Validates global config. * 2. Tries to retrieve given file (with url or local path). @@ -160,41 +193,30 @@ ${error}` const {filepath, query, output} = safeGlobalConfig; const file = await retrieveFile(filepath); - - try { - const parsedCSV: any[] = parse(file, { - columns: true, - skip_empty_lines: true, - cast: true, + console.log(file); + const parsedCSV = parseCSVFile(file); + + return inputs.map(input => { + /** Collects query values from input. */ + const queryData: any = {}; + const queryKeys = Object.keys(query); + queryKeys.forEach(queryKey => { + const queryValue = query[queryKey]; + queryData[queryKey] = input[queryValue]; }); - return inputs.map(input => { - /** Collects query values from input. */ - const queryData: any = {}; - const queryKeys = Object.keys(query); - queryKeys.forEach(queryKey => { - const queryValue = query[queryKey]; - queryData[queryKey] = input[queryValue]; - }); - - /** Gets related data from CSV. */ - const relatedData = parsedCSV.find(withCriteria(queryData)); + /** Gets related data from CSV. */ + const relatedData = parsedCSV.find(withCriteria(queryData)); - if (!relatedData) { - throw new InputValidationError( - 'One or more of the given query parameters are not found in the target CSV file column headers.' - ); - } + if (!relatedData) { + throw new QueryDataNotFoundError(NO_QUERY_DATA); + } - return { - ...input, - ...filterOutput(relatedData, {output, query}), - }; - }); - } catch (error) { - throw new InputValidationError(`Error happened while parsing given CSV file: ${filepath} -${error}`); - } + return { + ...input, + ...filterOutput(relatedData, {output, query}), + }; + }); }; /** @@ -202,7 +224,7 @@ ${error}`); */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ From 9b3ea3ee924677649d3548307f452dbab7ac0d6f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:57:03 +0400 Subject: [PATCH 039/863] feat(builtins): update errors usage coefficient --- src/builtins/coefficient/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts index 627e5f64e..c049911ae 100644 --- a/src/builtins/coefficient/index.ts +++ b/src/builtins/coefficient/index.ts @@ -5,9 +5,12 @@ import {ExecutePlugin, PluginParams} from '../../types/interface'; import {validate} from '../../util/validations'; import {ERRORS} from '../../util/errors'; +import {STRINGS} from '../../config'; + import {CoefficientConfig} from './types'; -const {ConfigNotFoundError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { const metadata = { @@ -45,7 +48,7 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ From f088869822856a27c4873dbe1ccbb3b49a4fa738 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:57:37 +0400 Subject: [PATCH 040/863] feat(builtins): update errors usage time-sync --- src/builtins/time-sync.ts | 57 ++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/builtins/time-sync.ts b/src/builtins/time-sync.ts index 67d5c9079..469fdec35 100644 --- a/src/builtins/time-sync.ts +++ b/src/builtins/time-sync.ts @@ -5,6 +5,7 @@ import {z} from 'zod'; import {parameterize} from '../lib/parameterize'; import {ERRORS} from '../util/errors'; +import {validate} from '../util/validations'; import {STRINGS} from '../config'; @@ -14,16 +15,24 @@ import { TimeNormalizerConfig, TimeParams, } from '../types/time-sync'; -import {validate} from '../util/validations'; Settings.defaultZone = 'utc'; -const {InputValidationError} = ERRORS; +const { + GlobalConfigError, + InvalidDateInInputError, + InvalidPaddingError, + InvalidInputError, +} = ERRORS; const { INVALID_TIME_NORMALIZATION, INVALID_OBSERVATION_OVERLAP, AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, + START_LOWER_END, + TIMESTAMP_REQUIRED, + INVALID_DATETIME, } = STRINGS; export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { @@ -64,7 +73,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { seconds: previousInput.duration, }) > currentMoment ) { - throw new InputValidationError(INVALID_OBSERVATION_OVERLAP); + throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); } const compareableTime = previousInputTimestamp.plus({ @@ -106,19 +115,22 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { }; const parseDate = (date: Date | string) => { - if (!date) return DateTime.invalid('Invalid date'); + if (!date) { + return DateTime.invalid('Invalid date'); + } + // dates are passed to time-sync.ts both in ISO 8601 format // and as a Date object (from the deserialization of a YAML file) // if the YAML parser fails to identify as a date, it passes as a string if (isDate(date)) { return DateTime.fromJSDate(date); } + if (typeof date === 'string') { return DateTime.fromISO(date); } - throw new InputValidationError( - `Unexpected date datatype: ${typeof date}: ${date}` - ); + + throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); }; /** @@ -128,10 +140,10 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const schema = z.object({ timestamp: z .string({ - required_error: `required in input[${index}]`, + required_error: TIMESTAMP_REQUIRED(index), }) .datetime({ - message: `invalid datetime in input[${index}]`, + message: INVALID_DATETIME(index), }) .or(z.date()), duration: z.number(), @@ -145,7 +157,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (globalConfig === undefined) { - throw new InputValidationError(INVALID_TIME_NORMALIZATION); + throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); } const schema = z @@ -156,7 +168,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { 'allow-padding': z.boolean(), }) .refine(data => data['start-time'] < data['end-time'], { - message: '`start-time` should be lower than `end-time`', + message: START_LOWER_END, }); return validate>(schema, globalConfig); @@ -176,8 +188,10 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { i: number ) => { const thisMoment = parseDate(currentRoundMoment).startOf('second'); + return thisMoment.plus({seconds: i}); }; + /** * Breaks down input per minimal time unit. */ @@ -259,8 +273,9 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { const {start, end} = pad; const isPaddingNeeded = start || end; + if (!params.allowPadding && isPaddingNeeded) { - throw new InputValidationError(AVOIDING_PADDING_BY_EDGES(start, end)); + throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); } }; @@ -292,8 +307,8 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. * For methods is `avg` and `none` calculating average of the frame. */ - const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => { - return inputsInTimeslot.reduce((acc, input, index, inputs) => { + const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => + inputsInTimeslot.reduce((acc, input, index, inputs) => { const metrics = Object.keys(input); metrics.forEach(metric => { @@ -336,13 +351,12 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, {} as PluginParams); - }; /** * Takes each array frame with interval length, then aggregating them together as from units.yaml file. */ - const resampleInputs = (inputs: PluginParams[], params: TimeParams) => { - return inputs.reduce((acc: PluginParams[], _input, index, inputs) => { + const resampleInputs = (inputs: PluginParams[], params: TimeParams) => + inputs.reduce((acc: PluginParams[], _input, index, inputs) => { const frameStart = index * params.interval; const frameEnd = (index + 1) * params.interval; const inputsFrame = inputs.slice(frameStart, frameEnd); @@ -356,7 +370,6 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, [] as PluginParams[]); - }; /** * Pads zeroish inputs from the beginning or at the end of the inputs if needed. @@ -394,6 +407,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) ); } + return paddedArray; }; @@ -404,6 +418,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) => { const array: PluginParams[] = []; const dateRange = Interval.fromDateTimes(startDate, endDate); + for (const interval of dateRange.splitBy({second: 1})) { array.push( fillWithZeroishInput( @@ -415,6 +430,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) ); } + return array; }; @@ -424,8 +440,8 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const trimInputsByGlobalTimeline = ( inputs: PluginParams[], params: TimeParams - ): PluginParams[] => { - return inputs.reduce((acc: PluginParams[], item) => { + ): PluginParams[] => + inputs.reduce((acc: PluginParams[], item) => { const {timestamp} = item; if ( @@ -437,7 +453,6 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, [] as PluginParams[]); - }; return {metadata, execute}; }; From b34df91e030b646e99e7a41fe9bc2f072a3bf233 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:57:52 +0400 Subject: [PATCH 041/863] feat(builtins): update errors usage group-by --- src/builtins/group-by.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builtins/group-by.ts b/src/builtins/group-by.ts index 6a7036adf..e4e8af958 100644 --- a/src/builtins/group-by.ts +++ b/src/builtins/group-by.ts @@ -8,9 +8,9 @@ import {GroupByConfig} from '../types/group-by'; import {ERRORS} from '../util/errors'; import {validate} from '../util/validations'; -const {InvalidGroupingError, InputValidationError} = ERRORS; +const {InvalidGroupingError, GlobalConfigError} = ERRORS; -const {INVALID_GROUP_BY} = STRINGS; +const {INVALID_GROUP_BY, MISSING_GLOBAL_CONFIG} = STRINGS; /** * Plugin for inputs grouping. @@ -79,7 +79,7 @@ export const GroupBy = (): GroupByPlugin => { */ const validateConfig = (config: GroupByConfig) => { if (!config) { - throw new InputValidationError('Config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z.object({ From 93adf7146ada5be7c7af1b982edc1c9450c9afbb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:58:03 +0400 Subject: [PATCH 042/863] feat(builtins): update errors usage export yaml --- src/builtins/export-yaml.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts index e242bbcc2..d4f71c3f5 100644 --- a/src/builtins/export-yaml.ts +++ b/src/builtins/export-yaml.ts @@ -1,9 +1,12 @@ import {saveYamlFileAs} from '../util/yaml'; import {ERRORS} from '../util/errors'; +import {STRINGS} from '../config'; + import {Context} from '../types/manifest'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED} = STRINGS; export const ExportYaml = () => { /** Takes string before hashtag. */ @@ -14,7 +17,7 @@ export const ExportYaml = () => { */ const execute = async (tree: any, context: Context, outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } const outputFile = { From b6d9b20e570d234572eaa6819acd6a35e9ddbc61 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:58:08 +0400 Subject: [PATCH 043/863] feat(builtins): update errors usage export csv --- src/builtins/export-csv.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts index efd2cc3cb..b0f4f80e8 100644 --- a/src/builtins/export-csv.ts +++ b/src/builtins/export-csv.ts @@ -3,10 +3,13 @@ import {stringify} from 'csv-stringify/sync'; import {ERRORS} from '../util/errors'; +import {STRINGS} from '../config'; + import {Context} from '../types/manifest'; import {PluginParams} from '../types/interface'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {CSV_EXPORT, OUTPUT_REQUIRED} = STRINGS; /** * Extension to IF that outputs the tree in a CSV format. @@ -16,15 +19,14 @@ export const ExportCSV = () => { const validatedPath = validateOutputPath(outputPath); const paths = validatedPath.split('#'); - const output = paths.slice(0, paths.length - 1).join(''); const criteria = paths[paths.length - 1]; if (paths.length <= 1 || !criteria) { - throw new ExhaustError( - 'CSV export criteria is not found in output path. Please append it after --output #.' - ); + throw new ExhaustOutputArgError(CSV_EXPORT); } + const output = paths.slice(0, paths.length - 1).join(''); + return { output, criteria, @@ -36,11 +38,7 @@ export const ExportCSV = () => { */ const validateOutputPath = (outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); - } - - if (!outputPath.includes('#')) { - throw new ExhaustError('Output path should contain `#`.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } return outputPath; From 19f1eeccb9585d698b2f6c769a19816676dbb489 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:58:14 +0400 Subject: [PATCH 044/863] feat(builtins): update errors usage export csv raw --- src/builtins/export-csv-raw.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts index 429d99c85..429990902 100644 --- a/src/builtins/export-csv-raw.ts +++ b/src/builtins/export-csv-raw.ts @@ -2,10 +2,13 @@ import * as fs from 'fs/promises'; import {ERRORS} from '../util/errors'; +import {STRINGS} from '../config'; + import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError, WriteFileError} = ERRORS; +const {OUTPUT_REQUIRED, WRITE_CSV_ERROR} = STRINGS; export const ExportCSVRaw = (): ExhaustPluginInterface => { /** @@ -127,7 +130,7 @@ export const ExportCSVRaw = (): ExhaustPluginInterface => { try { await fs.writeFile(`${outputPath}.csv`, content); } catch (error) { - throw new ExhaustError(`Failed to write CSV to ${outputPath}: ${error}`); + throw new WriteFileError(WRITE_CSV_ERROR(outputPath, error)); } }; @@ -136,7 +139,7 @@ export const ExportCSVRaw = (): ExhaustPluginInterface => { */ const execute = async (tree: any, _context: Context, outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } const [extractredFlatMap, extractedHeaders] = From cfc89dbec2bad8aaa656faaf1d62114b3edf89ef Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:58:45 +0400 Subject: [PATCH 045/863] test(util): migrate tests to use new errors --- src/__tests__/unit/util/aggregation-helper.test.ts | 11 ++++++----- src/__tests__/unit/util/args.test.ts | 10 +++++----- src/__tests__/unit/util/plugin-storage.test.ts | 6 +++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts index 20690bc2f..7cccbfccc 100644 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ b/src/__tests__/unit/util/aggregation-helper.test.ts @@ -5,7 +5,7 @@ import {STRINGS} from '../../../config'; import {PluginParams} from '../../../types/interface'; -const {InvalidAggregationParamsError} = ERRORS; +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; describe('util/aggregation-helper: ', () => { @@ -20,9 +20,9 @@ describe('util/aggregation-helper: ', () => { try { aggregateInputsIntoOne(inputs, metrics, isTemporal); } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationParamsError); + expect(error).toBeInstanceOf(InvalidAggregationMethodError); - if (error instanceof InvalidAggregationParamsError) { + if (error instanceof InvalidAggregationMethodError) { expect(error.message).toEqual(INVALID_AGGREGATION_METHOD(metrics[0])); } } @@ -38,9 +38,10 @@ describe('util/aggregation-helper: ', () => { try { aggregateInputsIntoOne(inputs, metrics, isTemporal); } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationParamsError); + console.log(error); + expect(error).toBeInstanceOf(MissingAggregationParamError); - if (error instanceof InvalidAggregationParamsError) { + if (error instanceof MissingAggregationParamError) { expect(error.message).toEqual(METRIC_MISSING(metrics[0], 0)); } } diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index d40d36cae..7da9efa37 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -76,7 +76,7 @@ import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; -const {CliInputError} = ERRORS; +const {CliInputError, CliSourceFileError} = ERRORS; const { MANIFEST_IS_MISSING, @@ -115,8 +115,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(MANIFEST_IS_MISSING)); + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(MANIFEST_IS_MISSING)); } }); @@ -195,8 +195,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(FILE_IS_NOT_YAML)); + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(FILE_IS_NOT_YAML)); } }); diff --git a/src/__tests__/unit/util/plugin-storage.test.ts b/src/__tests__/unit/util/plugin-storage.test.ts index b2bd25011..f8ac5b631 100644 --- a/src/__tests__/unit/util/plugin-storage.test.ts +++ b/src/__tests__/unit/util/plugin-storage.test.ts @@ -1,7 +1,7 @@ import {pluginStorage} from '../../../util/plugin-storage'; import {ERRORS} from '../../../util/errors'; -const {PluginInitalizationError} = ERRORS; +const {PluginInitializationError} = ERRORS; describe('util/pluginStorage: ', () => { describe('pluginStorage(): ', () => { @@ -30,9 +30,9 @@ describe('util/pluginStorage: ', () => { try { storage.get(pluginName); } catch (error) { - expect(error).toBeInstanceOf(PluginInitalizationError); + expect(error).toBeInstanceOf(PluginInitializationError); - if (error instanceof PluginInitalizationError) { + if (error instanceof PluginInitializationError) { expect(error.message).toEqual; } } From fe46a8d6542bddb9ec8419c57f881c652cba9958 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:58:56 +0400 Subject: [PATCH 046/863] test(lib): migrate tests to use new errors --- src/__tests__/unit/lib/exhaust.test.ts | 22 +++++++--------- src/__tests__/unit/lib/initialize.test.ts | 32 ++++++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index 97db0b9dc..a1f46595a 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -7,8 +7,8 @@ import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; -const {ExhaustError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN} = STRINGS; +const {ExhaustOutputArgError, InvalidExhaustPluginError} = ERRORS; +const {INVALID_EXHAUST_PLUGIN, OUTPUT_REQUIRED} = STRINGS; describe('lib/exhaust: ', () => { describe('exhaust(): ', () => { @@ -50,7 +50,6 @@ describe('lib/exhaust: ', () => { outputs: ['yaml'], }, }; - const expectedMessage = 'Output path is required.'; expect.assertions(2); @@ -58,10 +57,10 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {}); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); + expect(error).toBeInstanceOf(ExhaustOutputArgError); - if (error instanceof ExhaustError) { - expect(error.message).toEqual(expectedMessage); + if (error instanceof ExhaustOutputArgError) { + expect(error.message).toEqual(OUTPUT_REQUIRED); } } }); @@ -73,9 +72,6 @@ describe('lib/exhaust: ', () => { outputs: ['mock'], }, }; - const expectedMessage = INVALID_EXHAUST_PLUGIN( - context.initialize.outputs[0] - ); expect.assertions(2); @@ -83,10 +79,12 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {}); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); + expect(error).toBeInstanceOf(InvalidExhaustPluginError); - if (error instanceof ExhaustError) { - expect(error.message).toEqual(expectedMessage); + if (error instanceof InvalidExhaustPluginError) { + expect(error.message).toEqual( + INVALID_EXHAUST_PLUGIN(context.initialize.outputs[0]) + ); } } }); diff --git a/src/__tests__/unit/lib/initialize.test.ts b/src/__tests__/unit/lib/initialize.test.ts index ad5541684..23ca27171 100644 --- a/src/__tests__/unit/lib/initialize.test.ts +++ b/src/__tests__/unit/lib/initialize.test.ts @@ -18,7 +18,11 @@ import {STRINGS} from '../../../config'; import {GlobalPlugins} from '../../../types/manifest'; -const {PluginCredentialError, ModuleInitializationError} = ERRORS; +const { + MissingPluginPathError, + MissingPluginMethodError, + PluginInitializationError, +} = ERRORS; const {MISSING_METHOD, MISSING_PATH, INVALID_MODULE_PATH} = STRINGS; describe('lib/initalize: ', () => { @@ -81,9 +85,9 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); } catch (error) { - expect(error).toBeInstanceOf(PluginCredentialError); + expect(error).toBeInstanceOf(MissingPluginPathError); - if (error instanceof PluginCredentialError) { + if (error instanceof MissingPluginPathError) { expect(error.message).toEqual(MISSING_PATH); } } @@ -103,9 +107,9 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); } catch (error) { - expect(error).toBeInstanceOf(PluginCredentialError); + expect(error).toBeInstanceOf(MissingPluginMethodError); - if (error instanceof PluginCredentialError) { + if (error instanceof MissingPluginMethodError) { expect(error.message).toEqual(MISSING_METHOD); } } @@ -160,14 +164,16 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); - } catch (error) { - expect(error).toBeInstanceOf(ModuleInitializationError); - - if (error instanceof ModuleInitializationError) { - expect(error.message).toEqual( - INVALID_MODULE_PATH(plugins.mockavizta.path) - ); - } + } catch (error: any) { + expect(error).toBeInstanceOf(PluginInitializationError); + expect(error.message).toEqual( + INVALID_MODULE_PATH( + plugins.mockavizta.path, + new Error( + "Cannot find module 'failing-mock' from 'src/lib/initialize.ts'" + ) + ) + ); } }); }); From 6cca843d563fb7c3241d4704d43321a5e781d831 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:59:14 +0400 Subject: [PATCH 047/863] test(config): drop strings tests --- src/__tests__/unit/config/strings.test.ts | 171 ---------------------- 1 file changed, 171 deletions(-) delete mode 100644 src/__tests__/unit/config/strings.test.ts diff --git a/src/__tests__/unit/config/strings.test.ts b/src/__tests__/unit/config/strings.test.ts deleted file mode 100644 index bdc1f871f..000000000 --- a/src/__tests__/unit/config/strings.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import {STRINGS} from '../../../config/strings'; - -const { - NOT_NATIVE_PLUGIN, - INVALID_MODULE_PATH, - INVALID_AGGREGATION_METHOD, - METRIC_MISSING, - AVOIDING_PADDING, - AVOIDING_PADDING_BY_EDGES, - INVALID_GROUP_BY, - REJECTING_OVERRIDE, - INVALID_EXHAUST_PLUGIN, - UNKNOWN_PARAM, - NOT_INITALIZED_PLUGIN, -} = STRINGS; - -describe('config/strings: ', () => { - describe('NOT_NATIVE_PLUGIN(): ', () => { - it('successfully injects path into message.', () => { - const path = 'mock/path'; - const expectedMessage = ` -You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`; - - expect(NOT_NATIVE_PLUGIN(path)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_MODULE_PATH(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Provided module: '${param}' is invalid or not found.`; - - expect(INVALID_MODULE_PATH(param)).toEqual(expectedMessage); - }); - }); - - describe('AVOIDING_PADDING(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Avoiding padding at ${param}`; - - expect(AVOIDING_PADDING(param)).toEqual(expectedMessage); - }); - }); - - describe('AVOIDING_PADDING_BY_EDGES(): ', () => { - it('successfully appends given start and end params.', () => { - const start = true; - const end = true; - - const expectedMessage = 'Avoiding padding at start and end'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - - it('successfully appends given start param.', () => { - const start = true; - const end = false; - - const expectedMessage = 'Avoiding padding at start'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - - it('successfully appends given end param.', () => { - const start = false; - const end = true; - - const expectedMessage = 'Avoiding padding at end'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_AGGREGATION_METHOD(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Aggregation is not possible for given ${param} since method is 'none'.`; - - expect(INVALID_AGGREGATION_METHOD(param)).toEqual(expectedMessage); - }); - }); - - describe('METRIC_MISSING(): ', () => { - it('successfully appends given param to message.', () => { - const metric = 'mock-metric'; - const index = 0; - - const expectedMessage = `Aggregation metric ${metric} is not found in inputs[${index}].`; - - expect(METRIC_MISSING(metric, index)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_GROUP_BY(): ', () => { - it('injects type in given message.', () => { - const type = 'mock-type'; - const message = `Invalid group ${type}.`; - - expect(INVALID_GROUP_BY(type)).toEqual(message); - }); - }); - - describe('REJECTING_OVERRIDE(): ', () => { - it('inejcts param name into message.', () => { - const param: any = { - name: 'mock-name', - description: 'mock-description', - aggregation: 'sum', - unit: 'mock-unit', - }; - - expect(REJECTING_OVERRIDE(param)); - }); - }); - - describe('INVALID_EXHAUST_PLUGIN(): ', () => { - it('injects plugin name into message.', () => { - const pluginName = 'mock-plugin'; - const message = `Invalid exhaust plugin: ${pluginName}.`; - - expect(INVALID_EXHAUST_PLUGIN(pluginName)).toEqual(message); - }); - }); - - describe('AVOIDING_PADDING(): ', () => { - it('successfully appends given param to message.', () => { - const description_suffix = 'pad description'; - - const expectedMessage = `Avoiding padding at ${description_suffix}`; - - expect(AVOIDING_PADDING(description_suffix)).toEqual(expectedMessage); - }); - }); - - describe('UNKNOWN_PARAM(): ', () => { - it('injects name into message.', () => { - const name = 'mock-name'; - const message = `Unknown parameter: ${name}. Using 'sum' aggregation method.`; - - expect(UNKNOWN_PARAM(name)).toEqual(message); - }); - }); - - describe('NOT_INITALIZED_PLUGIN(): ', () => { - it('injects name into message.', () => { - const name = 'mock-name'; - const message = `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`; - - expect(NOT_INITALIZED_PLUGIN(name)).toEqual(message); - }); - }); - - describe('AVOIDING_PADDING_BY_EDGES(): ', () => { - it('successfully combines boolean params into a description.', () => { - let description_suffix = 'start and end'; - let expectedMessage = `Avoiding padding at ${description_suffix}`; - - expect(AVOIDING_PADDING_BY_EDGES(true, true)).toEqual(expectedMessage); - description_suffix = 'start'; - expectedMessage = `Avoiding padding at ${description_suffix}`; - expect(AVOIDING_PADDING_BY_EDGES(true, false)).toEqual(expectedMessage); - description_suffix = 'end'; - expectedMessage = `Avoiding padding at ${description_suffix}`; - expect(AVOIDING_PADDING_BY_EDGES(false, true)).toEqual(expectedMessage); - }); - }); -}); From 55a9060ae3e0a065ebba2407246776ae40041a2d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 16:59:44 +0400 Subject: [PATCH 048/863] test(builtins): migrate tests to use updated error pattern --- .../unit/builtins/CommonGenerator.test.ts | 18 +++---- .../unit/builtins/RandIntGenerator.test.ts | 25 +++------ .../unit/builtins/coefficient.test.ts | 10 ++-- src/__tests__/unit/builtins/divide.test.ts | 17 +++--- src/__tests__/unit/builtins/exponent.test.ts | 30 +++++------ .../unit/builtins/export-csv-raw.test.ts | 18 ++++--- .../unit/builtins/export-csv.test.ts | 23 ++++---- .../unit/builtins/export-yaml.test.ts | 9 ++-- src/__tests__/unit/builtins/group-by.test.ts | 13 ++--- .../unit/builtins/interpolation.test.ts | 34 ++++++------ .../unit/builtins/mock-observations.test.ts | 14 ++--- src/__tests__/unit/builtins/multiply.test.ts | 11 ++-- src/__tests__/unit/builtins/regex.test.ts | 20 ++++--- .../unit/builtins/sci-embodied.test.ts | 25 ++++++--- src/__tests__/unit/builtins/sci.test.ts | 8 +-- src/__tests__/unit/builtins/shell.test.ts | 8 +-- src/__tests__/unit/builtins/subtract.test.ts | 9 ++-- src/__tests__/unit/builtins/sum.test.ts | 15 +++--- src/__tests__/unit/builtins/time-sync.test.ts | 52 ++++++++++++------- 19 files changed, 189 insertions(+), 170 deletions(-) diff --git a/src/__tests__/unit/builtins/CommonGenerator.test.ts b/src/__tests__/unit/builtins/CommonGenerator.test.ts index 881aa810e..d4d1bdac9 100644 --- a/src/__tests__/unit/builtins/CommonGenerator.test.ts +++ b/src/__tests__/unit/builtins/CommonGenerator.test.ts @@ -1,12 +1,12 @@ -import {KeyValuePair} from '../../../types/common'; - import {ERRORS} from '../../../util/errors'; import {CommonGenerator} from '../../../builtins/mock-observations/helpers/common-generator'; +import {STRINGS} from '../../../config'; -const {InputValidationError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; -describe('lib/mock-observations/CommonGenerator: ', () => { +describe('builtins/mock-observations/CommonGenerator: ', () => { describe('initialize: ', () => { it('throws an error when config is not empty object.', async () => { const commonGenerator = CommonGenerator({}); @@ -16,18 +16,14 @@ describe('lib/mock-observations/CommonGenerator: ', () => { try { commonGenerator.next([]); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'CommonGenerator: Config must not be null or empty.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); }); describe('next(): ', () => { it('returns a result with valid data.', async () => { - const config: KeyValuePair = { + const config: Record = { key1: 'value1', key2: 'value2', }; @@ -35,7 +31,7 @@ describe('lib/mock-observations/CommonGenerator: ', () => { expect.assertions(1); - expect(commonGenerator.next([])).toStrictEqual({ + expect(commonGenerator.next([])).toEqual({ key1: 'value1', key2: 'value2', }); diff --git a/src/__tests__/unit/builtins/RandIntGenerator.test.ts b/src/__tests__/unit/builtins/RandIntGenerator.test.ts index c904f7350..1d2969695 100644 --- a/src/__tests__/unit/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/unit/builtins/RandIntGenerator.test.ts @@ -4,20 +4,19 @@ import {ERRORS} from '../../../util/errors'; import {RandIntGenerator} from '../../../builtins/mock-observations/helpers/rand-int-generator'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; -describe('lib/mock-observations/RandIntGenerator: ', () => { +const {GlobalConfigError} = ERRORS; +const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/mock-observations/RandIntGenerator: ', () => { describe('initialize', () => { it('throws an error when the generator name is empty string.', async () => { expect.assertions(1); try { RandIntGenerator('', {}); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: `name` is empty or all spaces.' - ) - ); + expect(error).toEqual(new GlobalConfigError(INVALID_NAME)); } }); @@ -26,11 +25,7 @@ describe('lib/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('generator-name', {}); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: Config must not be null or empty.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -42,11 +37,7 @@ describe('lib/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('random', config); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: Config is missing min or max.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_MIN_MAX)); } }); }); diff --git a/src/__tests__/unit/builtins/coefficient.test.ts b/src/__tests__/unit/builtins/coefficient.test.ts index bf7455679..44595d774 100644 --- a/src/__tests__/unit/builtins/coefficient.test.ts +++ b/src/__tests__/unit/builtins/coefficient.test.ts @@ -2,7 +2,10 @@ import {Coefficient} from '../../../builtins/coefficient'; import {ERRORS} from '../../../util/errors'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { describe('Coefficient: ', () => { @@ -49,7 +52,6 @@ describe('builtins/coefficient: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; const coefficient = Coefficient(config!); - const expectedMessage = 'Global config is not provided.'; expect.assertions(1); @@ -62,7 +64,9 @@ describe('builtins/coefficient: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts index 8f56bb19d..9c794dae6 100644 --- a/src/__tests__/unit/builtins/divide.test.ts +++ b/src/__tests__/unit/builtins/divide.test.ts @@ -1,8 +1,10 @@ import {Divide} from '../../../builtins'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { describe('Divide: ', () => { @@ -103,7 +105,6 @@ describe('builtins/divide: ', () => { }); it('throws an error on missing global config.', async () => { - const expectedMessage = 'Global config is not provided.'; const config = undefined; const divide = Divide(config!); @@ -117,7 +118,9 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); @@ -148,8 +151,6 @@ describe('builtins/divide: ', () => { }); it('throws an error when `denominator` is string.', async () => { - const expectedMessage = '`10` is missing from the input.'; - const globalConfig = { numerator: 'vcpus-allocated', denominator: '10', @@ -168,7 +169,11 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(expectedMessage)); + expect(error).toStrictEqual( + new MissingInputDataError( + MISSING_INPUT_DATA(globalConfig.denominator) + ) + ); } }); }); diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts index 54c69ffcb..6034fd3bd 100644 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ b/src/__tests__/unit/builtins/exponent.test.ts @@ -1,10 +1,12 @@ import {Exponent} from '../../../builtins/exponent'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError} = ERRORS; +const {InputValidationError, MissingInputDataError} = ERRORS; +const {NOT_NUMERIC_VALUE, MISSING_INPUT_DATA} = STRINGS; -describe('lib/exponent: ', () => { +describe('builtins/exponent: ', () => { describe('Exponent: ', () => { const globalConfig = { 'input-parameter': 'energy/base', @@ -45,9 +47,6 @@ describe('lib/exponent: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Exponent: energy/base is missing from the input array.'; - expect.assertions(1); try { @@ -59,27 +58,26 @@ describe('lib/exponent: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new MissingInputDataError(MISSING_INPUT_DATA('energy/base')) ); } }); it('throws an error on input param value not numeric.', async () => { - const expectedMessage = 'Exponent: i-am-not-a-number is not numeric.'; - expect.assertions(1); + const input = [ + { + duration: 3600, + 'energy/base': 'i-am-not-a-number', + timestamp: '2021-01-01T00:00:00Z', + }, + ]; try { - await exponent.execute([ - { - duration: 3600, - 'energy/base': 'i-am-not-a-number', - timestamp: '2021-01-01T00:00:00Z', - }, - ]); + await exponent.execute(input); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError(NOT_NUMERIC_VALUE(input[0]['energy/base'])) ); } }); diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts index 1ebf9e45e..a66a24ac2 100644 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ b/src/__tests__/unit/builtins/export-csv-raw.test.ts @@ -4,9 +4,12 @@ import {jest} from '@jest/globals'; import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; + import {tree, context, outputs} from '../../../__mocks__/builtins/export-csv'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {WRITE_CSV_ERROR, OUTPUT_REQUIRED} = STRINGS; jest.mock('fs/promises', () => ({ __esModule: true, @@ -40,18 +43,17 @@ describe('builtins/export-csv-raw: ', () => { it('throws an error when the CSV file could not be created.', async () => { const outputPath = 'output#carbon'; + const expectedMessage = 'Could not write CSV file.'; expect.assertions(1); - jest - .spyOn(fs, 'writeFile') - .mockRejectedValue('Could not write CSV file.'); + jest.spyOn(fs, 'writeFile').mockRejectedValue(expectedMessage); await expect( exportCSVRaw.execute(tree, context, outputPath) ).rejects.toThrow( - new ExhaustError( - 'Failed to write CSV to output#carbon: Could not write CSV file.' + new ExhaustOutputArgError( + WRITE_CSV_ERROR(outputPath, expectedMessage) ) ); }); @@ -65,8 +67,8 @@ describe('builtins/export-csv-raw: ', () => { try { await exportCSVRaw.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); }); diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts index 94414a970..09fd4e737 100644 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ b/src/__tests__/unit/builtins/export-csv.test.ts @@ -5,6 +5,8 @@ import {jest} from '@jest/globals'; import {ExportCSV} from '../../../builtins/export-csv'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; + import { tree, context, @@ -13,7 +15,8 @@ import { aggregation, } from '../../../__mocks__/builtins/export-csv'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED, CSV_EXPORT} = STRINGS; jest.mock('fs/promises', () => ({ writeFile: jest.fn<() => Promise>().mockResolvedValue(), @@ -197,8 +200,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); @@ -210,10 +213,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual( - new ExhaustError('Output path should contain `#`.') - ); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); } }); @@ -225,12 +226,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual( - new ExhaustError( - 'CSV export criteria is not found in output path. Please append it after --output #.' - ) - ); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); } }); }); diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts index a2157e4ef..f17b9154e 100644 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ b/src/__tests__/unit/builtins/export-yaml.test.ts @@ -2,13 +2,16 @@ import {ExportYaml} from '../../../builtins/export-yaml'; import {ERRORS} from '../../../util/errors'; import {saveYamlFileAs} from '../../../util/yaml'; +import {STRINGS} from '../../../config'; + import {tree, context} from '../../../__mocks__/builtins/export-csv'; jest.mock('../../../util/yaml', () => ({ saveYamlFileAs: jest.fn(), })); -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED} = STRINGS; describe('builtins/export-yaml: ', () => { describe('ExportYaml: ', () => { @@ -38,8 +41,8 @@ describe('builtins/export-yaml: ', () => { try { await exportYaml.execute({}, context, ''); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); }); diff --git a/src/__tests__/unit/builtins/group-by.test.ts b/src/__tests__/unit/builtins/group-by.test.ts index 9c99ee700..b472125d1 100644 --- a/src/__tests__/unit/builtins/group-by.test.ts +++ b/src/__tests__/unit/builtins/group-by.test.ts @@ -1,7 +1,10 @@ import {GroupBy} from '../../../builtins/group-by'; import {ERRORS} from '../../../util/errors'; -const {InvalidGroupingError, InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {InvalidGroupingError, InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, INVALID_GROUP_BY} = STRINGS; describe('builtins/group-by: ', () => { describe('GroupBy: ', () => { @@ -92,10 +95,8 @@ describe('builtins/group-by: ', () => { try { plugin.execute(inputs, config!); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError('Config is not provided.') - ); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -166,7 +167,7 @@ describe('builtins/group-by: ', () => { } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( - new InvalidGroupingError('Invalid group unknown.') + new InvalidGroupingError(INVALID_GROUP_BY(config.group[2])) ); } }); diff --git a/src/__tests__/unit/builtins/interpolation.test.ts b/src/__tests__/unit/builtins/interpolation.test.ts index c4bba939f..54dd2dab7 100644 --- a/src/__tests__/unit/builtins/interpolation.test.ts +++ b/src/__tests__/unit/builtins/interpolation.test.ts @@ -1,8 +1,16 @@ import {Interpolation} from '../../../builtins'; -import {Method} from '../../../builtins/interpolation/types'; import {ERRORS} from '../../../util/errors'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +import {Method} from '../../../builtins/interpolation/types'; +import {STRINGS} from '../../../config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + WITHIN_THE_RANGE, + ARRAY_LENGTH_NON_EMPTY, + X_Y_EQUAL, +} = STRINGS; describe('builtins/interpolation: ', () => { describe('Interpolation: ', () => { @@ -144,10 +152,8 @@ describe('builtins/interpolation: ', () => { try { plugin.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(ConfigNotFoundError); - expect(error).toEqual( - new ConfigNotFoundError('Global config is not provided.') - ); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -163,11 +169,7 @@ describe('builtins/interpolation: ', () => { plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - 'The length of `x` and `y` should be equal' - ) - ); + expect(error).toEqual(new InputValidationError(X_Y_EQUAL)); } }); @@ -184,11 +186,7 @@ describe('builtins/interpolation: ', () => { plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - 'The target x value must be within the range of the given x values' - ) - ); + expect(error).toEqual(new InputValidationError(WITHIN_THE_RANGE)); } }); it('throws an error when the the length of the input arrays is <2', () => { @@ -213,9 +211,7 @@ describe('builtins/interpolation: ', () => { } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( - new InputValidationError( - 'the length of the input arrays must be greater than 1' - ) + new InputValidationError(ARRAY_LENGTH_NON_EMPTY) ); } }); diff --git a/src/__tests__/unit/builtins/mock-observations.test.ts b/src/__tests__/unit/builtins/mock-observations.test.ts index 37d3a04b4..3e2ddab5b 100644 --- a/src/__tests__/unit/builtins/mock-observations.test.ts +++ b/src/__tests__/unit/builtins/mock-observations.test.ts @@ -1,10 +1,12 @@ import {MockObservations} from '../../../builtins/mock-observations'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError} = ERRORS; +const {InputValidationError, GlobalConfigError} = ERRORS; +const {INVALID_MIN_MAX} = STRINGS; -describe('lib/mock-observations: ', () => { +describe('builtins/mock-observations: ', () => { describe('init: ', () => { it('successfully initalized.', () => { const mockObservations = MockObservations({ @@ -88,8 +90,6 @@ describe('lib/mock-observations: ', () => { }); it('throws an error when the `min` is greater then `max` of `randint` config.', async () => { - const errorMessage = - 'RandIntGenerator: Min value should not be greater than or equal to max value of cpu/utilization.'; const config = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', @@ -112,8 +112,10 @@ describe('lib/mock-observations: ', () => { try { await mockObservations.execute([]); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual(new InputValidationError(errorMessage)); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual( + new GlobalConfigError(INVALID_MIN_MAX('cpu/utilization')) + ); } }); diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts index a4451179d..7efceb325 100644 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ b/src/__tests__/unit/builtins/multiply.test.ts @@ -1,10 +1,12 @@ import {Multiply} from '../../../builtins/multiply'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError} = ERRORS; +const {MissingInputDataError} = ERRORS; +const {MISSING_INPUT_DATA} = STRINGS; -describe('lib/multiply: ', () => { +describe('builtins/multiply: ', () => { describe('Multiply: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,9 +50,6 @@ describe('lib/multiply: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Multiply: cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -62,7 +61,7 @@ describe('lib/multiply: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new MissingInputDataError(MISSING_INPUT_DATA('cpu/energy')) ); } }); diff --git a/src/__tests__/unit/builtins/regex.test.ts b/src/__tests__/unit/builtins/regex.test.ts index 19ccdf89d..462faad8f 100644 --- a/src/__tests__/unit/builtins/regex.test.ts +++ b/src/__tests__/unit/builtins/regex.test.ts @@ -1,10 +1,12 @@ import {Regex} from '../../../builtins/regex'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigValidationError} = ERRORS; +const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -describe('lib/regex: ', () => { +describe('builtins/regex: ', () => { describe('Regex: ', () => { const globalConfig = { parameter: 'physical-processor', @@ -81,7 +83,6 @@ describe('lib/regex: ', () => { it('throws an error when `parameter` does not match to `match`.', 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'; - const expectedMessage = `Regex: \`${physicalProcessor}\` does not match the /^(^:)+/ regex expression.`; const globalConfig = { parameter: 'physical-processor', @@ -102,14 +103,14 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new RegexMismatchError( + REGEX_MISMATCH(physicalProcessor, '/^(^:)+/') + ) ); } }); it('throws an error on missing global config.', async () => { - const expectedMessage = 'Regex: Configuration data is missing.'; - const config = undefined; const regex = Regex(config!); @@ -124,15 +125,12 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigValidationError(expectedMessage) + new GlobalConfigError(MISSING_GLOBAL_CONFIG) ); } }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Regex: `physical-processor` is missing from the input.'; - expect.assertions(1); try { @@ -144,7 +142,7 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new MissingInputDataError(MISSING_INPUT_DATA('physical-processor')) ); } }); diff --git a/src/__tests__/unit/builtins/sci-embodied.test.ts b/src/__tests__/unit/builtins/sci-embodied.test.ts index 75f9f12fd..4b9f88deb 100644 --- a/src/__tests__/unit/builtins/sci-embodied.test.ts +++ b/src/__tests__/unit/builtins/sci-embodied.test.ts @@ -1,9 +1,12 @@ import {SciEmbodied} from '../../../builtins/sci-embodied'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; + const {InputValidationError} = ERRORS; +const {SCI_EMBODIED_ERROR} = STRINGS; -describe('lib/sci-embodied:', () => { +describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { const sciEmbodied = SciEmbodied(); @@ -191,8 +194,6 @@ describe('lib/sci-embodied:', () => { }); it('throws an error when `device/emissions-embodied` is string.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is not a valid number in input. please provide it as `gco2e`. Error code: invalid_union.'; const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -216,7 +217,13 @@ describe('lib/sci-embodied:', () => { try { await sciEmbodied.execute(inputs); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); expect(error).toBeInstanceOf(InputValidationError); } }); @@ -268,8 +275,6 @@ describe('lib/sci-embodied:', () => { }); it('throws an exception on invalid values.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is not a valid number in input. please provide it as `gco2e`. Error code: invalid_union.'; const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -285,8 +290,14 @@ describe('lib/sci-embodied:', () => { try { await sciEmbodied.execute(inputs); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); } }); }); diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts index 2b6261cda..a9401a5a8 100644 --- a/src/__tests__/unit/builtins/sci.test.ts +++ b/src/__tests__/unit/builtins/sci.test.ts @@ -2,9 +2,9 @@ import {Sci} from '../../../builtins/sci'; import {ERRORS} from '../../../util/errors'; -const {InputValidationError} = ERRORS; +const {MissingInputDataError} = ERRORS; -describe('lib/sci:', () => { +describe('builtins/sci:', () => { describe('Sci: ', () => { const sci = Sci({'functional-unit': 'users'}); @@ -113,7 +113,7 @@ describe('lib/sci:', () => { try { await sci.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingInputDataError); } }); @@ -136,7 +136,7 @@ describe('lib/sci:', () => { try { await sci.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingInputDataError); } }); }); diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts index 7f1ffd58c..306dada3c 100644 --- a/src/__tests__/unit/builtins/shell.test.ts +++ b/src/__tests__/unit/builtins/shell.test.ts @@ -5,12 +5,12 @@ import {Shell} from '../../../builtins/shell'; import {ERRORS} from '../../../util/errors'; -const {InputValidationError} = ERRORS; +const {InputValidationError, ProcessExecutionError} = ERRORS; jest.mock('child_process'); jest.mock('js-yaml'); -describe('lib/shell', () => { +describe('builtins/shell', () => { describe('Shell', () => { const shell = Shell({}); @@ -87,9 +87,9 @@ describe('lib/shell', () => { try { await shell.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(ProcessExecutionError); expect(error).toStrictEqual( - new InputValidationError('Could not run the command') + new ProcessExecutionError('Could not run the command') ); } }); diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts index 7ac717142..2179adcd4 100644 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ b/src/__tests__/unit/builtins/subtract.test.ts @@ -1,10 +1,12 @@ import {Subtract} from '../../../builtins/subtract'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; const {InputValidationError} = ERRORS; +const {MISSING_INPUT_DATA} = STRINGS; -describe('lib/subtract: ', () => { +describe('builtins/subtract: ', () => { describe('Subtract: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,9 +50,6 @@ describe('lib/subtract: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Subtract: cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -62,7 +61,7 @@ describe('lib/subtract: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError(MISSING_INPUT_DATA('cpu/energy')) ); } }); diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts index 734ea8db2..e7b515f26 100644 --- a/src/__tests__/unit/builtins/sum.test.ts +++ b/src/__tests__/unit/builtins/sum.test.ts @@ -1,10 +1,12 @@ import {Sum} from '../../../builtins/sum'; import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; -describe('lib/sum: ', () => { +describe('builtins/sum: ', () => { describe('Sum: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,7 +50,6 @@ describe('lib/sum: ', () => { }); it('throws an error when global config is not provided.', () => { - const expectedMessage = 'Global config is not provided.'; const config = undefined; const sum = Sum(config!); @@ -65,13 +66,13 @@ describe('lib/sum: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); it('throws an error on missing params in input.', () => { - const expectedMessage = 'cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -83,7 +84,7 @@ describe('lib/sum: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new MissingInputDataError(MISSING_INPUT_DATA('cpu/energy')) ); } }); diff --git a/src/__tests__/unit/builtins/time-sync.test.ts b/src/__tests__/unit/builtins/time-sync.test.ts index 4839ad6ca..ac627fe02 100644 --- a/src/__tests__/unit/builtins/time-sync.test.ts +++ b/src/__tests__/unit/builtins/time-sync.test.ts @@ -1,11 +1,26 @@ +import {Settings, DateTime} from 'luxon'; + import {TimeSync} from '../../../builtins/time-sync'; + import {ERRORS} from '../../../util/errors'; -import {Settings, DateTime} from 'luxon'; + import {STRINGS} from '../../../config'; -Settings.defaultZone = 'utc'; -const {InputValidationError} = ERRORS; -const {INVALID_OBSERVATION_OVERLAP, INVALID_TIME_NORMALIZATION} = STRINGS; +Settings.defaultZone = 'utc'; +const { + InputValidationError, + InvalidPaddingError, + InvalidDateInInputError, + InvalidInputError, + GlobalConfigError, +} = ERRORS; + +const { + INVALID_OBSERVATION_OVERLAP, + INVALID_TIME_NORMALIZATION, + AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, +} = STRINGS; jest.mock('luxon', () => { const originalModule = jest.requireActual('luxon'); @@ -196,7 +211,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_TIME_NORMALIZATION) + new GlobalConfigError(INVALID_TIME_NORMALIZATION) ); } }); @@ -228,7 +243,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_OBSERVATION_OVERLAP) + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) ); } }); @@ -258,7 +273,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_OBSERVATION_OVERLAP) + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) ); } }); @@ -335,22 +350,23 @@ describe('execute(): ', () => { 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([ - { - timestamp: 45, - duration: 10, - 'cpu/utilization': 10, - }, - ]); + await timeModel.execute(data); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(InvalidDateInInputError); expect(error).toStrictEqual( - new InputValidationError('Unexpected date datatype: number: 45') + new InvalidDateInInputError(INVALID_DATE_TYPE(data[0].timestamp)) ); } }); @@ -675,7 +691,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError('Avoiding padding at start') + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, false)) ); } }); @@ -735,7 +751,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError('Avoiding padding at start and end') + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, true)) ); } }); From 35b7657a032f9c0eb32df1492080488669a5e6e5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 17:00:12 +0400 Subject: [PATCH 049/863] test(builtins): migrate errors, add cases to csv lookup --- .../unit/builtins/csv-lookup.test.ts | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts index 4e16fd9b6..8fbdee401 100644 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ b/src/__tests__/unit/builtins/csv-lookup.test.ts @@ -5,9 +5,19 @@ import AxiosMockAdapter from 'axios-mock-adapter'; import {CSVLookup} from '../../../builtins'; +import {STRINGS} from '../../../config'; + import {ERRORS} from '../../../util/errors'; -const {FileNotFoundError, InputValidationError, ConfigNotFoundError} = ERRORS; +const { + GlobalConfigError, + ReadFileError, + FetchingFileError, + QueryDataNotFoundError, + MissingCSVColumnError, + CSVParseError, +} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { const mock = new AxiosMockAdapter(axios); @@ -131,7 +141,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(ReadFileError); } } }); @@ -160,7 +170,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(ReadFileError); } } }); @@ -192,7 +202,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(FetchingFileError); } } }); @@ -340,11 +350,8 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error.message).toEqual( - `Error happened while parsing given CSV file: ./file.csv -InputValidationError: One or more of the given query parameters are not found in the target CSV file column headers.` - ); + expect(error).toBeInstanceOf(QueryDataNotFoundError); + expect(error.message).toEqual(NO_QUERY_DATA); } } }); @@ -368,8 +375,8 @@ InputValidationError: One or more of the given query parameters are not found in await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(ConfigNotFoundError); - expect(error.message).toEqual('Global config is not provided.'); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error.message).toEqual(MISSING_GLOBAL_CONFIG); } } }); @@ -400,10 +407,9 @@ InputValidationError: One or more of the given query parameters are not found in await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingCSVColumnError); expect(error.message).toEqual( - `Error happened while parsing given CSV file: ./file.csv -InputValidationError: There is no column with name: mock.` + MISSING_CSV_COLUMN(globalConfig.output) ); } } @@ -477,5 +483,33 @@ InputValidationError: There is no column with name: mock.` expect(result).toStrictEqual(expectedResult); }); }); + + it('rejects with CSV parse error', async () => { + process.env.csv = 'fail'; + expect.assertions(1); + const globalConfig = { + filepath: './fail-csv-reader.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: [['gpu-count']], + }; + const csvLookup = CSVLookup(globalConfig); + + try { + await csvLookup.execute([ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(CSVParseError); + } + }); }); }); From efa095ef9765fafaeb2089fa36a021d2516046ed Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 10 Jun 2024 17:00:26 +0400 Subject: [PATCH 050/863] test(mocks): add invalid csv case to fs --- src/__mocks__/fs/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index da8438c8b..ec83ff675 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -28,6 +28,13 @@ export const readFile = async (filePath: string) => { throw new Error('file not found'); } + if (filePath.includes('fail-csv-reader.csv')) { + return ` +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 +16,16,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.4xlarge,EBS-Only,32,32,November 2018,`; + } + /** * Used for csv lookup plugin. */ From 10cf52abd65c2ad22d417bcb2c58d6eb54a1ea3c Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:05:55 +0400 Subject: [PATCH 051/863] fix(src): move template manifest to the top level of the scr folder --- src/{env/template.yml => env-template.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{env/template.yml => env-template.yml} (100%) diff --git a/src/env/template.yml b/src/env-template.yml similarity index 100% rename from src/env/template.yml rename to src/env-template.yml From caf68b1a610b0402fe7ff060407fc6704ebfca87 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:08:52 +0400 Subject: [PATCH 052/863] feat(config): add log strings --- src/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index d0693c120..e0fd5ee42 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -57,4 +57,6 @@ Note that for the '--output' option you also need to define the output type in y INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', MANIFEST_NOT_FOUND: 'Manifest file not found.', + INITIALIZING_PACKAGE_JSON: 'Initializing package.json.', + INSTALLING_NPM_PACKAGES: 'Installing npm packages...', }; From a28f05b20d192000a544bd2a8ded30a81bf4c390 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:19:20 +0400 Subject: [PATCH 053/863] feat(types): add env types --- src/types/if-env.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/types/if-env.ts diff --git a/src/types/if-env.ts b/src/types/if-env.ts new file mode 100644 index 000000000..b8a63f7ef --- /dev/null +++ b/src/types/if-env.ts @@ -0,0 +1,7 @@ +export type EnvironmentOptions = { + folderPath: string; + install: boolean; + dependencies: {[path: string]: string}; +}; + +export type PathWithVersion = {[path: string]: string}; From ec3ce36f7a9913906ae943830016fe2581e9cb91 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:21:18 +0400 Subject: [PATCH 054/863] feat(util): move some env functions into helpers.ts --- src/util/helpers.ts | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 99291f81d..86bcfab96 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,4 +1,5 @@ import * as fs from 'fs/promises'; +import * as path from 'path'; import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; @@ -10,7 +11,8 @@ import {STRINGS} from '../config'; import {Difference} from '../types/lib/compare'; -const {ISSUE_TEMPLATE} = STRINGS; +const {ISSUE_TEMPLATE, INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = + STRINGS; /** * Formats given error according to class instance, scope and message. @@ -196,3 +198,35 @@ export const isFileExists = async (filePath: string) => { return false; } }; + +/** + * Checks if the package.json is exists, if not, inisializes it. + */ +export const initPackageJsonIfNotExists = async (folderPath: string) => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + const isPackageJsonExists = await isFileExists(packageJsonPath); + + if (!isPackageJsonExists) { + logger.info(INITIALIZING_PACKAGE_JSON); + await execPromise('npm init -y', {cwd: folderPath}); + } + + return packageJsonPath; +}; + +/** + * Installs packages from the specified dependencies in the specified folder. + */ +export const installDependencies = async ( + folderPath: string, + dependencies: {[path: string]: string} +) => { + const packages = Object.entries(dependencies).map( + ([dependency, version]) => `${dependency}@${version.replace('^', '')}` + ); + + logger.info(INSTALLING_NPM_PACKAGES); + await execPromise(`npm install ${packages.join(' ')}`, { + cwd: folderPath, + }); +}; From 1f0700e326cd1f50df0c45dba544a1a8963acc41 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:22:56 +0400 Subject: [PATCH 055/863] fix(src): move env to the src folder --- src/{env => }/env.ts | 78 ++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 57 deletions(-) rename src/{env => }/env.ts (69%) diff --git a/src/env/env.ts b/src/env.ts similarity index 69% rename from src/env/env.ts rename to src/env.ts index 0964d095d..94821d466 100644 --- a/src/env/env.ts +++ b/src/env.ts @@ -3,15 +3,17 @@ import * as fs from 'fs/promises'; import * as path from 'path'; -import {execPromise, isFileExists} from '../util/helpers'; -import {parseIfEnvArgs} from '../util/args'; -import {logger} from '../util/logger'; +import {installDependencies, initPackageJsonIfNotExists} from './util/helpers'; +import {parseIfEnvArgs} from './util/args'; +import {logger} from './util/logger'; -import {load} from '../lib/load'; +import {load} from './lib/load'; -import {CONFIG} from '../config'; +import {CONFIG} from './config'; -const packageJson = require('../../package.json'); +import {EnvironmentOptions, PathWithVersion} from './types/if-env'; + +const packageJson = require('../package.json'); const {IF_ENV} = CONFIG; const { @@ -23,12 +25,6 @@ const { const FOLDER_NAME = 'if-environment'; -type EnvironmentOptions = { - folderPath: string; - install: boolean; - dependencies: {[path: string]: string}; -}; - const IfEnv = async () => { const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { @@ -87,13 +83,10 @@ const getOptionsFromArgs = async (commandArgs: { /** * Gets depencecies with versions. */ -const extractPathsWithVersion = ( - plugins: any, - dependencies: string[] -): {[path: string]: string} => { +const extractPathsWithVersion = (plugins: any, dependencies: string[]) => { const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); - const pathsWithVersion: {[path: string]: string} = {}; + const pathsWithVersion: PathWithVersion = {}; uniquePaths.forEach(pluginPath => { const dependency = dependencies.find((dependency: string) => @@ -117,13 +110,13 @@ const extractPathsWithVersion = ( /** * Creates folder if not exists, installs dependencies if required, update depenedencies. */ -async function initializeAndInstallLibs(options: EnvironmentOptions) { +const initializeAndInstallLibs = async (options: EnvironmentOptions) => { try { const {folderPath, install, dependencies} = options; await fs.mkdir(folderPath, {recursive: true}); - const packageJsonPath = await ensurePackageJsonExists(folderPath); + const packageJsonPath = await initPackageJsonIfNotExists(folderPath); if (install) { await installDependencies(folderPath, dependencies); @@ -133,45 +126,15 @@ async function initializeAndInstallLibs(options: EnvironmentOptions) { } catch (error) { console.log(FAILURE_MESSAGE); } -} - -/** - * Checks if the package.json is exists, if not, inisializes it. - */ -async function ensurePackageJsonExists(folderPath: string) { - const packageJsonPath = path.resolve(folderPath, 'package.json'); - const isPackageJsonExists = await isFileExists(packageJsonPath); - - if (!isPackageJsonExists) { - await execPromise('npm init -y', {cwd: folderPath}); - } - - return packageJsonPath; -} - -/** - * Installs packages from the specified dependencies in the specified folder. - */ -async function installDependencies( - folderPath: string, - dependencies: {[path: string]: string} -) { - const packages = Object.entries(dependencies).map( - ([dependency, version]) => `${dependency}@${version.replace('^', '')}` - ); - - await execPromise(`npm install ${packages.join(' ')}`, { - cwd: folderPath, - }); -} +}; /** * Updates package.json dependencies. */ -async function updatePackageJsonDependencies( +const updatePackageJsonDependencies = async ( packageJsonPath: string, - dependencies: {[path: string]: string} -) { + dependencies: PathWithVersion +) => { const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); const packageJson = JSON.parse(packageJsonContent); @@ -181,14 +144,14 @@ async function updatePackageJsonDependencies( }; await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); -} +}; /** * Adds a manifest template to the folder where the if-env CLI command runs. */ -async function addTemplateManifest() { +const addTemplateManifest = async () => { try { - const templateManifest = path.resolve(__dirname, 'template.yml'); + const templateManifest = path.resolve(__dirname, './env-template.yml'); const destinationPath = path.resolve( __dirname, FOLDER_NAME, @@ -200,8 +163,9 @@ async function addTemplateManifest() { await fs.writeFile(destinationPath, data, 'utf-8'); } catch (error) { console.log(FAILURE_MESSAGE_TEMPLATE); + process.exit(1); } -} +}; IfEnv().catch(error => { if (error instanceof Error) { From 4583da38faa824fb3c156bec97ec68c25009400b Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 10 Jun 2024 19:29:02 +0400 Subject: [PATCH 056/863] fix(package): fix env file path --- package-lock.json | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 39b301049..4baee717e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "bin": { "ie": "build/index.js", "if-diff": "build/diff.js", - "if-env": "build/env/env.js" + "if-env": "build/env.js" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/package.json b/package.json index 96074537b..ec174390f 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "bin": { "ie": "./build/index.js", "if-diff": "./build/diff.js", - "if-env": "./build/env/env.js" + "if-env": "./build/env.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -75,7 +75,7 @@ "fix:package": "fixpack", "ie": "npx ts-node src/index.ts", "if-diff": "npx ts-node src/diff.ts", - "if-env": "npx ts-node src/env/env.ts", + "if-env": "npx ts-node src/env.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", From 9dec82bd67574c980d7cf805adc7502b8780939a Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 11 Jun 2024 11:19:07 +0400 Subject: [PATCH 057/863] test(mocks): add fs.stat mock function --- src/__mocks__/fs/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index da8438c8b..6ac9b66ea 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -86,3 +86,11 @@ export const writeFile = async (pathToFile: string, content: string) => { expect(pathToFile).toBe(mockPathToFile); expect(content).toBe(mockObject); }; + +export const stat = async (filePath: string) => { + if (filePath === 'true') { + return true; + } else { + throw new Error('File not found.'); + } +}; From ec43b2dadc34ff94f888bf90cb259fb72d239180 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 11 Jun 2024 11:28:34 +0400 Subject: [PATCH 058/863] test(util): add test for npm manipulation functions in helpers.ts --- src/__tests__/unit/util/helpers.test.ts | 103 +++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index d627790e4..b5e04527c 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -1,3 +1,9 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +const mockInfo = jest.fn(); const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -6,10 +12,12 @@ jest.mock('node:readline/promises', () => ); jest.mock('../../../util/logger', () => ({ logger: { + info: mockInfo, warn: mockWarn, error: mockError, }, })); + import { andHandle, checkIfEqual, @@ -17,11 +25,16 @@ import { mergeObjects, oneIsPrimitive, parseManifestFromStdin, + isFileExists, + installDependencies, + initPackageJsonIfNotExists, } from '../../../util/helpers'; import {ERRORS} from '../../../util/errors'; import {Difference} from '../../../types/lib/compare'; +import {STRINGS} from '../../../config/strings'; const {WriteFileError} = ERRORS; +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; describe('util/helpers: ', () => { describe('andHandle(): ', () => { @@ -47,9 +60,7 @@ describe('util/helpers: ', () => { expect(mockError).toHaveBeenCalledTimes(1); }); }); -}); -describe('util/helpers: ', () => { describe('mergeObjects(): ', () => { it('does not override input.', () => { expect.assertions(1); @@ -413,4 +424,92 @@ description: mock-description expect(response).toBeFalsy(); }); }); + + describe('isFileExists(): ', () => { + it('returns true if the file exists.', async () => { + const result = await isFileExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns fale if the file does not exist.', async () => { + const result = await isFileExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('npm manipulation tests.', () => { + const helpers = require('../../../util/helpers'); + let folderPath = path.resolve(__dirname, 'npm-test'); + + beforeAll(() => { + if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, {recursive: true}); + } + }); + + afterAll(() => { + if (fs.existsSync(folderPath)) { + fs.rmSync(folderPath, {recursive: true, force: true}); + } + }); + + describe('initPackageJsonIfNotExists(): ', () => { + it('initializes package.json if it does not exist.', async () => { + const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + isFileExists('true'); + + await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); + expect(spyExecPromise).toHaveBeenCalledWith('npm init -y', { + cwd: folderPath, + }); + }); + + it('returns the package.json path if it exists.', async () => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + isFileExists('false'); + + const result = await initPackageJsonIfNotExists(folderPath); + + expect.assertions(1); + expect(result).toBe(packageJsonPath); + }); + }); + + describe('installDependencies(): ', () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + it('calls execPromise with the correct arguments.', async () => { + const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + const formattedDependencies = ['@grnsft/if@0.3.3-beta.0']; + expect.assertions(1); + + await installDependencies(folderPath, dependencies); + + expect(spyExecPromise).toHaveBeenCalledWith( + `npm install ${formattedDependencies.join(' ')}`, + {cwd: folderPath} + ); + }, 30000); + + it('logs the installation message.', async () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + await installDependencies(folderPath, dependencies); + + expect.assertions(1); + expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); + }); + }); + }); }); From 91c1bedcae20261484202021465ecea2c7794472 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 11 Jun 2024 11:30:21 +0400 Subject: [PATCH 059/863] test(util): fix commit lint error --- src/__tests__/unit/util/helpers.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index b5e04527c..86a0f2dd7 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -443,7 +443,7 @@ description: mock-description describe('npm manipulation tests.', () => { const helpers = require('../../../util/helpers'); - let folderPath = path.resolve(__dirname, 'npm-test'); + const folderPath = path.resolve(__dirname, 'npm-test'); beforeAll(() => { if (!fs.existsSync(folderPath)) { From 3c6c7d5ae17785eed618f35b719bcdee767af9f7 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:56:32 +0100 Subject: [PATCH 060/863] feat(package): update processes doc with details on SDLC --- github-processes.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/github-processes.md b/github-processes.md index 06721b4c6..7c8e9345b 100644 --- a/github-processes.md +++ b/github-processes.md @@ -107,6 +107,7 @@ After a PR has passed triage, it can be assigned to a core team member to review We intend to respond to new PRs and issues within 3 days of the ticket being opened, even if only with a brief message thanking the OP and explaining the triage process. +There may be exceptional instances where bug fixes are prioritized over other ongoing tasks and worked on immediately, before triage. ## Labels @@ -140,3 +141,41 @@ If more than two hotfixes are required on a particular release, the team will ca Hotfixes on release can be merged back into `main` when they have been fully QA tested. We intend for hotfixes to be as infrequent as possible. + + +## Software Development Life Cycle + +Our normal process is to have week-long sprints where we tackle issues that contribute to a larger epic which typically last for 4-6 weeks. + +Our Executive Director and Product owner take responsibility for defining epics. This means they make decisions about how IF should change and translate that into a series of documents that get worked up into tickets for specific tasks. After the initial design, individual tasks are refined by the product owner, which means defining a scope of work and acceptance criteria for each task. + +Refinement is the process of taking a loosely scoped or ambiguous ticket and making it so well-described that anyone could pick it up off the board and produce an equivalent outcome to one of the core team. It's important we do this diligently even if it feels unnecessary or frictionful, because: + +- it keeps us all aligned with the purpose and rationale of individual tasks +- it improves our transparency +- it lowers the barrier to entry for contributors +- it helps us to "measure twice, cut once" and avoid doing work more than once +- it helps us to think together about each issue +- it provides an archive of our thinking that we can go back to in future. + +We use checkboxes for the statement of work and acceptance criteria as this helps to track progress on the task while it is in flight. + +A ticket is considered READY when it has been refined by the product owner. In general, we try to pass the refined ticket to a core developer to review any implementation details. + +We have the `core-only` label that we apply to tasks that are reserved for the core team to work on. Community contributions that cover these tickets are unlikely to get merged unless organized in advance. This is typically for sensitive parts of the core of the IF. + +Epics are also opresented to the community on the IF discussion forum in advance of being worked on in a development sprint. This is to give community contributors a chance to give feedback, suggest course corrections and discuss the changes with the team. These discussions can also lead to community members taking on some of the epic tasks. + +Once the tickets are refined they get prioritized and assigned during our development sprints. There is a pre-sprint prioritization call between the project sponsor, owner and manager to determien the priorities for each sprint, then a sprint planning meeting where the tasks are assigned and sized. + +### Overview of development practises + +| Stage | Participants | Inputs | Outputs | Overview | +| ----------------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Initiation | Sponsor and Product Owner | Problem Statement and Objectives | Action Plan | In this phase, the team identifies a specific job-to-be-done or problem, develops a high-level vision for a solution, and outlines a preliminary task breakdown. | +| 2. Backlog | Product Owner | Breakdown of Epic or Milestone Tasks | An issue for each high-level task detailing the What and Why, along with a link to its parent epic | In this phase, each task from the epic or milestone is incorporated into the backlog (labeled as 'draft'), setting the context effectively. | +| 3. Design | Sponsor and Product Owner | What and Why, link to parent Epic Priority, Preliminary Acceptance Criteria and outline of work scope | In this phase, preliminary acceptance criteria are documented as a foundation for further refinement. | +| 4. Refinement Product Owner, Dev and QA (where applicable) | Preliminary Acceptance Criteria and outline of work scope | Comprehensive scenarios for Acceptance Criteria, confirmed work scope, and size | In this phase, engineers review the desired outcomes to ensure technical feasibility, clarify doubts, and solidify their understanding. They also estimate the required effort. Following this review, the issue is deemed Ready for implementation. | +| 5. Implementation | Dev and QA (where applicable) | A comprehensive set of scenarios for Acceptance Criteria and a confirmed Scope of Work. | A Pull Request (PR) including Unit Tests that pass and manifest files for automated testing, Technical documentation | In this phase, engineers execute the solution and review PRs. They also record a demo to demonstrate that it meets the acceptance criteria. | +| 6. UAT | Product Owner and Sponsor (if applicable) | Working feature and Acceptance Criteria | TBC | In this phase, the Product Owner verifies that the implementation matches the design by reviewing a demonstration of the work completed. | +| 7. Rollout \Product Owner, Sponsor and Marketing (if applicable) | Demos, Technical Documentation | TBC | In this phase, the Product Owner ensures that the community is prepared for the upcoming change. This preparation includes updates to the change log, project announcements, revisions to documentation, marketing efforts, and more. | From 944f053ceee5e093b2701c07480f7164841b2626 Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:25:06 +0100 Subject: [PATCH 061/863] Update github-processes.md Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- github-processes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github-processes.md b/github-processes.md index 7c8e9345b..81f2301d5 100644 --- a/github-processes.md +++ b/github-processes.md @@ -178,4 +178,4 @@ Once the tickets are refined they get prioritized and assigned during our develo | 4. Refinement Product Owner, Dev and QA (where applicable) | Preliminary Acceptance Criteria and outline of work scope | Comprehensive scenarios for Acceptance Criteria, confirmed work scope, and size | In this phase, engineers review the desired outcomes to ensure technical feasibility, clarify doubts, and solidify their understanding. They also estimate the required effort. Following this review, the issue is deemed Ready for implementation. | | 5. Implementation | Dev and QA (where applicable) | A comprehensive set of scenarios for Acceptance Criteria and a confirmed Scope of Work. | A Pull Request (PR) including Unit Tests that pass and manifest files for automated testing, Technical documentation | In this phase, engineers execute the solution and review PRs. They also record a demo to demonstrate that it meets the acceptance criteria. | | 6. UAT | Product Owner and Sponsor (if applicable) | Working feature and Acceptance Criteria | TBC | In this phase, the Product Owner verifies that the implementation matches the design by reviewing a demonstration of the work completed. | -| 7. Rollout \Product Owner, Sponsor and Marketing (if applicable) | Demos, Technical Documentation | TBC | In this phase, the Product Owner ensures that the community is prepared for the upcoming change. This preparation includes updates to the change log, project announcements, revisions to documentation, marketing efforts, and more. | +| 7. Rollout | Product Owner, Sponsor and Marketing (if applicable) | Demos, Technical Documentation | TBC | In this phase, the Product Owner ensures that the community is prepared for the upcoming change. This preparation includes updates to the change log, project announcements, revisions to documentation, marketing efforts, and more. | From 2fee65eb30db94d26cca4bde69c30ec7cc07f175 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Tue, 11 Jun 2024 20:11:14 +0100 Subject: [PATCH 062/863] fix(package): bump braces version to address high severity vuln in npm audit report --- package-lock.json | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 638b4e48a..a52e10aa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3004,11 +3004,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -5003,9 +5004,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6321,8 +6323,9 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -11087,8 +11090,9 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, From b78d49ad8618072049538607eb09a14040013cd9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 12 Jun 2024 14:51:34 +0400 Subject: [PATCH 063/863] revert(builtins): remove unnecessary console.log --- src/builtins/csv-lookup/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts index 4f7df52be..5a009ac8b 100644 --- a/src/builtins/csv-lookup/index.ts +++ b/src/builtins/csv-lookup/index.ts @@ -193,7 +193,6 @@ export const CSVLookup = (globalConfig: any): ExecutePlugin => { const {filepath, query, output} = safeGlobalConfig; const file = await retrieveFile(filepath); - console.log(file); const parsedCSV = parseCSVFile(file); return inputs.map(input => { From a75e8d7c2cea2801ef2c4f7019bb30289d5a39bc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 12 Jun 2024 14:52:12 +0400 Subject: [PATCH 064/863] test(util): remove unnecessary console.log --- src/__tests__/unit/util/aggregation-helper.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts index 7cccbfccc..64add64e0 100644 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ b/src/__tests__/unit/util/aggregation-helper.test.ts @@ -38,7 +38,6 @@ describe('util/aggregation-helper: ', () => { try { aggregateInputsIntoOne(inputs, metrics, isTemporal); } catch (error) { - console.log(error); expect(error).toBeInstanceOf(MissingAggregationParamError); if (error instanceof MissingAggregationParamError) { From f1b4c34822bce47af13fcb30dba5283e31886e4d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:27:14 +0100 Subject: [PATCH 065/863] feat(package): rename scirpts in package and lockfile --- package-lock.json | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a52e10aa3..fc7063570 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,8 @@ "zod": "^3.22.4" }, "bin": { - "ie": "build/index.js", - "if-diff": "build/diff.js" + "if-diff": "build/diff.js", + "if-run": "build/index.js" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/package.json b/package.json index 60e33dc0f..0ff122d85 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "email": "info@gsf.com" }, "bin": { - "ie": "./build/index.js", + "if-run": "./build/index.js", "if-diff": "./build/diff.js" }, "bugs": { @@ -72,7 +72,7 @@ "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/unit", "fix": "gts fix", "fix:package": "fixpack", - "ie": "npx ts-node src/index.ts", + "if-run": "npx ts-node src/index.ts", "if-diff": "npx ts-node src/diff.ts", "lint": "gts lint", "pre-commit": "lint-staged", From 20161b583744f68714eb19ec786eb3acff8500a6 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:27:49 +0100 Subject: [PATCH 066/863] feat(package): update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ff122d85..f17862f4b 100644 --- a/package.json +++ b/package.json @@ -72,8 +72,8 @@ "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/unit", "fix": "gts fix", "fix:package": "fixpack", - "if-run": "npx ts-node src/index.ts", "if-diff": "npx ts-node src/diff.ts", + "if-run": "npx ts-node src/index.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", From 0b4e6c9b6ccd422369f4202f28b0a334cf483453 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:28:44 +0100 Subject: [PATCH 067/863] feat(lib): rename ie to if-run in project readme --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c34bf0069..9de6c64e7 100644 --- a/README.md +++ b/README.md @@ -42,17 +42,17 @@ Then create a `manifest` file that describes your application (see our docs for Then, run `if` using the following command: ```sh -ie --manifest +if-run --manifest ## or you can use aliases -ie -m +if-run -m ``` Note that above command will not print the final output. In order to print the final output to the console, run `if` using the optional stdout argument: ```sh -ie --manifest --stdout +if-run --manifest --stdout ## or using aliases -ie -m -s +if-run -m -s ``` You can also add a savepath for your output yaml in order to have the output stored in a file. Note that you also have to add configuration to your manifest to enable this, as follows: @@ -66,25 +66,25 @@ initialize: On the command line: ```sh -ie --manifest --output +if-run --manifest --output ## or using aliases -ie -m -o +if-run -m -o ``` -The `ie` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). +The `if-run` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). Use the `debug` command if you want to diagnose and fix errors in your plugin: ```sh -ie --manifest --debug +if-run --manifest --debug ``` Use the `help` command if you need guidance about the available commands ```sh -ie --help +if-run --help ## or using alias -ie -h +if-run -h ``` ## Documentation From 0286a34bb9ae2481e5fc73e39c5837ae47be588b Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:29:27 +0100 Subject: [PATCH 068/863] fix(package): update command name in refactor guide --- Refactor-migration-guide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 80328fe9e..95269e1a5 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -12,13 +12,13 @@ There have been some name changes to the CLI, specifically: The command line tool has been renamed from `impact-engine` to simply `ie`. This means that to invoke the Impact Framework on the command line you simply use ``` - ie ... + if-run ... ``` - `impl` --> `manifest` We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to pass a manifest file to IF, you use the `--manifest` command, as follows: ```sh - ie --manifest + if-run --manifest ``` @@ -27,7 +27,7 @@ There have been some name changes to the CLI, specifically: We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to define a savepath for your output file, you use the `--output` command, as follows: ```sh - ie --manifest --output + if-run --manifest --output ``` ## Outputs @@ -55,13 +55,13 @@ npm i @grnsft/if Then run IF using the following command: ```sh -ie --manifest +if-run --manifest ``` This will dump the output to the console. If you want to save the output to a yaml file, provide a savepath to the `--output` command: ```sh -ie --manifest --output +if-run --manifest --output ``` From 9d5d82e5ec29cf0f795fb3dcd2e4ffd8729ea0e1 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:30:42 +0100 Subject: [PATCH 069/863] fix(lib): update ie to if-run in integration test script --- src/__tests__/integration/scenarios/sci-e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/integration/scenarios/sci-e.ts b/src/__tests__/integration/scenarios/sci-e.ts index 9fb808341..0342240c2 100644 --- a/src/__tests__/integration/scenarios/sci-e.ts +++ b/src/__tests__/integration/scenarios/sci-e.ts @@ -36,7 +36,7 @@ describe('integration/sci-e', () => { await saveYamlFileAs(file, absoluteManifestPath); // save yaml uses absolute path const response = ( await execPromise( - `npm run ie -- --manifest ${relativeManifestPath} --stdout` + `npm run if-run -- --manifest ${relativeManifestPath} --stdout` ) ).stdout; // exec promise uses relative path From a82b978f3ad4c6f0878661f8ce8f13df061649d0 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:31:16 +0100 Subject: [PATCH 070/863] fix(lib): update ie to if-run in test script --- scripts/run-yamls.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run-yamls.sh b/scripts/run-yamls.sh index 11371af66..fbe394c6b 100644 --- a/scripts/run-yamls.sh +++ b/scripts/run-yamls.sh @@ -4,5 +4,5 @@ echo 'Running all manifests' for f in ./examples/manifests/*.yml; do echo "Processing $f file..."; - npm run ie -- --manifest $f + npm run if-run -- --manifest $f done From 2c97c002001c74d3f5396c8b801da4aa1d856398 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 13 Jun 2024 10:32:16 +0100 Subject: [PATCH 071/863] fix(lib): update ie -> if-run in builtin readmes --- src/builtins/README.md | 2 +- src/builtins/coefficient/README.md | 2 +- src/builtins/csv-lookup/README.md | 2 +- src/builtins/divide/README.md | 2 +- src/builtins/exponent/README.md | 2 +- src/builtins/interpolation/README.md | 2 +- src/builtins/mock-observations/README.md | 2 +- src/builtins/multiply/README.md | 2 +- src/builtins/sci-embodied/README.md | 2 +- src/builtins/sci/README.md | 2 +- src/builtins/shell/README.md | 2 +- src/builtins/subtract/README.md | 2 +- src/builtins/sum/README.md | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/builtins/README.md b/src/builtins/README.md index b9906921d..c37e143a1 100644 --- a/src/builtins/README.md +++ b/src/builtins/README.md @@ -305,7 +305,7 @@ Then, you must select the metric you want to export to CSV. The name of that met For example, to export the `carbon` data from your tree to a CSV file: ```sh -ie --manifest example.yml --output example#carbon +if-run --manifest example.yml --output example#carbon ``` This will save a CSV file called `example.csv`. The contents will look similar to the following: diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index 096d20ab5..bf8808e8c 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -86,7 +86,7 @@ tree: You can run this example by saving it as `./examples/manifests/coefficient.yml` and executing the following command from the project root: ```sh -ie --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml +if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs` diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index 2c52969ae..d1aece699 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -136,7 +136,7 @@ You can run this example by saving it as `./examples/manifests/csv-lookup.yml` a ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup +if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup ``` The results will be saved to a new `yaml` file in `manifests/outputs`. diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index d403d0361..20ed19f55 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -89,7 +89,7 @@ You can run this example by saving it as `./examples/manifests/divide.yml` and e ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml +if-run --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index 48a67965a..d84020d63 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -91,7 +91,7 @@ You can run this example by saving it as `manifests/examples/test/exponent.yml` ```sh npm i -g @grnsft/if -ie --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml +if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md index cfcca2fa1..670a65ef2 100644 --- a/src/builtins/interpolation/README.md +++ b/src/builtins/interpolation/README.md @@ -164,5 +164,5 @@ You can execute this by passing it to `ie`. Run the impact using the following c ```sh npm i -g @grnsft/if -ie --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml +if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml ``` diff --git a/src/builtins/mock-observations/README.md b/src/builtins/mock-observations/README.md index 629e27f2d..1af4cd6d6 100644 --- a/src/builtins/mock-observations/README.md +++ b/src/builtins/mock-observations/README.md @@ -91,7 +91,7 @@ You can run this example `manifest` by saving it as `manifests/plugins/mock-obse ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation +if-run --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation ``` The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index d4e27674c..695d89331 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -88,7 +88,7 @@ You can run this example by saving it as `./examples/manifests/test/multiply.yml ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml +if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs` diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md index 90fc01d58..70307fee1 100644 --- a/src/builtins/sci-embodied/README.md +++ b/src/builtins/sci-embodied/README.md @@ -104,7 +104,7 @@ You can run this example `manifest` by executing the following command from the ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml +if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 477f74dc0..658209f1a 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -83,7 +83,7 @@ You can run this example `manifest` by saving it as `./manifests/plugins/sci.yml ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml +if-run --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml ``` The results will be saved to a new `yaml` file. diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md index ea813878b..54ccac285 100644 --- a/src/builtins/shell/README.md +++ b/src/builtins/shell/README.md @@ -124,7 +124,7 @@ You can run this example `manifest` by saving it as `manifests/plugins/shell.yml ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml +if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml ``` The results will be saved to a new `yaml` file. diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md index 9279220b8..bb8435548 100644 --- a/src/builtins/subtract/README.md +++ b/src/builtins/subtract/README.md @@ -88,7 +88,7 @@ You can run this example by saving it as `./examples/manifests/test/subrtact.yml ```sh npm i -g @grnsft/if -ie --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml +if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md index b912c07b3..d3fd892da 100644 --- a/src/builtins/sum/README.md +++ b/src/builtins/sum/README.md @@ -85,7 +85,7 @@ tree: You can run this example by saving it as `./examples/manifests/sum.yml` and executing the following command from the project root: ```sh -ie --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml +if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. From 0c4de5921b8ac7c3bb584a75ddd27304d3fbd0f8 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 13 Jun 2024 14:42:36 +0400 Subject: [PATCH 072/863] fix(src): call `overrideConsoleMethods(false)` to prevent show debug logs --- src/diff.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/diff.ts b/src/diff.ts index 7deb09e35..75a5450dd 100644 --- a/src/diff.ts +++ b/src/diff.ts @@ -9,6 +9,7 @@ import {validateManifest} from './util/validations'; import {CONFIG} from './config'; import {logger} from './util/logger'; +import {debugLogger} from './util/debug-logger'; const {IF_DIFF} = CONFIG; const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; @@ -16,6 +17,9 @@ const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; const IfDiff = async () => { const {sourcePath, targetPath} = parseIfDiffArgs(); + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + const {rawSourceManifest, rawTargetManifest} = await loadIfDiffFiles({ targetPath, sourcePath, From 76c6e80fdf6167edcc1c659cd5ab6268e26b31d0 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 13 Jun 2024 18:26:53 +0400 Subject: [PATCH 073/863] fix(src): update return data of parseIfEnvArgs --- src/util/args.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/args.ts b/src/util/args.ts index 753145022..9e9ef5e95 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -181,5 +181,5 @@ export const parseIfEnvArgs = async () => { throw new CliInputError(FILE_IS_NOT_YAML); } - return; + return {install}; }; From 2d2ca0e2324d9dc3eca1024d1941a77254f44d7c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 13 Jun 2024 18:29:19 +0400 Subject: [PATCH 074/863] test(util): update test of parseIfEnvArgs function --- src/__tests__/unit/util/args.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index ac91f8a3a..07620013d 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -337,7 +337,7 @@ describe('util/args: ', () => { expect.assertions(1); - expect(response).toEqual(undefined); + expect(response).toEqual({install: undefined}); }); it('executes if `manifest` and `install` are provided.', async () => { From be6412a73721533b92baf6293bb27146897051df Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 13 Jun 2024 18:30:26 +0400 Subject: [PATCH 075/863] fix(src): remove functioanlity that create sepereate folder --- src/env.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/env.ts b/src/env.ts index 94821d466..5128f58d4 100644 --- a/src/env.ts +++ b/src/env.ts @@ -23,17 +23,15 @@ const { FAILURE_MESSAGE_DEPENDENCIES, } = IF_ENV; -const FOLDER_NAME = 'if-environment'; - const IfEnv = async () => { const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { - folderPath: path.resolve(__dirname, FOLDER_NAME), - install: true, + folderPath: __dirname, + install: !!commandArgs.install, dependencies: {'@grnsft/if': packageJson.version}, }; - if (commandArgs) { + if (commandArgs && commandArgs.manifest) { const {folderPath, install, dependencies} = await getOptionsFromArgs(commandArgs); options.folderPath = folderPath; @@ -43,7 +41,7 @@ const IfEnv = async () => { await initializeAndInstallLibs(options); - if (!commandArgs) { + if (!commandArgs || !commandArgs.manifest) { await addTemplateManifest(); } @@ -152,11 +150,7 @@ const updatePackageJsonDependencies = async ( const addTemplateManifest = async () => { try { const templateManifest = path.resolve(__dirname, './env-template.yml'); - const destinationPath = path.resolve( - __dirname, - FOLDER_NAME, - 'manifest.yml' - ); + const destinationPath = path.resolve(__dirname, 'manifest.yml'); const data = await fs.readFile(templateManifest, 'utf-8'); await fs.writeFile(destinationPath, '', 'utf-8'); From 7e6772d4772af74cfb177de137acd9e46e36fe7f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:47:43 +0400 Subject: [PATCH 076/863] feat(src): read all piped data before checking params --- src/diff.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/diff.ts b/src/diff.ts index 7deb09e35..af61ae380 100644 --- a/src/diff.ts +++ b/src/diff.ts @@ -4,7 +4,7 @@ import {loadIfDiffFiles} from './lib/load'; import {compare} from './lib/compare'; import {parseIfDiffArgs} from './util/args'; -import {formatNotMatchingLog} from './util/helpers'; +import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; import {validateManifest} from './util/validations'; import {CONFIG} from './config'; @@ -14,11 +14,13 @@ const {IF_DIFF} = CONFIG; const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; const IfDiff = async () => { + const pipedSourceManifest = await parseManifestFromStdin(); const {sourcePath, targetPath} = parseIfDiffArgs(); const {rawSourceManifest, rawTargetManifest} = await loadIfDiffFiles({ targetPath, sourcePath, + pipedSourceManifest, }); const [sourceManifest, targetManifest] = [ rawSourceManifest, From d4a492b6825ec881bd2be1dd87f34cae79b74e4a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:48:53 +0400 Subject: [PATCH 077/863] test(lib): fix load if diff cases --- src/__tests__/unit/lib/load.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/lib/load.test.ts b/src/__tests__/unit/lib/load.test.ts index f9ad3e73b..95ae6b26b 100644 --- a/src/__tests__/unit/lib/load.test.ts +++ b/src/__tests__/unit/lib/load.test.ts @@ -45,6 +45,8 @@ import {PARAMETERS} from '../../../config'; import {PluginParams} from '../../../types/interface'; import {STRINGS} from '../../../config'; +import {parseManifestFromStdin} from '../../../util/helpers'; +import {LoadDiffParams} from '../../../types/util/args'; const {INVALID_SOURCE} = STRINGS; @@ -109,8 +111,10 @@ describe('lib/load: ', () => { it('successfully loads target, and source from stdin.', async () => { process.env.readline = 'valid-source'; - const params = { + const piped = await parseManifestFromStdin(); + const params: LoadDiffParams = { targetPath: 'target-path.yml', + pipedSourceManifest: piped, }; const response = await loadIfDiffFiles(params); From 8cd4266b92901021e18f477ff07a6bcc15996e5c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:49:26 +0400 Subject: [PATCH 078/863] test(util): fix parseManifestFromStdin case --- src/__tests__/unit/util/helpers.test.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index d627790e4..58ed0525b 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -364,16 +364,11 @@ describe('util/helpers: ', () => { it('throws error if there is no manifest in stdin.', async () => { process.env.readline = 'no_manifest'; - const expectedMessage = 'Manifest not found in STDIN.'; expect.assertions(1); - try { - await parseManifestFromStdin(); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual(expectedMessage); - } - } + const response = await parseManifestFromStdin(); + + expect(response).toEqual(''); }); it('returns empty string if there is no data in stdin.', async () => { From 17948b6b5f2f401570607f399de6a6c103406149 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:50:10 +0400 Subject: [PATCH 079/863] fix(lib): move piped data reader --- src/lib/load.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/load.ts b/src/lib/load.ts index 9b9508ded..2ed335b6f 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -3,7 +3,6 @@ import * as YAML from 'js-yaml'; import {ERRORS} from '../util/errors'; import {openYamlFileAsObject} from '../util/yaml'; import {readAndParseJson} from '../util/json'; -import {parseManifestFromStdin} from '../util/helpers'; import {PARAMETERS} from '../config'; import {STRINGS} from '../config'; @@ -41,8 +40,7 @@ export const load = async (inputPath: string, paramPath?: string) => { * Loads files to compare. As a source file checks if data is piped and then decides which one to take. */ export const loadIfDiffFiles = async (params: LoadDiffParams) => { - const {sourcePath, targetPath} = params; - const pipedSourceManifest = await parseManifestFromStdin(); + const {sourcePath, targetPath, pipedSourceManifest} = params; if (!sourcePath && !pipedSourceManifest) { throw new CliInputError(INVALID_SOURCE); From dd973179f7d78f9a29d57f94e7dc7e7d285fdbcc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:50:32 +0400 Subject: [PATCH 080/863] feat(types): add piped source manifest to load diff params --- src/types/util/args.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/util/args.ts b/src/types/util/args.ts index d9debf3cd..ae78fa4d0 100644 --- a/src/types/util/args.ts +++ b/src/types/util/args.ts @@ -1,4 +1,5 @@ export type LoadDiffParams = { sourcePath?: string; targetPath: string; + pipedSourceManifest?: string; }; From f14790bb2ef0484b005fa0feb03e66355063a7c0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:51:09 +0400 Subject: [PATCH 081/863] fix(util): return empty string if no manifest found --- src/util/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b15863cef..2b2dba87f 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -164,7 +164,7 @@ const collectPipedData = async () => { /** * Checks if there is piped data, tries to parse yaml from it. - * Throws error if there is piped info, but there is no valid manifest. + * Returns empty string if haven't found anything. */ export const parseManifestFromStdin = async () => { const pipedSourceManifest = await collectPipedData(); @@ -177,7 +177,7 @@ export const parseManifestFromStdin = async () => { const match = regex.exec(pipedSourceManifest); if (!match) { - throw new Error('Manifest not found in STDIN.'); + return ''; } return match![1]; From 640b0caf12fcee182592cf8d8e155b331dc62b00 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 18:51:41 +0400 Subject: [PATCH 082/863] fix(util): add newlines which improve readability --- src/util/validations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/validations.ts b/src/util/validations.ts index 3cd1dd6b9..21695f3ee 100644 --- a/src/util/validations.ts +++ b/src/util/validations.ts @@ -9,6 +9,7 @@ import {STRINGS} from '../config/strings'; const {ManifestValidationError, InputValidationError} = ERRORS; const {VALIDATING_MANIFEST} = STRINGS; + /** * At least one property defined handler. */ @@ -148,5 +149,6 @@ const flattenPath = (path: (string | number)[]): string => { const flattenPath = path.map(part => typeof part === 'number' ? `[${part}]` : part ); + return flattenPath.join('.'); }; From c4f15c95bb02a958d530f72e796a67cf3514178d Mon Sep 17 00:00:00 2001 From: Release commit workflow Date: Thu, 13 Jun 2024 15:09:31 +0000 Subject: [PATCH 083/863] =?UTF-8?q?chore(release):=20v0.4.0=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a52e10aa3..1c2c47735 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@grnsft/if", - "version": "0.3.4", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@grnsft/if", - "version": "0.3.4", + "version": "0.4.0", "license": "MIT", "dependencies": { "@commitlint/cli": "^18.6.0", diff --git a/package.json b/package.json index 60e33dc0f..c6db34155 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@grnsft/if", "description": "Impact Framework", - "version": "0.3.4", + "version": "0.4.0", "author": { "name": "Green Software Foundation", "email": "info@gsf.com" From d5d1ea9e15f2890b057a3e19948585b81d66f5a6 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 19:52:02 +0400 Subject: [PATCH 084/863] revert(config): remove missing manifest from stdin message --- src/config/strings.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 6ef27ac5e..83283e8fb 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -55,7 +55,6 @@ Note that for the '--output' option you also need to define the output type in y TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', - MISSING_MANIFEST_IN_STDIN: 'Manifest not found in STDIN.', /** Plugin messages */ MISSING_GLOBAL_CONFIG: 'Global config is not provided.', MISSING_INPUT_DATA: (param: string) => From f932b7dbdab916e0bebd49d2c517a1f5fbb8c166 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 19:52:40 +0400 Subject: [PATCH 085/863] revert(util): remove unused error class and message --- src/util/helpers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 6b94c9397..d3b5a0a3c 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -9,8 +9,7 @@ import {STRINGS} from '../config'; import {Difference} from '../types/lib/compare'; -const {ISSUE_TEMPLATE, MISSING_MANIFEST_IN_STDIN} = STRINGS; -const {CliInputError} = ERRORS; +const {ISSUE_TEMPLATE} = STRINGS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. From 6c40decedeb8c81d46f55bd256f534a05a39fa49 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:05:58 +0400 Subject: [PATCH 086/863] feat(util): introduce if-core for errors --- src/util/aggregation-helper.ts | 3 ++- src/util/args.ts | 3 ++- src/util/helpers.ts | 3 ++- src/util/plugin-storage.ts | 3 ++- src/util/validations.ts | 3 +-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/util/aggregation-helper.ts b/src/util/aggregation-helper.ts index 0a8b3c136..3caff8c6d 100644 --- a/src/util/aggregation-helper.ts +++ b/src/util/aggregation-helper.ts @@ -1,4 +1,5 @@ -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; + import {parameterize} from '../lib/parameterize'; import {CONFIG, STRINGS} from '../config'; diff --git a/src/util/args.ts b/src/util/args.ts index e7a042094..ee090c1ef 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -1,8 +1,9 @@ import * as path from 'path'; + import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core'; import {checkIfFileIsYaml} from './yaml'; -import {ERRORS} from './errors'; import {logger} from './logger'; import {CONFIG, STRINGS} from '../config'; diff --git a/src/util/helpers.ts b/src/util/helpers.ts index d3b5a0a3c..45af8b50c 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -2,7 +2,8 @@ import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; -import {ERRORS} from './errors'; +import {ERRORS} from '@grnsft/if-core'; + import {logger} from './logger'; import {STRINGS} from '../config'; diff --git a/src/util/plugin-storage.ts b/src/util/plugin-storage.ts index 15582e9f3..da1e45970 100644 --- a/src/util/plugin-storage.ts +++ b/src/util/plugin-storage.ts @@ -1,4 +1,5 @@ -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; + import {STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; diff --git a/src/util/validations.ts b/src/util/validations.ts index 21695f3ee..30cb1e930 100644 --- a/src/util/validations.ts +++ b/src/util/validations.ts @@ -1,6 +1,5 @@ import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; - -import {ERRORS} from './errors'; +import {ERRORS} from '@grnsft/if-core'; import {AGGREGATION_METHODS} from '../types/aggregation'; import {AGGREGATION_TYPES} from '../types/parameters'; From 56abea628fa1c32358299d5bba5e5b9dbd246d53 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:07:48 +0400 Subject: [PATCH 087/863] feat(lib): introduce if-core for errors --- src/lib/exhaust.ts | 3 ++- src/lib/initialize.ts | 25 +++++++++++++------------ src/lib/load.ts | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 002818c70..d60268698 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -1,3 +1,5 @@ +import {ERRORS} from '@grnsft/if-core'; + /** * @todo This is temporary solution, will be refactored to support dynamic plugins. */ @@ -6,7 +8,6 @@ import {ExportCSVRaw} from '../builtins/export-csv-raw'; import {ExportLog} from '../builtins/export-log'; import {ExportYaml} from '../builtins/export-yaml'; -import {ERRORS} from '../util/errors'; import {STRINGS} from '../config'; diff --git a/src/lib/initialize.ts b/src/lib/initialize.ts index e9c4f27a0..ac01e8e8e 100644 --- a/src/lib/initialize.ts +++ b/src/lib/initialize.ts @@ -1,6 +1,7 @@ -import pathLib = require('path'); +import * as path from 'node:path'; + +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../util/errors'; import {logger} from '../util/logger'; import {memoizedLog} from '../util/log-memoize'; import {pluginStorage} from '../util/plugin-storage'; @@ -53,23 +54,23 @@ const importAndVerifyModule = async (method: string, path: string) => { * Then checks if `path` is starting with github, then grabs the repository name. * Imports module, then checks if it's a valid plugin. */ -const handModule = (method: string, path: string) => { - console.debug(LOADING_PLUGIN_FROM_PATH(method, path)); +const handModule = (method: string, pluginPath: string) => { + console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath)); - if (path === 'builtin') { - path = pathLib.normalize(`${__dirname}/../builtins`); + if (pluginPath === 'builtin') { + pluginPath = path.normalize(`${__dirname}/../builtins`); } else { - if (path?.startsWith(GITHUB_PATH)) { - const parts = path.split('/'); - path = parts[parts.length - 1]; + if (pluginPath?.startsWith(GITHUB_PATH)) { + const parts = pluginPath.split('/'); + pluginPath = parts[parts.length - 1]; } - if (!path.includes(NATIVE_PLUGIN)) { - memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(path)); + if (!pluginPath.includes(NATIVE_PLUGIN)) { + memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(pluginPath)); } } - return importAndVerifyModule(method, path); + return importAndVerifyModule(method, pluginPath); }; /** diff --git a/src/lib/load.ts b/src/lib/load.ts index 0a65d4476..72620e982 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -1,6 +1,6 @@ import * as YAML from 'js-yaml'; +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../util/errors'; import {openYamlFileAsObject} from '../util/yaml'; import {readAndParseJson} from '../util/json'; From 5ea7b14909c94a665bb97d6280361a2696b8f2fd Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:08:03 +0400 Subject: [PATCH 088/863] feat(builtins): introduce if-core for errors --- src/builtins/coefficient/index.ts | 2 +- src/builtins/csv-lookup/index.ts | 2 +- src/builtins/divide/index.ts | 2 +- src/builtins/exponent/index.ts | 2 +- src/builtins/export-csv-raw.ts | 2 +- src/builtins/export-csv.ts | 2 +- src/builtins/export-yaml.ts | 2 +- src/builtins/group-by.ts | 2 +- src/builtins/interpolation/index.ts | 2 +- src/builtins/mock-observations/helpers/common-generator.ts | 2 +- src/builtins/mock-observations/helpers/rand-int-generator.ts | 2 +- src/builtins/multiply/index.ts | 2 +- src/builtins/regex/index.ts | 2 +- src/builtins/sci/index.ts | 2 +- src/builtins/shell/index.ts | 2 +- src/builtins/subtract/index.ts | 2 +- src/builtins/sum/index.ts | 2 +- src/builtins/time-sync.ts | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts index c049911ae..65404172f 100644 --- a/src/builtins/coefficient/index.ts +++ b/src/builtins/coefficient/index.ts @@ -3,7 +3,7 @@ import {z} from 'zod'; import {ExecutePlugin, PluginParams} from '../../types/interface'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts index 5a009ac8b..47232e115 100644 --- a/src/builtins/csv-lookup/index.ts +++ b/src/builtins/csv-lookup/index.ts @@ -6,7 +6,7 @@ import {z} from 'zod'; import {parse} from 'csv-parse/sync'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts index e50ca81f9..14e8b4d44 100644 --- a/src/builtins/divide/index.ts +++ b/src/builtins/divide/index.ts @@ -1,6 +1,6 @@ import {z} from 'zod'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 0de914fda..3a417329b 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -1,6 +1,6 @@ import {z} from 'zod'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts index 7adc4281b..9ce1edae3 100644 --- a/src/builtins/export-csv-raw.ts +++ b/src/builtins/export-csv-raw.ts @@ -1,6 +1,6 @@ import * as fs from 'fs/promises'; -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../config'; diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts index e92de3ce8..9eb03d9cc 100644 --- a/src/builtins/export-csv.ts +++ b/src/builtins/export-csv.ts @@ -1,7 +1,7 @@ import {writeFile} from 'fs/promises'; import {stringify} from 'csv-stringify/sync'; -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../config'; diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts index b3822c619..f6a3d71d7 100644 --- a/src/builtins/export-yaml.ts +++ b/src/builtins/export-yaml.ts @@ -1,5 +1,5 @@ import {saveYamlFileAs} from '../util/yaml'; -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../config'; diff --git a/src/builtins/group-by.ts b/src/builtins/group-by.ts index e4e8af958..3d38d444a 100644 --- a/src/builtins/group-by.ts +++ b/src/builtins/group-by.ts @@ -5,7 +5,7 @@ import {STRINGS} from '../config'; import {GroupByPlugin, PluginParams} from '../types/interface'; import {GroupByConfig} from '../types/group-by'; -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../util/validations'; const {InvalidGroupingError, GlobalConfigError} = ERRORS; diff --git a/src/builtins/interpolation/index.ts b/src/builtins/interpolation/index.ts index 35f88788b..dfe507c42 100644 --- a/src/builtins/interpolation/index.ts +++ b/src/builtins/interpolation/index.ts @@ -4,7 +4,7 @@ import {z} from 'zod'; import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; diff --git a/src/builtins/mock-observations/helpers/common-generator.ts b/src/builtins/mock-observations/helpers/common-generator.ts index ee4909dcd..732e7320e 100644 --- a/src/builtins/mock-observations/helpers/common-generator.ts +++ b/src/builtins/mock-observations/helpers/common-generator.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../../config'; diff --git a/src/builtins/mock-observations/helpers/rand-int-generator.ts b/src/builtins/mock-observations/helpers/rand-int-generator.ts index a48e399c8..6c0365d35 100644 --- a/src/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/builtins/mock-observations/helpers/rand-int-generator.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../../config'; diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts index ffcf4d14c..5ceb44c3c 100644 --- a/src/builtins/multiply/index.ts +++ b/src/builtins/multiply/index.ts @@ -1,6 +1,6 @@ import {z} from 'zod'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; diff --git a/src/builtins/regex/index.ts b/src/builtins/regex/index.ts index 5730697cc..cdcbd13b8 100644 --- a/src/builtins/regex/index.ts +++ b/src/builtins/regex/index.ts @@ -1,6 +1,6 @@ import {z} from 'zod'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index a39e33c94..c7802213d 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -1,7 +1,7 @@ import {z} from 'zod'; import {validate, allDefined} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; diff --git a/src/builtins/shell/index.ts b/src/builtins/shell/index.ts index c78f668e2..0b894d64b 100644 --- a/src/builtins/shell/index.ts +++ b/src/builtins/shell/index.ts @@ -6,7 +6,7 @@ import {ExecutePlugin, PluginParams} from '../../types/interface'; import {ConfigParams} from '../../types/common'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; const {ProcessExecutionError} = ERRORS; diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts index 25f5d8522..87523082e 100644 --- a/src/builtins/subtract/index.ts +++ b/src/builtins/subtract/index.ts @@ -1,6 +1,6 @@ import {z} from 'zod'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts index 9944373a8..676829162 100644 --- a/src/builtins/sum/index.ts +++ b/src/builtins/sum/index.ts @@ -1,7 +1,7 @@ import {z} from 'zod'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; diff --git a/src/builtins/time-sync.ts b/src/builtins/time-sync.ts index 469fdec35..1542b7854 100644 --- a/src/builtins/time-sync.ts +++ b/src/builtins/time-sync.ts @@ -4,7 +4,7 @@ import {z} from 'zod'; import {parameterize} from '../lib/parameterize'; -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {validate} from '../util/validations'; import {STRINGS} from '../config'; From 896553e0f077ec9b4b0482271884e15f57d6643f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:09:56 +0400 Subject: [PATCH 089/863] test(util): introduce if-core for errors --- src/__tests__/unit/util/aggregation-helper.test.ts | 3 ++- src/__tests__/unit/util/args.test.ts | 4 ++-- src/__tests__/unit/util/errors.test.ts | 2 +- src/__tests__/unit/util/helpers.test.ts | 2 +- src/__tests__/unit/util/plugin-storage.test.ts | 3 ++- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts index 64add64e0..eb379e10f 100644 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ b/src/__tests__/unit/util/aggregation-helper.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {aggregateInputsIntoOne} from '../../../util/aggregation-helper'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index 7da9efa37..52e468987 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -69,10 +69,10 @@ jest.mock('ts-command-line-args', () => ({ }, })); -import path = require('path'); +import * as path from 'node:path'; +import {ERRORS} from '@grnsft/if-core'; import {parseIEProcessArgs, parseIfDiffArgs} from '../../../util/args'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/util/errors.test.ts b/src/__tests__/unit/util/errors.test.ts index 47e3e9e9a..15d6ea52a 100644 --- a/src/__tests__/unit/util/errors.test.ts +++ b/src/__tests__/unit/util/errors.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; describe('util/errors: ', () => { describe('ERRORS: ', () => { diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 58ed0525b..4aaccc5f5 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -10,6 +10,7 @@ jest.mock('../../../util/logger', () => ({ error: mockError, }, })); +import {ERRORS} from '@grnsft/if-core'; import { andHandle, checkIfEqual, @@ -18,7 +19,6 @@ import { oneIsPrimitive, parseManifestFromStdin, } from '../../../util/helpers'; -import {ERRORS} from '../../../util/errors'; import {Difference} from '../../../types/lib/compare'; const {WriteFileError} = ERRORS; diff --git a/src/__tests__/unit/util/plugin-storage.test.ts b/src/__tests__/unit/util/plugin-storage.test.ts index f8ac5b631..0555b1db5 100644 --- a/src/__tests__/unit/util/plugin-storage.test.ts +++ b/src/__tests__/unit/util/plugin-storage.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {pluginStorage} from '../../../util/plugin-storage'; -import {ERRORS} from '../../../util/errors'; const {PluginInitializationError} = ERRORS; From 395737ac0017eb5b7044982d9c8cec2be5614fd2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:10:26 +0400 Subject: [PATCH 090/863] test(lib): introduce if-core for errors --- src/__tests__/unit/lib/exhaust.test.ts | 4 ++-- src/__tests__/unit/lib/initialize.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index a1f46595a..1fa652bb3 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ jest.mock('fs', () => require('../../../__mocks__/fs')); -import {exhaust} from '../../../lib/exhaust'; +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../../../util/errors'; +import {exhaust} from '../../../lib/exhaust'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/lib/initialize.test.ts b/src/__tests__/unit/lib/initialize.test.ts index 23ca27171..51d15f0d7 100644 --- a/src/__tests__/unit/lib/initialize.test.ts +++ b/src/__tests__/unit/lib/initialize.test.ts @@ -10,9 +10,9 @@ jest.mock('../../../util/log-memoize', () => ({ memoizedLog: mockLog, })); -import {initialize} from '../../../lib/initialize'; +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../../../util/errors'; +import {initialize} from '../../../lib/initialize'; import {STRINGS} from '../../../config'; From e39478132bd643b56334f8db4bfe479e693989f8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:13:14 +0400 Subject: [PATCH 091/863] test(builtins): introduce if-core for errors --- src/__tests__/unit/builtins/CommonGenerator.test.ts | 3 ++- src/__tests__/unit/builtins/RandIntGenerator.test.ts | 6 +++--- src/__tests__/unit/builtins/coefficient.test.ts | 4 ++-- src/__tests__/unit/builtins/csv-lookup.test.ts | 2 +- src/__tests__/unit/builtins/divide.test.ts | 3 ++- src/__tests__/unit/builtins/exponent.test.ts | 3 ++- src/__tests__/unit/builtins/export-csv-raw.test.ts | 2 +- src/__tests__/unit/builtins/export-csv.test.ts | 2 +- src/__tests__/unit/builtins/export-yaml.test.ts | 3 ++- src/__tests__/unit/builtins/group-by.test.ts | 3 ++- src/__tests__/unit/builtins/interpolation.test.ts | 3 ++- src/__tests__/unit/builtins/mock-observations.test.ts | 3 ++- src/__tests__/unit/builtins/multiply.test.ts | 3 ++- src/__tests__/unit/builtins/regex.test.ts | 3 ++- src/__tests__/unit/builtins/sci-embodied.test.ts | 3 ++- src/__tests__/unit/builtins/sci.test.ts | 4 ++-- src/__tests__/unit/builtins/shell.test.ts | 2 +- src/__tests__/unit/builtins/subtract.test.ts | 3 ++- src/__tests__/unit/builtins/sum.test.ts | 3 ++- src/__tests__/unit/builtins/time-sync.test.ts | 3 +-- 20 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/__tests__/unit/builtins/CommonGenerator.test.ts b/src/__tests__/unit/builtins/CommonGenerator.test.ts index d4d1bdac9..23109c117 100644 --- a/src/__tests__/unit/builtins/CommonGenerator.test.ts +++ b/src/__tests__/unit/builtins/CommonGenerator.test.ts @@ -1,6 +1,7 @@ -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {CommonGenerator} from '../../../builtins/mock-observations/helpers/common-generator'; + import {STRINGS} from '../../../config'; const {GlobalConfigError} = ERRORS; diff --git a/src/__tests__/unit/builtins/RandIntGenerator.test.ts b/src/__tests__/unit/builtins/RandIntGenerator.test.ts index 1d2969695..ca1b60183 100644 --- a/src/__tests__/unit/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/unit/builtins/RandIntGenerator.test.ts @@ -1,11 +1,11 @@ -import {KeyValuePair} from '../../../types/common'; - -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core'; import {RandIntGenerator} from '../../../builtins/mock-observations/helpers/rand-int-generator'; import {STRINGS} from '../../../config'; +import {KeyValuePair} from '../../../types/common'; + const {GlobalConfigError} = ERRORS; const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; diff --git a/src/__tests__/unit/builtins/coefficient.test.ts b/src/__tests__/unit/builtins/coefficient.test.ts index 44595d774..e7e92adf5 100644 --- a/src/__tests__/unit/builtins/coefficient.test.ts +++ b/src/__tests__/unit/builtins/coefficient.test.ts @@ -1,6 +1,6 @@ -import {Coefficient} from '../../../builtins/coefficient'; +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../../../util/errors'; +import {Coefficient} from '../../../builtins/coefficient'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts index 8fbdee401..e887f5e4b 100644 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ b/src/__tests__/unit/builtins/csv-lookup.test.ts @@ -2,12 +2,12 @@ jest.mock('fs/promises', () => require('../../../__mocks__/fs')); import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; +import {ERRORS} from '@grnsft/if-core'; import {CSVLookup} from '../../../builtins'; import {STRINGS} from '../../../config'; -import {ERRORS} from '../../../util/errors'; const { GlobalConfigError, diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts index 9c794dae6..c75c926be 100644 --- a/src/__tests__/unit/builtins/divide.test.ts +++ b/src/__tests__/unit/builtins/divide.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Divide} from '../../../builtins'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts index 6034fd3bd..04d9f7e9b 100644 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ b/src/__tests__/unit/builtins/exponent.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Exponent} from '../../../builtins/exponent'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {InputValidationError, MissingInputDataError} = ERRORS; diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts index a66a24ac2..5ff8d20cd 100644 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ b/src/__tests__/unit/builtins/export-csv-raw.test.ts @@ -1,8 +1,8 @@ import * as fs from 'fs/promises'; import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core'; import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts index 09fd4e737..942732e2e 100644 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ b/src/__tests__/unit/builtins/export-csv.test.ts @@ -1,9 +1,9 @@ import * as fs from 'fs/promises'; import {stringify} from 'csv-stringify/sync'; import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core'; import {ExportCSV} from '../../../builtins/export-csv'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts index f17b9154e..56b155cba 100644 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ b/src/__tests__/unit/builtins/export-yaml.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {ExportYaml} from '../../../builtins/export-yaml'; -import {ERRORS} from '../../../util/errors'; import {saveYamlFileAs} from '../../../util/yaml'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/group-by.test.ts b/src/__tests__/unit/builtins/group-by.test.ts index b472125d1..22ef77f56 100644 --- a/src/__tests__/unit/builtins/group-by.test.ts +++ b/src/__tests__/unit/builtins/group-by.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {GroupBy} from '../../../builtins/group-by'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/interpolation.test.ts b/src/__tests__/unit/builtins/interpolation.test.ts index 54dd2dab7..ead5880bb 100644 --- a/src/__tests__/unit/builtins/interpolation.test.ts +++ b/src/__tests__/unit/builtins/interpolation.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Interpolation} from '../../../builtins'; -import {ERRORS} from '../../../util/errors'; import {Method} from '../../../builtins/interpolation/types'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/mock-observations.test.ts b/src/__tests__/unit/builtins/mock-observations.test.ts index 3e2ddab5b..7a46cf79f 100644 --- a/src/__tests__/unit/builtins/mock-observations.test.ts +++ b/src/__tests__/unit/builtins/mock-observations.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {MockObservations} from '../../../builtins/mock-observations'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {InputValidationError, GlobalConfigError} = ERRORS; diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts index 7efceb325..ff168110e 100644 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ b/src/__tests__/unit/builtins/multiply.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Multiply} from '../../../builtins/multiply'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {MissingInputDataError} = ERRORS; diff --git a/src/__tests__/unit/builtins/regex.test.ts b/src/__tests__/unit/builtins/regex.test.ts index 462faad8f..57cdc5e0c 100644 --- a/src/__tests__/unit/builtins/regex.test.ts +++ b/src/__tests__/unit/builtins/regex.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Regex} from '../../../builtins/regex'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; diff --git a/src/__tests__/unit/builtins/sci-embodied.test.ts b/src/__tests__/unit/builtins/sci-embodied.test.ts index 4b9f88deb..1d8f05438 100644 --- a/src/__tests__/unit/builtins/sci-embodied.test.ts +++ b/src/__tests__/unit/builtins/sci-embodied.test.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core'; + import {SciEmbodied} from '../../../builtins/sci-embodied'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts index a9401a5a8..751804f17 100644 --- a/src/__tests__/unit/builtins/sci.test.ts +++ b/src/__tests__/unit/builtins/sci.test.ts @@ -1,6 +1,6 @@ -import {Sci} from '../../../builtins/sci'; +import {ERRORS} from '@grnsft/if-core'; -import {ERRORS} from '../../../util/errors'; +import {Sci} from '../../../builtins/sci'; const {MissingInputDataError} = ERRORS; diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts index 306dada3c..ce5b4aea7 100644 --- a/src/__tests__/unit/builtins/shell.test.ts +++ b/src/__tests__/unit/builtins/shell.test.ts @@ -1,9 +1,9 @@ import {spawnSync} from 'child_process'; import {loadAll} from 'js-yaml'; +import {ERRORS} from '@grnsft/if-core'; import {Shell} from '../../../builtins/shell'; -import {ERRORS} from '../../../util/errors'; const {InputValidationError, ProcessExecutionError} = ERRORS; diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts index 2179adcd4..a1c1e3302 100644 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ b/src/__tests__/unit/builtins/subtract.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Subtract} from '../../../builtins/subtract'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {InputValidationError} = ERRORS; diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts index e7b515f26..7a09958d1 100644 --- a/src/__tests__/unit/builtins/sum.test.ts +++ b/src/__tests__/unit/builtins/sum.test.ts @@ -1,6 +1,7 @@ +import {ERRORS} from '@grnsft/if-core'; + import {Sum} from '../../../builtins/sum'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; diff --git a/src/__tests__/unit/builtins/time-sync.test.ts b/src/__tests__/unit/builtins/time-sync.test.ts index ac627fe02..63174743a 100644 --- a/src/__tests__/unit/builtins/time-sync.test.ts +++ b/src/__tests__/unit/builtins/time-sync.test.ts @@ -1,9 +1,8 @@ +import {ERRORS} from '@grnsft/if-core'; import {Settings, DateTime} from 'luxon'; import {TimeSync} from '../../../builtins/time-sync'; -import {ERRORS} from '../../../util/errors'; - import {STRINGS} from '../../../config'; Settings.defaultZone = 'utc'; From f95d21c7589381921c1a387b1cf857344b602471 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:13:40 +0400 Subject: [PATCH 092/863] feat(package): install `@grnsft/if-core` dependency --- package-lock.json | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) diff --git a/package-lock.json b/package-lock.json index 1c2c47735..2ec34c515 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", + "@grnsft/if-core": "^0.0.3", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1179,6 +1180,18 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@grnsft/if-core": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.3.tgz", + "integrity": "sha512-ieuUcadEgA4EztIzCbCW5ifK2a6SUU2ioZtLTce8pJ+imgeQ47lQM3UtChtbaUm52rEwvgl1Psp0ysgOjqssFA==", + "dependencies": { + "typescript": "^5.1.6" + }, + "engines": { + "node": ">=18", + "npm": ">=8" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "dev": true, diff --git a/package.json b/package.json index c6db34155..5093d2235 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", + "@grnsft/if-core": "^0.0.3", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 163df83594b4ab6be79297e7fee70750089c48f1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:16:01 +0400 Subject: [PATCH 093/863] revert(util): drop errors support --- src/util/errors.ts | 49 ---------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 src/util/errors.ts diff --git a/src/util/errors.ts b/src/util/errors.ts deleted file mode 100644 index f4f067d77..000000000 --- a/src/util/errors.ts +++ /dev/null @@ -1,49 +0,0 @@ -const CUSTOM_ERRORS = [ - 'CliInputError', - 'ManifestValidationError', - 'InputValidationError', - 'InvalidGroupingError', - 'WriteFileError', - /** More specific errors */ - 'ParseCliParamsError', - 'CliSourceFileError', - 'CliTargetFileError', - 'InvalidAggregationMethodError', - 'MissingAggregationParamError', - 'MissingPluginMethodError', - 'MissingPluginPathError', - 'PluginInitializationError', - 'InvalidExhaustPluginError', - /** Plugins */ - 'GlobalConfigError', - 'MissingInputDataError', - 'ProcessExecutionError', - 'RegexMismatchError', - 'FetchingFileError', - 'ReadFileError', - 'MissingCSVColumnError', - 'QueryDataNotFoundError', - 'InvalidDateInInputError', - 'InvalidPaddingError', - 'InvalidInputError', - 'ExhaustOutputArgError', - 'CSVParseError', -] as const; - -type CustomErrors = { - [K in (typeof CUSTOM_ERRORS)[number]]: ErrorConstructor; -}; - -export const ERRORS = CUSTOM_ERRORS.reduce((acc, className) => { - acc = { - ...acc, - [className]: class extends Error { - constructor(message: string) { - super(message); - this.name = this.constructor.name; - } - }, - }; - - return acc; -}, {} as CustomErrors); From 98e825a02f7995dfaaa727fe0baf683812e5b90b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:17:02 +0400 Subject: [PATCH 094/863] chore(builtins): remove redundant newlines --- src/__tests__/unit/builtins/csv-lookup.test.ts | 1 - src/__tests__/unit/builtins/shell.test.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts index e887f5e4b..9e718d537 100644 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ b/src/__tests__/unit/builtins/csv-lookup.test.ts @@ -8,7 +8,6 @@ import {CSVLookup} from '../../../builtins'; import {STRINGS} from '../../../config'; - const { GlobalConfigError, ReadFileError, diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts index ce5b4aea7..95f44fb12 100644 --- a/src/__tests__/unit/builtins/shell.test.ts +++ b/src/__tests__/unit/builtins/shell.test.ts @@ -4,7 +4,6 @@ import {ERRORS} from '@grnsft/if-core'; import {Shell} from '../../../builtins/shell'; - const {InputValidationError, ProcessExecutionError} = ERRORS; jest.mock('child_process'); From 434cde45f5f3c5421f51754a0398ec9582227908 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:17:23 +0400 Subject: [PATCH 095/863] test(util): drop errors --- src/__tests__/unit/util/errors.test.ts | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/__tests__/unit/util/errors.test.ts diff --git a/src/__tests__/unit/util/errors.test.ts b/src/__tests__/unit/util/errors.test.ts deleted file mode 100644 index 15d6ea52a..000000000 --- a/src/__tests__/unit/util/errors.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {ERRORS} from '@grnsft/if-core'; - -describe('util/errors: ', () => { - describe('ERRORS: ', () => { - it('checks for properties.', () => { - const errors = Object.values(ERRORS); - - errors.forEach(error => { - expect(error).toBeInstanceOf(Function); - }); - }); - }); -}); From 6743cba3cc25f505b689fc0ad6df9efe7e112f89 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 13 Jun 2024 20:17:53 +0400 Subject: [PATCH 096/863] fix(lib): remove redundant exhaust newline --- src/lib/exhaust.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index d60268698..a4982681d 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -8,7 +8,6 @@ import {ExportCSVRaw} from '../builtins/export-csv-raw'; import {ExportLog} from '../builtins/export-log'; import {ExportYaml} from '../builtins/export-yaml'; - import {STRINGS} from '../config'; import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; From 474a46589612b4312df38a28ca25a8284befec41 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:23:39 +0100 Subject: [PATCH 097/863] fix(package): rm if-plugins from readme --- README.md | 44 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index c34bf0069..2be7911fa 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,6 @@ > [!IMPORTANT] > Incubation Project: This project is an incubation project being run inside the Green Software Foundation; as such, we DON’T recommend using it in any critical use case. Incubation projects are experimental, offer no support guarantee, have minimal governance and process, and may be retired at any moment. This project may one day Graduate, in which case this disclaimer will be removed. -**Note** We have recently (March 2024) refactored the IF codebase and introduced some changes affecting both users and developers. You can read our migration guide [HERE](./Refactor-migration-guide.md) to help you update to the latest version! - -[Impact Framework](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/17072136/Opensource+Impact+Engine+Framework) (IF) is an [Incubation](https://oc.greensoftware.foundation/project-lifecycle.html#incubation) project from the [Open Source Working Group](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/852049/Open+Source+Working+Group) in the [Green Software Foundation](https://greensoftware.foundation/). - **Our documentation is online at [if.greensoftware.foundation](https://if.greensoftware.foundation/)** **IF** is a framework to **M**odel, **M**easure, si**M**ulate and **M**onitor the environmental impacts of software @@ -23,39 +19,31 @@ Read the [specification and design docs](https://if.greensoftware.foundation) to ## Get started -The first thing to understand is that IF is a framework for running plugins. This means that in order to do some calculations, you need to load some plugins from some external resource. We provide a [standard library of plugins](https://github.com/Green-Software-Foundation/if-plugins) and a repository of [community plugins](https://github.com/Green-Software-Foundation/if-unofficial-plugins) to get you started. +IF is a framework for running pipelines of plugins that operate on a set of observations. This is all configured using a manifest file. We provide a standard library of plugins that come bundled with IF - we refer to these as `builtins`. We also have an [Explorer](https://explorer.if.greensoftware.foundation) where anyone can list third party plugins you can install. -Start by installing framework itself: +Start by installing the latest version of IF: ```sh npm install -g "@grnsft/if" ``` -Then installing some plugins: - -```sh -npm install -g "@grnsft/if-plugins" -``` - Then create a `manifest` file that describes your application (see our docs for a detailed explanation). Then, run `if` using the following command: ```sh -ie --manifest +if-run --manifest --stdout ## or you can use aliases -ie -m +if-run -m --stdout ``` -Note that above command will not print the final output. In order to print the final output to the console, run `if` using the optional stdout argument: +Note that above command will print your outputs to the console. You can also provide the `--output` command to save your outputs to a yaml file: ```sh -ie --manifest --stdout -## or using aliases -ie -m -s +if-run -m -o ``` -You can also add a savepath for your output yaml in order to have the output stored in a file. Note that you also have to add configuration to your manifest to enable this, as follows: +Note that you also have to add configuration to your manifest to enable this, as follows: ```yaml initialize: @@ -63,34 +51,27 @@ initialize: - yaml ``` -On the command line: - -```sh -ie --manifest --output -## or using aliases -ie -m -o -``` - The `ie` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). Use the `debug` command if you want to diagnose and fix errors in your plugin: ```sh -ie --manifest --debug +if-run --manifest --debug ``` Use the `help` command if you need guidance about the available commands ```sh -ie --help +if-run --help ## or using alias -ie -h +if-run -h ``` ## Documentation Please read our documentation at [if.greensoftware.foundation](https://if.greensoftware.foundation/) + ## Video walk-through Watch this video to learn how to create and run a `manifest`. @@ -107,11 +88,10 @@ We have a public mailing list at [if-community@greensoftware.foundation](https:/ To contribute to IF, please fork this repository and raise a pull request from your fork. -You can check our issue board for issues tagged `help-wanted`. These are issues that are not currently, actively being worked on by the core team but are well-scoped enough for someone to pick up. We recommend commenting on the issue to start a chat with the core team, then start working on the issue when you have been assigned to it. This process helps to ensure your work is aligned with our roadmap and makes it much more likely that your changes will get merged compared to unsolicited PRs. +You can check our issue board for issues. We mark some issues `core-only` if they are somehow sensitive and we want one of our core developers to handle it. Any other issues are open for the community to work on. We recommend commenting on the issue to start a chat with the core team, then start working on the issue when you have been assigned to it. This process helps to ensure your work is aligned with our roadmap and makes it much more likely that your changes will get merged compared to unsolicited PRs. Please read the full contribution guidelines at [if.greensoftware.foundation](https://if.greensoftware.foundation/Contributing) -The same guidelines also apply to `if-docs`, `if-plugins` and `if-unofficial-plugins`. ## Bug reports From 5ec4d5a25739f5f7458a7b65c4ffad6c8e8d4c1a Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 14 Jun 2024 10:25:00 +0100 Subject: [PATCH 098/863] fix(lib): small fix to contributing guide --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3974becb0..841d69272 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ The following document is a rule set of guidelines for contributing. ## What and when to contribute -You can contribute anything to the IF, but we are likely to close out unsolicited PRs without merging them. Our issue board is completely open and we have tags (`help-wanted`, `good-first-issue`) to help contributors to choose tasks to work on. We recommend speaking to the core team on Github before starting working on an issue. You can do this by raising an issue or commenting on an existing issue. This helps us to direct your energy in directions that are aligned with our roadmap, prevent multiple people working on the same task, and better manage our board. This all makes it much more likely that your work will get merged. +You can contribute anything to the IF, but we are likely to close out unsolicited PRs without merging them. Our issue board is completely open and we have tags (`core-only`, `good-first-issue`) to help contributors to choose tasks to work on. If an issue is unassigned and does not have the `core-only` label, it is available to work on. We recommend speaking to the core team on Github before starting working on an issue. You can do this by commenting on an existing issue or discussion thread or starting a new one if appropriate. This helps us to direct your energy in directions that are aligned with our roadmap, prevent multiple people working on the same task, and better manage our board. This all makes it much more likely that your work will get merged. You can also contribute by participating in discussions on our mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that includes what we've shipped, what we're working on and how you can get involved each week. From 1ddb2f2bec24d759261898843736fca1d0a70856 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 14 Jun 2024 10:30:33 +0100 Subject: [PATCH 099/863] fix(package): remove refs to if-plugins --- CONTRIBUTING.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 841d69272..d1ea0db53 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,9 +30,9 @@ You can also contribute by participating in discussions on our mailing list at [ ## Reporting bugs -We appreciate bug reports! If you experience an issue with IF or one of our plugins, you can report it using our bug reporting template. To do this: +We appreciate bug reports! If you experience an issue with IF, you can report it using our bug reporting template. To do this: -1. Go to the [IF repository](https://github.com/Green-Software-Foundation/if) (or [plugin repository](https://github.com/Green-Software-Foundation/if-plugins) if you bug relates to a specific plugin) +1. Go to the [IF repository](https://github.com/Green-Software-Foundation/if) 2. Click on the `Issues` tab 3. Click on `Create New Issue` and select the `Bug Report` template. 4. Fill out the requested information. @@ -46,8 +46,7 @@ The assessment rubric is as follows: | | Consequence | Severity | | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------- | | Bugs in IF core leading to incorrect calculations | unusable framework | 5 | -| Bugs in if-plugins leading to incorrect calculations | core pathways fail, IF very limited in functionality | 5 | -| Bugs in if-unofficial-pluginsd leading to incorrect calculations | Third party plugins harder to use, limits IF to standard lib | 3 | +| Bugs in builtins leading to incorrect calculations | core pathways fail, IF very limited in functionality | 5 | | Bugs in template | Harder to build plugins, ecosystem growth is impacted | 2 | | Bugs in docs | product does not match expectation, hard to debug, frustration, loss of adoption | 2 | | Security flaw: privacy related | leak user data, unlikely to achieve adoption in serious orgs | 5 | From 015bf60b8cd4460ec69d8b9bbf46a5a7e57d36bc Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:02:48 +0100 Subject: [PATCH 100/863] Update README.md Co-authored-by: Manushak Keramyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2be7911fa..c72600b91 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ initialize: - yaml ``` -The `ie` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). +The `if-run` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). Use the `debug` command if you want to diagnose and fix errors in your plugin: From 2fdb5dcdf6c6b31005ef79ceafe004feb011156e Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:09:02 +0100 Subject: [PATCH 101/863] Update README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d44dd1cd6..6fe0f67a4 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Then, run `if` using the following command: ```sh if-run --manifest --stdout ## or you can use aliases -if-run -m --stdout +if-run -m -s ``` From 4e1ee62015ecfd63afaf005e48d45a57888498a3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 16:52:29 +0400 Subject: [PATCH 102/863] feat(util): introduce if-core utils and types --- src/util/aggregation-helper.ts | 4 ++-- src/util/args.ts | 2 +- src/util/helpers.ts | 2 +- src/util/plugin-storage.ts | 2 +- src/util/validations.ts | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/util/aggregation-helper.ts b/src/util/aggregation-helper.ts index 3caff8c6d..408a4e9f7 100644 --- a/src/util/aggregation-helper.ts +++ b/src/util/aggregation-helper.ts @@ -1,11 +1,11 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; import {parameterize} from '../lib/parameterize'; import {CONFIG, STRINGS} from '../config'; import {AggregationResult} from '../types/aggregation'; -import {PluginParams} from '../types/interface'; const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; diff --git a/src/util/args.ts b/src/util/args.ts index ee090c1ef..c54117c75 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import {parse} from 'ts-command-line-args'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {checkIfFileIsYaml} from './yaml'; import {logger} from './logger'; diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 45af8b50c..fcab2e27a 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -2,7 +2,7 @@ import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {logger} from './logger'; diff --git a/src/util/plugin-storage.ts b/src/util/plugin-storage.ts index da1e45970..1f9711943 100644 --- a/src/util/plugin-storage.ts +++ b/src/util/plugin-storage.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../config'; diff --git a/src/util/validations.ts b/src/util/validations.ts index 30cb1e930..920e7cbdb 100644 --- a/src/util/validations.ts +++ b/src/util/validations.ts @@ -1,11 +1,11 @@ import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../config/strings'; import {AGGREGATION_METHODS} from '../types/aggregation'; import {AGGREGATION_TYPES} from '../types/parameters'; -import {STRINGS} from '../config/strings'; - const {ManifestValidationError, InputValidationError} = ERRORS; const {VALIDATING_MANIFEST} = STRINGS; From 8d1244ac8770c0291ee2d15521a7f4ddfa194d87 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 16:53:01 +0400 Subject: [PATCH 103/863] revert(types): drop common and group-by --- src/types/common.ts | 5 ----- src/types/group-by.ts | 3 --- 2 files changed, 8 deletions(-) delete mode 100644 src/types/common.ts delete mode 100644 src/types/group-by.ts diff --git a/src/types/common.ts b/src/types/common.ts deleted file mode 100644 index f7d337392..000000000 --- a/src/types/common.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type KeyValuePair = { - [key: string]: any; -}; - -export type ConfigParams = Record; diff --git a/src/types/group-by.ts b/src/types/group-by.ts deleted file mode 100644 index 72dd6d61b..000000000 --- a/src/types/group-by.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type GroupByConfig = { - group: string[]; -}; From 9ee5885b886731673866c46f3f7b1cffa95e496b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 16:53:22 +0400 Subject: [PATCH 104/863] feat(types): introduce if-core types --- src/types/compute.ts | 3 ++- src/types/interface.ts | 25 +------------------------ 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/types/compute.ts b/src/types/compute.ts index 739d86742..2de3e6e33 100644 --- a/src/types/compute.ts +++ b/src/types/compute.ts @@ -1,4 +1,5 @@ -import {PluginParams} from './interface'; +import {PluginParams} from '@grnsft/if-core/types'; + import {Context} from './manifest'; import {PluginStorageInterface} from './plugin-storage'; diff --git a/src/types/interface.ts b/src/types/interface.ts index f06449bc6..6834a3ebb 100644 --- a/src/types/interface.ts +++ b/src/types/interface.ts @@ -1,27 +1,4 @@ -import {GroupByConfig} from './group-by'; - -export type PluginParams = Record; - -export type ConfigParams = Record; - -export type ExecutePlugin = { - execute: ( - inputs: PluginParams[], - config?: Record - ) => PluginParams[] | Promise; - metadata: { - kind: string; - }; - [key: string]: any; -}; - -export type GroupByPlugin = { - execute: (inputs: PluginParams[], config: GroupByConfig) => {children: any}; - metadata: { - kind: string; - }; - [key: string]: any; -}; +import {ExecutePlugin, GroupByPlugin} from '@grnsft/if-core/types'; export type PluginInterface = ExecutePlugin | GroupByPlugin; From 27c74503d78e79ece685d43c4fff7dcc255e03ba Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:43:28 +0400 Subject: [PATCH 105/863] feat(lib): introduce if-core utils and types --- src/lib/aggregate.ts | 7 ++++--- src/lib/compute.ts | 5 +++-- src/lib/exhaust.ts | 2 +- src/lib/initialize.ts | 2 +- src/lib/load.ts | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/lib/aggregate.ts b/src/lib/aggregate.ts index 977f30300..c6eef11cc 100644 --- a/src/lib/aggregate.ts +++ b/src/lib/aggregate.ts @@ -1,10 +1,11 @@ -import {aggregateInputsIntoOne} from '../util/aggregation-helper'; +import {PluginParams} from '@grnsft/if-core/types'; -import {PluginParams} from '../types/interface'; -import {AggregationParams, AggregationParamsSure} from '../types/manifest'; +import {aggregateInputsIntoOne} from '../util/aggregation-helper'; import {STRINGS} from '../config/strings'; +import {AggregationParams, AggregationParamsSure} from '../types/manifest'; + const {AGGREGATING_NODE, AGGREGATING_OUTPUTS} = STRINGS; /** diff --git a/src/lib/compute.ts b/src/lib/compute.ts index 40db1a42a..b83a22d2e 100644 --- a/src/lib/compute.ts +++ b/src/lib/compute.ts @@ -1,9 +1,10 @@ +import {PluginParams, GroupByConfig} from '@grnsft/if-core/types'; + import {debugLogger} from '../util/debug-logger'; import {mergeObjects} from '../util/helpers'; import {ComputeParams, Node, Params} from '../types/compute'; -import {PluginParams, isExecute, isGroupBy} from '../types/interface'; -import {GroupByConfig} from '../types/group-by'; +import {isExecute, isGroupBy} from '../types/interface'; import {STRINGS} from '../config/strings'; diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index a4982681d..1b65ca898 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; /** * @todo This is temporary solution, will be refactored to support dynamic plugins. diff --git a/src/lib/initialize.ts b/src/lib/initialize.ts index ac01e8e8e..212d98e37 100644 --- a/src/lib/initialize.ts +++ b/src/lib/initialize.ts @@ -1,6 +1,6 @@ import * as path from 'node:path'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {logger} from '../util/logger'; import {memoizedLog} from '../util/log-memoize'; diff --git a/src/lib/load.ts b/src/lib/load.ts index 72620e982..61f2b6cf5 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -1,5 +1,5 @@ import * as YAML from 'js-yaml'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {openYamlFileAsObject} from '../util/yaml'; import {readAndParseJson} from '../util/json'; From fa18a5ee72ffe73a56f0aa8a16e2b9980e0c0e95 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:44:00 +0400 Subject: [PATCH 106/863] revert(uiltins): drop local types support --- src/builtins/coefficient/types.ts | 5 ----- src/builtins/exponent/types.ts | 5 ----- src/builtins/interpolation/types.ts | 5 ----- src/builtins/mock-observations/types.ts | 16 ---------------- src/builtins/multiply/types.ts | 4 ---- src/builtins/subtract/types.ts | 4 ---- src/builtins/sum/types.ts | 4 ---- 7 files changed, 43 deletions(-) delete mode 100644 src/builtins/coefficient/types.ts delete mode 100644 src/builtins/exponent/types.ts delete mode 100644 src/builtins/interpolation/types.ts delete mode 100644 src/builtins/mock-observations/types.ts delete mode 100644 src/builtins/multiply/types.ts delete mode 100644 src/builtins/subtract/types.ts delete mode 100644 src/builtins/sum/types.ts diff --git a/src/builtins/coefficient/types.ts b/src/builtins/coefficient/types.ts deleted file mode 100644 index 9cbb78b7d..000000000 --- a/src/builtins/coefficient/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type CoefficientConfig = { - 'input-parameter': string; - coefficient: number; - 'output-parameter': string; -}; diff --git a/src/builtins/exponent/types.ts b/src/builtins/exponent/types.ts deleted file mode 100644 index 54e8b2efc..000000000 --- a/src/builtins/exponent/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ExponentConfig = { - 'input-parameter': string; - exponent: number; - 'output-parameter': string; -}; diff --git a/src/builtins/interpolation/types.ts b/src/builtins/interpolation/types.ts deleted file mode 100644 index 09b7abb5e..000000000 --- a/src/builtins/interpolation/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Method { - LINEAR = 'linear', - SPLINE = 'spline', - POLYNOMIAL = 'polynomial', -} diff --git a/src/builtins/mock-observations/types.ts b/src/builtins/mock-observations/types.ts deleted file mode 100644 index 82591207c..000000000 --- a/src/builtins/mock-observations/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {DateTime} from 'luxon'; - -import {Generator} from './interfaces/index'; - -export type ObservationParams = { - duration: number; - timeBucket: DateTime; - component: Record; - generators: Generator[]; -}; - -export type RandIntGeneratorParams = { - name: string; - min: number; - max: number; -}; diff --git a/src/builtins/multiply/types.ts b/src/builtins/multiply/types.ts deleted file mode 100644 index 88f4cae49..000000000 --- a/src/builtins/multiply/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type MultiplyConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; diff --git a/src/builtins/subtract/types.ts b/src/builtins/subtract/types.ts deleted file mode 100644 index 4dc6775d2..000000000 --- a/src/builtins/subtract/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type SubtractConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; diff --git a/src/builtins/sum/types.ts b/src/builtins/sum/types.ts deleted file mode 100644 index e30c990e5..000000000 --- a/src/builtins/sum/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type SumConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; From 89a19ee055e4775ba07a31e542fb733a7e3d94cb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:44:15 +0400 Subject: [PATCH 107/863] feat(builtins): introduce if-core utils and types --- src/builtins/coefficient/index.ts | 11 ++++++----- src/builtins/csv-lookup/index.ts | 5 ++--- src/builtins/divide/index.ts | 5 ++--- src/builtins/exponent/index.ts | 10 ++++++---- src/builtins/export-csv-raw.ts | 6 ++---- src/builtins/export-csv.ts | 6 +++--- src/builtins/export-log.ts | 1 + src/builtins/export-yaml.ts | 3 ++- src/builtins/group-by.ts | 10 ++++++---- src/builtins/interpolation/index.ts | 12 +++++++----- .../helpers/common-generator.ts | 5 +++-- .../helpers/rand-int-generator.ts | 10 ++++------ src/builtins/mock-observations/index.ts | 16 +++++++++------- src/builtins/multiply/index.ts | 10 ++++++---- src/builtins/regex/index.ts | 6 ++---- src/builtins/sci-embodied/index.ts | 3 +-- src/builtins/sci/index.ts | 6 ++---- src/builtins/shell/index.ts | 7 +++---- src/builtins/subtract/index.ts | 10 ++++++---- src/builtins/sum/index.ts | 6 ++---- src/builtins/time-sync.ts | 17 +++++++++-------- 21 files changed, 84 insertions(+), 81 deletions(-) diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts index 65404172f..aed444ad3 100644 --- a/src/builtins/coefficient/index.ts +++ b/src/builtins/coefficient/index.ts @@ -1,14 +1,15 @@ import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + CoefficientConfig, + ExecutePlugin, + PluginParams, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; -import {CoefficientConfig} from './types'; - const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts index 47232e115..8243a6391 100644 --- a/src/builtins/csv-lookup/index.ts +++ b/src/builtins/csv-lookup/index.ts @@ -4,14 +4,13 @@ import {readFile} from 'fs/promises'; 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 {validate} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; - const { FILE_FETCH_FAILED, FILE_READ_FAILED, diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts index 14e8b4d44..a38e3601b 100644 --- a/src/builtins/divide/index.ts +++ b/src/builtins/divide/index.ts @@ -1,12 +1,11 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; - const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 3a417329b..90d66cd72 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -1,13 +1,15 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + ExponentConfig, +} from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ExponentConfig} from './types'; - const {MissingInputDataError, InputValidationError} = ERRORS; const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts index 9ce1edae3..7afc21cb2 100644 --- a/src/builtins/export-csv-raw.ts +++ b/src/builtins/export-csv-raw.ts @@ -1,16 +1,14 @@ import * as fs from 'fs/promises'; - -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../config'; -import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; const {ExhaustOutputArgError, WriteFileError} = ERRORS; const {OUTPUT_REQUIRED, WRITE_CSV_ERROR, EXPORTING_RAW_CSV_FILE} = STRINGS; -export const ExportCSVRaw = (): ExhaustPluginInterface => { +export const ExportCSVRaw = () => { /** * handle a tree leaf, where there are no child nodes, by adding it as key->value pair to the flat map * and capturing key as a header diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts index 9eb03d9cc..53a105733 100644 --- a/src/builtins/export-csv.ts +++ b/src/builtins/export-csv.ts @@ -1,12 +1,12 @@ import {writeFile} from 'fs/promises'; -import {stringify} from 'csv-stringify/sync'; -import {ERRORS} from '@grnsft/if-core'; +import {stringify} from 'csv-stringify/sync'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; import {STRINGS} from '../config'; import {Context} from '../types/manifest'; -import {PluginParams} from '../types/interface'; const {ExhaustOutputArgError} = ERRORS; const {CSV_EXPORT, OUTPUT_REQUIRED, EXPORTING_TO_CSV_FILE} = STRINGS; diff --git a/src/builtins/export-log.ts b/src/builtins/export-log.ts index 3120f3386..fee267dc2 100644 --- a/src/builtins/export-log.ts +++ b/src/builtins/export-log.ts @@ -1,4 +1,5 @@ import * as YAML from 'js-yaml'; + import {Context} from '../types/manifest'; export const ExportLog = () => { diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts index f6a3d71d7..624e1298f 100644 --- a/src/builtins/export-yaml.ts +++ b/src/builtins/export-yaml.ts @@ -1,5 +1,6 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {saveYamlFileAs} from '../util/yaml'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../config'; diff --git a/src/builtins/group-by.ts b/src/builtins/group-by.ts index 3d38d444a..63c4cd5c5 100644 --- a/src/builtins/group-by.ts +++ b/src/builtins/group-by.ts @@ -1,11 +1,13 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + GroupByPlugin, + PluginParams, + GroupByConfig, +} from '@grnsft/if-core/types'; import {STRINGS} from '../config'; -import {GroupByPlugin, PluginParams} from '../types/interface'; -import {GroupByConfig} from '../types/group-by'; - -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../util/validations'; const {InvalidGroupingError, GlobalConfigError} = ERRORS; diff --git a/src/builtins/interpolation/index.ts b/src/builtins/interpolation/index.ts index dfe507c42..98a84ad8a 100644 --- a/src/builtins/interpolation/index.ts +++ b/src/builtins/interpolation/index.ts @@ -1,15 +1,17 @@ import Spline from 'typescript-cubic-spline'; import {z} from 'zod'; - -import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + Method, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; -import {Method} from './types'; - const {GlobalConfigError} = ERRORS; const { MISSING_GLOBAL_CONFIG, diff --git a/src/builtins/mock-observations/helpers/common-generator.ts b/src/builtins/mock-observations/helpers/common-generator.ts index 732e7320e..8283cf1bd 100644 --- a/src/builtins/mock-observations/helpers/common-generator.ts +++ b/src/builtins/mock-observations/helpers/common-generator.ts @@ -1,4 +1,5 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ConfigParams} from '@grnsft/if-core/types'; import {STRINGS} from '../../../config'; @@ -7,7 +8,7 @@ import {Generator} from '../interfaces'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const CommonGenerator = (config: Record): Generator => { +export const CommonGenerator = (config: ConfigParams): Generator => { /** * Generates next value by copying the validated config. * Validates the provided config is not null or empty. diff --git a/src/builtins/mock-observations/helpers/rand-int-generator.ts b/src/builtins/mock-observations/helpers/rand-int-generator.ts index 6c0365d35..1cb4d161f 100644 --- a/src/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/builtins/mock-observations/helpers/rand-int-generator.ts @@ -1,9 +1,9 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {RandIntGeneratorParams, ConfigParams} from '@grnsft/if-core/types'; import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; -import {RandIntGeneratorParams} from '../types'; const {GlobalConfigError} = ERRORS; @@ -12,7 +12,7 @@ const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = export const RandIntGenerator = ( name: string, - config: Record + config: ConfigParams ): Generator => { const next = () => ({ [validatedName]: generateRandInt(getFieldToPopulate()), @@ -26,9 +26,7 @@ export const RandIntGenerator = ( return name; }; - const validateConfig = ( - config: Record - ): {min: number; max: number} => { + const validateConfig = (config: ConfigParams): {min: number; max: number} => { if (!config || Object.keys(config).length === 0) { throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } diff --git a/src/builtins/mock-observations/index.ts b/src/builtins/mock-observations/index.ts index b535da757..c7488de0f 100644 --- a/src/builtins/mock-observations/index.ts +++ b/src/builtins/mock-observations/index.ts @@ -1,15 +1,18 @@ import {DateTime, Duration} from 'luxon'; import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + ObservationParams, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams, KeyValuePair} from '../../types/common'; import {Generator} from './interfaces/index'; -import {ObservationParams} from './types'; export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -122,11 +125,10 @@ export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { CommonGenerator(config), ]; - const createRandIntGenerators = (config: any): Generator[] => { - return Object.entries(config).map(([fieldToPopulate, value]) => - RandIntGenerator(fieldToPopulate, value as KeyValuePair) + const createRandIntGenerators = (config: any): Generator[] => + Object.entries(config).map(([fieldToPopulate, value]) => + RandIntGenerator(fieldToPopulate, value as Record) ); - }; return Object.entries(generatorsConfig).flatMap(([key, value]) => key === 'randint' diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts index 5ceb44c3c..717c68507 100644 --- a/src/builtins/multiply/index.ts +++ b/src/builtins/multiply/index.ts @@ -1,13 +1,15 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + MultiplyConfig, +} from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {MultiplyConfig} from './types'; - const {MissingInputDataError} = ERRORS; const {MISSING_INPUT_DATA} = STRINGS; diff --git a/src/builtins/regex/index.ts b/src/builtins/regex/index.ts index cdcbd13b8..8d382ec74 100644 --- a/src/builtins/regex/index.ts +++ b/src/builtins/regex/index.ts @@ -1,13 +1,11 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; - const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; diff --git a/src/builtins/sci-embodied/index.ts b/src/builtins/sci-embodied/index.ts index 02f897584..678d41336 100644 --- a/src/builtins/sci-embodied/index.ts +++ b/src/builtins/sci-embodied/index.ts @@ -1,11 +1,10 @@ import {z} from 'zod'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; - const {SCI_EMBODIED_ERROR} = STRINGS; export const SciEmbodied = (): ExecutePlugin => { diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index c7802213d..223493f3a 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -1,13 +1,11 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; - const {MissingInputDataError} = ERRORS; const {MISSING_FUNCTIONAL_UNIT_CONFIG, MISSING_FUNCTIONAL_UNIT_INPUT} = STRINGS; diff --git a/src/builtins/shell/index.ts b/src/builtins/shell/index.ts index 0b894d64b..352ee6bcd 100644 --- a/src/builtins/shell/index.ts +++ b/src/builtins/shell/index.ts @@ -1,12 +1,11 @@ import {spawnSync, SpawnSyncReturns} from 'child_process'; + import {loadAll, dump} from 'js-yaml'; import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; const {ProcessExecutionError} = ERRORS; diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts index 87523082e..20a61b5b6 100644 --- a/src/builtins/subtract/index.ts +++ b/src/builtins/subtract/index.ts @@ -1,13 +1,15 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + SubtractConfig, +} from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {SubtractConfig} from './types'; - const {InputValidationError} = ERRORS; const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts index 676829162..ecce47cf3 100644 --- a/src/builtins/sum/index.ts +++ b/src/builtins/sum/index.ts @@ -1,13 +1,11 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, SumConfig} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '@grnsft/if-core'; import {STRINGS} from '../../config'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {SumConfig} from './types'; - const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_INPUT_DATA, MISSING_GLOBAL_CONFIG} = STRINGS; diff --git a/src/builtins/time-sync.ts b/src/builtins/time-sync.ts index 1542b7854..8b37241b8 100644 --- a/src/builtins/time-sync.ts +++ b/src/builtins/time-sync.ts @@ -1,21 +1,22 @@ import {isDate} from 'node:util/types'; + import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + PaddingReceipt, + TimeNormalizerConfig, + TimeParams, +} from '@grnsft/if-core/types'; import {parameterize} from '../lib/parameterize'; -import {ERRORS} from '@grnsft/if-core'; import {validate} from '../util/validations'; import {STRINGS} from '../config'; -import {ExecutePlugin, PluginParams} from '../types/interface'; -import { - PaddingReceipt, - TimeNormalizerConfig, - TimeParams, -} from '../types/time-sync'; - Settings.defaultZone = 'utc'; const { From 710b2a32e333cc5e9e8cb0001158ee684c775b0c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:45:25 +0400 Subject: [PATCH 108/863] test(util): introduce if-core util and types --- src/__tests__/unit/util/aggregation-helper.test.ts | 5 ++--- src/__tests__/unit/util/args.test.ts | 2 +- src/__tests__/unit/util/helpers.test.ts | 2 +- src/__tests__/unit/util/plugin-storage.test.ts | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts index eb379e10f..1a23bc3c1 100644 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ b/src/__tests__/unit/util/aggregation-helper.test.ts @@ -1,11 +1,10 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; import {aggregateInputsIntoOne} from '../../../util/aggregation-helper'; import {STRINGS} from '../../../config'; -import {PluginParams} from '../../../types/interface'; - const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index 52e468987..045bf2807 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -70,7 +70,7 @@ jest.mock('ts-command-line-args', () => ({ })); import * as path from 'node:path'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {parseIEProcessArgs, parseIfDiffArgs} from '../../../util/args'; diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 4aaccc5f5..86ea702a4 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -10,7 +10,7 @@ jest.mock('../../../util/logger', () => ({ error: mockError, }, })); -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import { andHandle, checkIfEqual, diff --git a/src/__tests__/unit/util/plugin-storage.test.ts b/src/__tests__/unit/util/plugin-storage.test.ts index 0555b1db5..8b76f36cd 100644 --- a/src/__tests__/unit/util/plugin-storage.test.ts +++ b/src/__tests__/unit/util/plugin-storage.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {pluginStorage} from '../../../util/plugin-storage'; From 21c8d0bf00ba33a66884c7642b36a827c45f0302 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:45:55 +0400 Subject: [PATCH 109/863] test(lib): drop unused manifests --- src/__tests__/unit/lib/manifest/basic.ts | 48 ------- src/__tests__/unit/lib/manifest/nested.ts | 146 ---------------------- 2 files changed, 194 deletions(-) delete mode 100644 src/__tests__/unit/lib/manifest/basic.ts delete mode 100644 src/__tests__/unit/lib/manifest/nested.ts diff --git a/src/__tests__/unit/lib/manifest/basic.ts b/src/__tests__/unit/lib/manifest/basic.ts deleted file mode 100644 index e5da7c642..000000000 --- a/src/__tests__/unit/lib/manifest/basic.ts +++ /dev/null @@ -1,48 +0,0 @@ -import {Manifest} from '../../../../types/manifest'; - -export const manifest: Manifest = { - name: 'gsf-demo', - description: 'Hello', - tags: { - kind: 'web', - complexity: 'moderate', - category: 'cloud', - }, - initialize: { - plugins: { - 'mock-name': { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'front-end': { - pipeline: ['mock-name'], - config: { - 'mock-name': { - 'core-units': 24, - processor: 'Intel® Core™ i7-1185G7', - }, - }, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 18.392, - }, - { - timestamp: '2023-08-06T00:00', - duration: 3600, - 'cpu/utilization': 16, - }, - ], - }, - }, - }, -}; diff --git a/src/__tests__/unit/lib/manifest/nested.ts b/src/__tests__/unit/lib/manifest/nested.ts deleted file mode 100644 index 0c27fad12..000000000 --- a/src/__tests__/unit/lib/manifest/nested.ts +++ /dev/null @@ -1,146 +0,0 @@ -import {Manifest} from '../../../../types/manifest'; - -export const manifestNested: Manifest = { - name: 'nesting-demo', - description: null, - tags: { - kind: 'web', - complexity: 'moderate', - category: 'on-premise', - }, - initialize: { - plugins: { - mockavizta: { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'child-0': { - config: { - mockavizta: { - allocation: 'LINEAR', - verbose: true, - }, - }, - pipeline: ['mockavizta'], - children: { - 'child-0-1': { - children: { - 'child-0-1-1': { - pipeline: ['mockavizta'], - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - 'child-0-1-2': { - children: { - 'child-1-2-1': { - pipeline: ['mockavizta'], - config: { - mockavizta: { - allocation: 'mock-allocation', - verbose: false, - }, - }, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - }, - }, - }, - }, - }, - }, - }, - }, -}; - -export const manifestNestedNoConfig: Manifest = { - name: 'nesting-demo', - description: null, - tags: { - kind: 'web', - complexity: 'moderate', - category: 'on-premise', - }, - initialize: { - plugins: { - mockavizta: { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'child-0': { - config: { - mockavizta: { - allocation: 'LINEAR', - verbose: true, - }, - }, - pipeline: ['mockavizta'], - children: { - 'child-0-1': { - children: { - 'child-0-1-1': { - pipeline: ['mockavizta'], - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - 'child-0-1-2': { - children: { - 'child-1-2-1': { - pipeline: ['mockavizta'], - config: {}, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - }, - }, - }, - }, - }, - }, - }, - }, -}; From 6709d12de37aa0582d2d2f722ca0e02412346ca5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:46:10 +0400 Subject: [PATCH 110/863] test(lib): introduce if-core utils and types --- src/__tests__/unit/lib/exhaust.test.ts | 2 +- src/__tests__/unit/lib/initialize.test.ts | 2 +- src/__tests__/unit/lib/load.test.ts | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index 1fa652bb3..49db14370 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ jest.mock('fs', () => require('../../../__mocks__/fs')); -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {exhaust} from '../../../lib/exhaust'; diff --git a/src/__tests__/unit/lib/initialize.test.ts b/src/__tests__/unit/lib/initialize.test.ts index 51d15f0d7..ff3c10c45 100644 --- a/src/__tests__/unit/lib/initialize.test.ts +++ b/src/__tests__/unit/lib/initialize.test.ts @@ -10,7 +10,7 @@ jest.mock('../../../util/log-memoize', () => ({ memoizedLog: mockLog, })); -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {initialize} from '../../../lib/initialize'; diff --git a/src/__tests__/unit/lib/load.test.ts b/src/__tests__/unit/lib/load.test.ts index 95ae6b26b..ba3bca902 100644 --- a/src/__tests__/unit/lib/load.test.ts +++ b/src/__tests__/unit/lib/load.test.ts @@ -38,14 +38,14 @@ jest.mock('../../../util/yaml', () => ({ }, })); -import {load, loadIfDiffFiles} from '../../../lib/load'; +import {PluginParams} from '@grnsft/if-core/types'; -import {PARAMETERS} from '../../../config'; +import {load, loadIfDiffFiles} from '../../../lib/load'; -import {PluginParams} from '../../../types/interface'; +import {PARAMETERS, STRINGS} from '../../../config'; -import {STRINGS} from '../../../config'; import {parseManifestFromStdin} from '../../../util/helpers'; + import {LoadDiffParams} from '../../../types/util/args'; const {INVALID_SOURCE} = STRINGS; From ec2d8c0b57f3650742d2bbf94d01d7280d8cebdf Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:46:23 +0400 Subject: [PATCH 111/863] test(builtins): introduce if-core utils and types --- src/__tests__/unit/builtins/CommonGenerator.test.ts | 2 +- src/__tests__/unit/builtins/RandIntGenerator.test.ts | 6 ++---- src/__tests__/unit/builtins/coefficient.test.ts | 2 +- src/__tests__/unit/builtins/csv-lookup.test.ts | 2 +- src/__tests__/unit/builtins/divide.test.ts | 2 +- src/__tests__/unit/builtins/exponent.test.ts | 2 +- src/__tests__/unit/builtins/export-csv-raw.test.ts | 3 ++- src/__tests__/unit/builtins/export-csv.test.ts | 3 ++- src/__tests__/unit/builtins/export-yaml.test.ts | 2 +- src/__tests__/unit/builtins/group-by.test.ts | 2 +- src/__tests__/unit/builtins/interpolation.test.ts | 4 ++-- src/__tests__/unit/builtins/mock-observations.test.ts | 2 +- src/__tests__/unit/builtins/multiply.test.ts | 2 +- src/__tests__/unit/builtins/regex.test.ts | 2 +- src/__tests__/unit/builtins/sci-embodied.test.ts | 2 +- src/__tests__/unit/builtins/sci.test.ts | 2 +- src/__tests__/unit/builtins/shell.test.ts | 2 +- src/__tests__/unit/builtins/subtract.test.ts | 2 +- src/__tests__/unit/builtins/sum.test.ts | 2 +- src/__tests__/unit/builtins/time-sync.test.ts | 2 +- 20 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/__tests__/unit/builtins/CommonGenerator.test.ts b/src/__tests__/unit/builtins/CommonGenerator.test.ts index 23109c117..b0c165d1a 100644 --- a/src/__tests__/unit/builtins/CommonGenerator.test.ts +++ b/src/__tests__/unit/builtins/CommonGenerator.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {CommonGenerator} from '../../../builtins/mock-observations/helpers/common-generator'; diff --git a/src/__tests__/unit/builtins/RandIntGenerator.test.ts b/src/__tests__/unit/builtins/RandIntGenerator.test.ts index ca1b60183..328f7d6f4 100644 --- a/src/__tests__/unit/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/unit/builtins/RandIntGenerator.test.ts @@ -1,11 +1,9 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {RandIntGenerator} from '../../../builtins/mock-observations/helpers/rand-int-generator'; import {STRINGS} from '../../../config'; -import {KeyValuePair} from '../../../types/common'; - const {GlobalConfigError} = ERRORS; const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; @@ -44,7 +42,7 @@ describe('builtins/mock-observations/RandIntGenerator: ', () => { describe('next(): ', () => { it('returns a result with valid data.', async () => { - const config: KeyValuePair = { + const config: Record = { min: 10, max: 90, }; diff --git a/src/__tests__/unit/builtins/coefficient.test.ts b/src/__tests__/unit/builtins/coefficient.test.ts index e7e92adf5..034d20f95 100644 --- a/src/__tests__/unit/builtins/coefficient.test.ts +++ b/src/__tests__/unit/builtins/coefficient.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Coefficient} from '../../../builtins/coefficient'; diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts index 9e718d537..81e0498b4 100644 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ b/src/__tests__/unit/builtins/csv-lookup.test.ts @@ -2,7 +2,7 @@ jest.mock('fs/promises', () => require('../../../__mocks__/fs')); import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {CSVLookup} from '../../../builtins'; diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts index c75c926be..79fc6c0b5 100644 --- a/src/__tests__/unit/builtins/divide.test.ts +++ b/src/__tests__/unit/builtins/divide.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Divide} from '../../../builtins'; diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts index 04d9f7e9b..c139a5608 100644 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ b/src/__tests__/unit/builtins/exponent.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Exponent} from '../../../builtins/exponent'; diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts index 5ff8d20cd..ab71e0e34 100644 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ b/src/__tests__/unit/builtins/export-csv-raw.test.ts @@ -1,6 +1,7 @@ import * as fs from 'fs/promises'; + import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts index 942732e2e..78feaf534 100644 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ b/src/__tests__/unit/builtins/export-csv.test.ts @@ -1,7 +1,8 @@ import * as fs from 'fs/promises'; + import {stringify} from 'csv-stringify/sync'; import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {ExportCSV} from '../../../builtins/export-csv'; diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts index 56b155cba..fb7954c1e 100644 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ b/src/__tests__/unit/builtins/export-yaml.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {ExportYaml} from '../../../builtins/export-yaml'; import {saveYamlFileAs} from '../../../util/yaml'; diff --git a/src/__tests__/unit/builtins/group-by.test.ts b/src/__tests__/unit/builtins/group-by.test.ts index 22ef77f56..3d676148b 100644 --- a/src/__tests__/unit/builtins/group-by.test.ts +++ b/src/__tests__/unit/builtins/group-by.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {GroupBy} from '../../../builtins/group-by'; diff --git a/src/__tests__/unit/builtins/interpolation.test.ts b/src/__tests__/unit/builtins/interpolation.test.ts index ead5880bb..6219e01ec 100644 --- a/src/__tests__/unit/builtins/interpolation.test.ts +++ b/src/__tests__/unit/builtins/interpolation.test.ts @@ -1,8 +1,8 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {Method} from '@grnsft/if-core/types'; import {Interpolation} from '../../../builtins'; -import {Method} from '../../../builtins/interpolation/types'; import {STRINGS} from '../../../config'; const {InputValidationError, GlobalConfigError} = ERRORS; diff --git a/src/__tests__/unit/builtins/mock-observations.test.ts b/src/__tests__/unit/builtins/mock-observations.test.ts index 7a46cf79f..fd28d5595 100644 --- a/src/__tests__/unit/builtins/mock-observations.test.ts +++ b/src/__tests__/unit/builtins/mock-observations.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {MockObservations} from '../../../builtins/mock-observations'; diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts index ff168110e..f191ae169 100644 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ b/src/__tests__/unit/builtins/multiply.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Multiply} from '../../../builtins/multiply'; diff --git a/src/__tests__/unit/builtins/regex.test.ts b/src/__tests__/unit/builtins/regex.test.ts index 57cdc5e0c..54a70ed9e 100644 --- a/src/__tests__/unit/builtins/regex.test.ts +++ b/src/__tests__/unit/builtins/regex.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Regex} from '../../../builtins/regex'; diff --git a/src/__tests__/unit/builtins/sci-embodied.test.ts b/src/__tests__/unit/builtins/sci-embodied.test.ts index 1d8f05438..a3f5bcbff 100644 --- a/src/__tests__/unit/builtins/sci-embodied.test.ts +++ b/src/__tests__/unit/builtins/sci-embodied.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {SciEmbodied} from '../../../builtins/sci-embodied'; diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts index 751804f17..c12085d4e 100644 --- a/src/__tests__/unit/builtins/sci.test.ts +++ b/src/__tests__/unit/builtins/sci.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Sci} from '../../../builtins/sci'; diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts index 95f44fb12..96de944f1 100644 --- a/src/__tests__/unit/builtins/shell.test.ts +++ b/src/__tests__/unit/builtins/shell.test.ts @@ -1,6 +1,6 @@ import {spawnSync} from 'child_process'; import {loadAll} from 'js-yaml'; -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Shell} from '../../../builtins/shell'; diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts index a1c1e3302..b84b05db8 100644 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ b/src/__tests__/unit/builtins/subtract.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Subtract} from '../../../builtins/subtract'; diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts index 7a09958d1..dbd05a783 100644 --- a/src/__tests__/unit/builtins/sum.test.ts +++ b/src/__tests__/unit/builtins/sum.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Sum} from '../../../builtins/sum'; diff --git a/src/__tests__/unit/builtins/time-sync.test.ts b/src/__tests__/unit/builtins/time-sync.test.ts index 63174743a..6dd984659 100644 --- a/src/__tests__/unit/builtins/time-sync.test.ts +++ b/src/__tests__/unit/builtins/time-sync.test.ts @@ -1,4 +1,4 @@ -import {ERRORS} from '@grnsft/if-core'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Settings, DateTime} from 'luxon'; import {TimeSync} from '../../../builtins/time-sync'; From 5ee388aa73e6dffbb3d12d5a017e74ed1d59d38b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:46:36 +0400 Subject: [PATCH 112/863] test(mocks): introduce if-core types --- src/__mocks__/plugin/lib/mockavizta/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__mocks__/plugin/lib/mockavizta/index.ts b/src/__mocks__/plugin/lib/mockavizta/index.ts index 163a0cd24..54feae6a2 100644 --- a/src/__mocks__/plugin/lib/mockavizta/index.ts +++ b/src/__mocks__/plugin/lib/mockavizta/index.ts @@ -1,4 +1,4 @@ -import {PluginParams} from '../../../../types/interface'; +import {PluginParams} from '@grnsft/if-core/types'; /** * Mock model for testing. From b7a54a1fdbc59381dc17dc8cd07a4df626d281e6 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:46:53 +0400 Subject: [PATCH 113/863] fix(src): fix imports order in diff --- src/diff.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/diff.ts b/src/diff.ts index 71a57ed17..aad02482c 100644 --- a/src/diff.ts +++ b/src/diff.ts @@ -7,10 +7,11 @@ import {parseIfDiffArgs} from './util/args'; import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; import {validateManifest} from './util/validations'; -import {CONFIG} from './config'; import {logger} from './util/logger'; import {debugLogger} from './util/debug-logger'; +import {CONFIG} from './config'; + const {IF_DIFF} = CONFIG; const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; From df7374ad8683ddf20b6368fa3971f5fa4b919c5b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:47:07 +0400 Subject: [PATCH 114/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ec34c515..885d05d11 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.3", + "@grnsft/if-core": "^0.0.7", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1181,9 +1181,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.3.tgz", - "integrity": "sha512-ieuUcadEgA4EztIzCbCW5ifK2a6SUU2ioZtLTce8pJ+imgeQ47lQM3UtChtbaUm52rEwvgl1Psp0ysgOjqssFA==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.7.tgz", + "integrity": "sha512-+4w8Sq1KRPDb+Jy638wgrTXlXIZzewOBceT+rAy3Oaov1M/veY3gu3AV15SXcPHrsBoFmZ6QeI9g1rF3RKB0ww==", "dependencies": { "typescript": "^5.1.6" }, diff --git a/package.json b/package.json index 5093d2235..1846ec684 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.3", + "@grnsft/if-core": "^0.0.7", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 1d39e6b885d974232d9c884dbfbcd0997cc64947 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 17:47:58 +0400 Subject: [PATCH 115/863] chore(config): drop unused module path from jest --- jest.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index ed24da708..2e770bcad 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,7 +12,6 @@ module.exports = { }, modulePathIgnorePatterns: [ './build', - './src/__tests__/unit/lib/manifest', './src/__tests__/integration/helpers', './src/__tests__/integration/test-data', ], From 8857737bdf2aee115fe9d4b3c35c16158d92903a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 19:13:08 +0400 Subject: [PATCH 116/863] revert(config): drop issue template message --- src/config/strings.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 83283e8fb..7efa57a76 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -17,9 +17,6 @@ Incubation projects are experimental, offer no support guarantee, have minimal g NOT_NATIVE_PLUGIN: (path: string) => ` You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, - ISSUE_TEMPLATE: ` -Impact Framework is an alpha release from the Green Software Foundation and is released to capture early feedback. If you'd like to offer some feedback, please use this issue template: -https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+`, INVALID_MODULE_PATH: (path: string, error?: any) => `Provided module \`${path}\` is invalid or not found. ${error ?? ''} `, @@ -55,6 +52,8 @@ Note that for the '--output' option you also need to define the output type in y TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', + UNSUPPORTED_ERROR: (errorName: string) => + `UnsupportedErrorClass: plugin threw error class: ${errorName} that is not recognized by Impact Framework`, /** Plugin messages */ MISSING_GLOBAL_CONFIG: 'Global config is not provided.', MISSING_INPUT_DATA: (param: string) => From 00f0dafda6bed1ce30180a5549de4e7f25618c29 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 19:13:34 +0400 Subject: [PATCH 117/863] test(util): remove changed case --- src/__tests__/unit/util/helpers.test.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 86ea702a4..d8dfe2096 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -30,15 +30,6 @@ describe('util/helpers: ', () => { mockError.mockReset(); }); - it('logs error and warn in case of error is unknown.', () => { - const message = 'mock-message'; - const MockError = class extends Error {}; - - andHandle(new MockError(message)); - expect(mockWarn).toHaveBeenCalledTimes(1); - expect(mockError).toHaveBeenCalledTimes(1); - }); - it('logs error in case of error is unknown.', () => { const message = 'mock-message'; From 3000cc9981c39a006f97e7f25a4cee2a3f57a3e1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 14 Jun 2024 19:14:32 +0400 Subject: [PATCH 118/863] feat(util): exit on unknown error --- src/util/helpers.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index fcab2e27a..0c422c96f 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -10,7 +10,7 @@ import {STRINGS} from '../config'; import {Difference} from '../types/lib/compare'; -const {ISSUE_TEMPLATE} = STRINGS; +const {UNSUPPORTED_ERROR} = STRINGS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -21,7 +21,9 @@ export const andHandle = (error: Error) => { logger.error(error); if (!knownErrors.includes(error.name)) { - logger.warn(ISSUE_TEMPLATE); + logger.error(UNSUPPORTED_ERROR(error.name)); + // eslint-disable-next-line no-process-exit + process.exit(2); } }; From 1e04a0ecf6dd3acccb1a2e4ae6210d0ab62f570a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 17 Jun 2024 15:28:19 +0400 Subject: [PATCH 119/863] fix(src): get all dependencies from the manifest file --- src/env.ts | 70 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/env.ts b/src/env.ts index 5128f58d4..5e2dba498 100644 --- a/src/env.ts +++ b/src/env.ts @@ -26,9 +26,9 @@ const { const IfEnv = async () => { const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { - folderPath: __dirname, + folderPath: process.cwd(), install: !!commandArgs.install, - dependencies: {'@grnsft/if': packageJson.version}, + dependencies: {}, }; if (commandArgs && commandArgs.manifest) { @@ -57,11 +57,8 @@ const getOptionsFromArgs = async (commandArgs: { install: boolean | undefined; }) => { const {manifest: manifestPath, install} = commandArgs; - const folderPath = path.dirname(manifestPath); - const manifest = await load(manifestPath); - const plugins = manifest.rawManifest?.initialize?.plugins || {}; const dependencies = manifest.rawManifest?.execution?.environment.dependencies || []; @@ -69,7 +66,7 @@ const getOptionsFromArgs = async (commandArgs: { throw new Error(FAILURE_MESSAGE_DEPENDENCIES); } - const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); + const pathsWithVersion = extractPathsWithVersion(dependencies); return { folderPath, @@ -81,25 +78,21 @@ const getOptionsFromArgs = async (commandArgs: { /** * Gets depencecies with versions. */ -const extractPathsWithVersion = (plugins: any, dependencies: string[]) => { - const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); - const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); +const extractPathsWithVersion = (dependencies: string[]) => { const pathsWithVersion: PathWithVersion = {}; - uniquePaths.forEach(pluginPath => { - const dependency = dependencies.find((dependency: string) => - dependency.startsWith(pluginPath) - ); - - if (dependency) { - const splittedDependency = dependency.split('@'); - const version = - splittedDependency.length > 2 - ? splittedDependency[2].split(' ')[0] - : splittedDependency[1]; - - pathsWithVersion[pluginPath] = `^${version}`; - } + dependencies.forEach(dependency => { + const splittedDependency = dependency.split('@'); + const packageName = + splittedDependency.length > 2 + ? `@${splittedDependency[1]}` + : `@${splittedDependency[0]}`; + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[packageName] = `^${version}`; }); return pathsWithVersion; @@ -112,9 +105,14 @@ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { try { const {folderPath, install, dependencies} = options; + if (!Object.keys(dependencies).length) { + throw new Error(FAILURE_MESSAGE_DEPENDENCIES); + } + await fs.mkdir(folderPath, {recursive: true}); const packageJsonPath = await initPackageJsonIfNotExists(folderPath); + await updatePackageJsonProperties(packageJsonPath); if (install) { await installDependencies(folderPath, dependencies); @@ -123,9 +121,35 @@ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { } } catch (error) { console.log(FAILURE_MESSAGE); + process.exit(2); } }; +/** + * Update the package.json properties. + */ +const updatePackageJsonProperties = async (packageJsonPath: string) => { + const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); + const parsedPackageJsonContent = JSON.parse(packageJsonContent); + + const properties = { + name: 'if-environment', + description: packageJson.description, + author: packageJson.author, + bugs: packageJson.bugs, + engines: packageJson.engines, + homepage: packageJson.homepage, + }; + + const newPackageJson = Object.assign( + {}, + parsedPackageJsonContent, + properties + ); + + await fs.writeFile(packageJsonPath, JSON.stringify(newPackageJson, null, 2)); +}; + /** * Updates package.json dependencies. */ From 22febb1eda96d131ba4149378d82f573c28fae60 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 18 Jun 2024 11:17:02 +0400 Subject: [PATCH 120/863] chore(src): fetch changes from remote --- manifests/plugins/csv-lookup/success.yml | 2 +- manifests/plugins/divide/success.yml | 2 +- manifests/plugins/sum/success.yml | 2 +- package-lock.json | 19 +++++++++++++++++++ package.json | 2 +- src/env.ts | 1 + src/util/helpers.ts | 1 - 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/manifests/plugins/csv-lookup/success.yml b/manifests/plugins/csv-lookup/success.yml index f57b4718a..c6fc07d7b 100644 --- a/manifests/plugins/csv-lookup/success.yml +++ b/manifests/plugins/csv-lookup/success.yml @@ -23,4 +23,4 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 cloud/provider: Google Cloud - cloud/region: asia-east-1 + cloud/region: asia-east1 diff --git a/manifests/plugins/divide/success.yml b/manifests/plugins/divide/success.yml index ed75a7c5c..d9840205a 100644 --- a/manifests/plugins/divide/success.yml +++ b/manifests/plugins/divide/success.yml @@ -2,7 +2,7 @@ name: divide description: success path tags: initialize: -# outputs: ['yaml'] + outputs: ['yaml'] plugins: cloud-metadata: method: CloudMetadata diff --git a/manifests/plugins/sum/success.yml b/manifests/plugins/sum/success.yml index fc0661bf5..454efc9e0 100644 --- a/manifests/plugins/sum/success.yml +++ b/manifests/plugins/sum/success.yml @@ -2,7 +2,7 @@ name: sum description: successful path tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: sum: method: Sum diff --git a/package-lock.json b/package-lock.json index e42ff4db5..73687b54f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -3772,6 +3773,24 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "license": "MIT", diff --git a/package.json b/package.json index 3bb7cb5c4..a9d044f33 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "fix:package": "fixpack", "if-diff": "npx ts-node src/diff.ts", "if-run": "npx ts-node src/index.ts", - "if-env": "npx ts-node src/env.ts", + "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", diff --git a/src/env.ts b/src/env.ts index 5128f58d4..92f563e38 100644 --- a/src/env.ts +++ b/src/env.ts @@ -24,6 +24,7 @@ const { } = IF_ENV; const IfEnv = async () => { + console.log(process.env.CURRENT_DIR); const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { folderPath: __dirname, diff --git a/src/util/helpers.ts b/src/util/helpers.ts index a2c69e0ea..9cac1f9d9 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,6 +1,5 @@ import * as fs from 'fs/promises'; import * as path from 'path'; - import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; From be0862bfd373107d8baeabf88df7f19e94e81120 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 18 Jun 2024 11:22:21 +0400 Subject: [PATCH 121/863] feat(package): init cross env --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a9d044f33..81a4d33e1 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -75,8 +76,8 @@ "fix": "gts fix", "fix:package": "fixpack", "if-diff": "npx ts-node src/diff.ts", - "if-run": "npx ts-node src/index.ts", "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", + "if-run": "npx ts-node src/index.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", From 4a8a962341ab409e39e54823db3a82c6a7f5c279 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 18 Jun 2024 14:04:33 +0400 Subject: [PATCH 122/863] fix(src): fix getting command working directory --- package-lock.json | 19 +++++++++++++++++++ package.json | 3 ++- src/env.ts | 10 ++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e42ff4db5..73687b54f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -3772,6 +3773,24 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "license": "MIT", diff --git a/package.json b/package.json index 3bb7cb5c4..81a4d33e1 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -75,8 +76,8 @@ "fix": "gts fix", "fix:package": "fixpack", "if-diff": "npx ts-node src/diff.ts", + "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", "if-run": "npx ts-node src/index.ts", - "if-env": "npx ts-node src/env.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", diff --git a/src/env.ts b/src/env.ts index 5e2dba498..12f29d903 100644 --- a/src/env.ts +++ b/src/env.ts @@ -24,9 +24,10 @@ const { } = IF_ENV; const IfEnv = async () => { + console.log(process.env.CURRENT_DIR); const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { - folderPath: process.cwd(), + folderPath: process.env.CURRENT_DIR || process.cwd(), install: !!commandArgs.install, dependencies: {}, }; @@ -36,7 +37,12 @@ const IfEnv = async () => { await getOptionsFromArgs(commandArgs); options.folderPath = folderPath; options.install = !!install; - options.dependencies = {...options.dependencies, ...dependencies}; + options.dependencies = {...dependencies}; + } else { + options.dependencies = { + ...packageJson.depencecies, + ...packageJson.devDependencies, + }; } await initializeAndInstallLibs(options); From aebd849a617bbd0b600727ceb72bafe7766c5c7b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 14:39:58 +0400 Subject: [PATCH 123/863] feat(types): add `cmd` property to IFEnvArgs type --- src/types/process-args.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 6b8cfc050..83561e55c 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -14,6 +14,7 @@ export interface IFDiffArgs { export interface IFEnvArgs { manifest?: string; install?: boolean; + cmd?: boolean; } export interface Options { From d6f4280e366d3296434a2ab5f1784ab5c3ea2eaa Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 14:41:27 +0400 Subject: [PATCH 124/863] feat(config): add `cmd` flag for if-env --- src/config/config.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index cbd389ff2..13acbd9b0 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -95,7 +95,14 @@ export const CONFIG = { type: Boolean, optional: true, alias: 'i', - description: '[commant to install package.json]', + description: '[command to install package.json]', + }, + cmd: { + type: Boolean, + optional: true, + alias: 'c', + description: + '[command to generate the package.json in the command working directory]', }, } as ArgumentConfig, HELP: { From c9fc62b59fa62547a80dadc681d3c793fa444128 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 14:49:21 +0400 Subject: [PATCH 125/863] feat(util): update parseIfEnvArgs function to add cmd flag --- src/util/args.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 013b94a83..3f7d2c066 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -173,7 +173,7 @@ const validateAndParseIfEnvArgs = () => { * Checks if the `manifest` command is provided and it is valid manifest file. */ export const parseIfEnvArgs = async () => { - const {manifest, install} = validateAndParseIfEnvArgs(); + const {manifest, install, cmd} = validateAndParseIfEnvArgs(); if (manifest) { const isManifestFileExists = await isFileExists(manifest); @@ -185,11 +185,11 @@ export const parseIfEnvArgs = async () => { if (checkIfFileIsYaml(manifest)) { const response = prependFullFilePath(manifest); - return {manifest: response, install}; + return {manifest: response, install, cmd}; } throw new CliInputError(FILE_IS_NOT_YAML); } - return {install}; + return {install, cmd}; }; From a2dd0227af2d1bcfc70452201b59a6b6c5a98da2 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 14:51:17 +0400 Subject: [PATCH 126/863] feat(types): add cmd property into EnvironmentOptions type and add ManifestPlugin type --- src/types/if-env.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/if-env.ts b/src/types/if-env.ts index b8a63f7ef..547787cea 100644 --- a/src/types/if-env.ts +++ b/src/types/if-env.ts @@ -1,7 +1,10 @@ export type EnvironmentOptions = { folderPath: string; install: boolean; + cmd: boolean; dependencies: {[path: string]: string}; }; export type PathWithVersion = {[path: string]: string}; + +export type ManifestPlugin = {[key: string]: {path: string; method: string}}; From ff443915a3b3eeec8a36b7b0d9268e51306b3bdb Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 14:53:21 +0400 Subject: [PATCH 127/863] fix(src): add cmd flag, fix template manifest directory and package.json depencencies --- src/env.ts | 84 +++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/src/env.ts b/src/env.ts index 12f29d903..5a9f3bd8f 100644 --- a/src/env.ts +++ b/src/env.ts @@ -11,7 +11,11 @@ import {load} from './lib/load'; import {CONFIG} from './config'; -import {EnvironmentOptions, PathWithVersion} from './types/if-env'; +import { + EnvironmentOptions, + ManifestPlugin, + PathWithVersion, +} from './types/if-env'; const packageJson = require('../package.json'); @@ -24,31 +28,26 @@ const { } = IF_ENV; const IfEnv = async () => { - console.log(process.env.CURRENT_DIR); const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { folderPath: process.env.CURRENT_DIR || process.cwd(), install: !!commandArgs.install, dependencies: {}, + cmd: !!commandArgs.cmd, }; if (commandArgs && commandArgs.manifest) { const {folderPath, install, dependencies} = await getOptionsFromArgs(commandArgs); - options.folderPath = folderPath; + options.folderPath = commandArgs.cmd ? options.folderPath : folderPath; options.install = !!install; options.dependencies = {...dependencies}; - } else { - options.dependencies = { - ...packageJson.depencecies, - ...packageJson.devDependencies, - }; } await initializeAndInstallLibs(options); if (!commandArgs || !commandArgs.manifest) { - await addTemplateManifest(); + await addTemplateManifest(options.folderPath); } console.log(SUCCESS_MESSAGE); @@ -65,6 +64,7 @@ const getOptionsFromArgs = async (commandArgs: { const {manifest: manifestPath, install} = commandArgs; const folderPath = path.dirname(manifestPath); const manifest = await load(manifestPath); + const plugins = manifest.rawManifest?.initialize?.plugins || {}; const dependencies = manifest.rawManifest?.execution?.environment.dependencies || []; @@ -72,7 +72,7 @@ const getOptionsFromArgs = async (commandArgs: { throw new Error(FAILURE_MESSAGE_DEPENDENCIES); } - const pathsWithVersion = extractPathsWithVersion(dependencies); + const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); return { folderPath, @@ -84,21 +84,28 @@ const getOptionsFromArgs = async (commandArgs: { /** * Gets depencecies with versions. */ -const extractPathsWithVersion = (dependencies: string[]) => { +const extractPathsWithVersion = ( + plugins: ManifestPlugin, + dependencies: string[] +) => { + const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); + const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); const pathsWithVersion: PathWithVersion = {}; - dependencies.forEach(dependency => { - const splittedDependency = dependency.split('@'); - const packageName = - splittedDependency.length > 2 - ? `@${splittedDependency[1]}` - : `@${splittedDependency[0]}`; - const version = - splittedDependency.length > 2 - ? splittedDependency[2].split(' ')[0] - : splittedDependency[1]; - - pathsWithVersion[packageName] = `^${version}`; + uniquePaths.forEach(pluginPath => { + const dependency = dependencies.find((dependency: string) => + dependency.startsWith(pluginPath) + ); + + if (dependency) { + const splittedDependency = dependency.split('@'); + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[pluginPath] = `^${version}`; + } }); return pathsWithVersion; @@ -109,21 +116,15 @@ const extractPathsWithVersion = (dependencies: string[]) => { */ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { try { - const {folderPath, install, dependencies} = options; - - if (!Object.keys(dependencies).length) { - throw new Error(FAILURE_MESSAGE_DEPENDENCIES); - } - - await fs.mkdir(folderPath, {recursive: true}); - + const {folderPath, install, cmd, dependencies} = options; const packageJsonPath = await initPackageJsonIfNotExists(folderPath); + await updatePackageJsonProperties(packageJsonPath); if (install) { await installDependencies(folderPath, dependencies); } else { - await updatePackageJsonDependencies(packageJsonPath, dependencies); + await updatePackageJsonDependencies(packageJsonPath, dependencies, cmd); } } catch (error) { console.log(FAILURE_MESSAGE); @@ -161,15 +162,20 @@ const updatePackageJsonProperties = async (packageJsonPath: string) => { */ const updatePackageJsonDependencies = async ( packageJsonPath: string, - dependencies: PathWithVersion + dependencies: PathWithVersion, + cmd: boolean ) => { const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); const packageJson = JSON.parse(packageJsonContent); - packageJson.dependencies = { - ...packageJson.dependencies, - ...dependencies, - }; + if (cmd) { + packageJson.dependencies = { + ...packageJson.dependencies, + ...dependencies, + }; + } else { + packageJson.dependencies = {...dependencies}; + } await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); }; @@ -177,10 +183,10 @@ const updatePackageJsonDependencies = async ( /** * Adds a manifest template to the folder where the if-env CLI command runs. */ -const addTemplateManifest = async () => { +const addTemplateManifest = async (destinationDir: string) => { try { const templateManifest = path.resolve(__dirname, './env-template.yml'); - const destinationPath = path.resolve(__dirname, 'manifest.yml'); + const destinationPath = path.resolve(destinationDir, 'manifest.yml'); const data = await fs.readFile(templateManifest, 'utf-8'); await fs.writeFile(destinationPath, '', 'utf-8'); From f1b204aaa0df73a70e7da1b32fa5d93576ebe951 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 15:13:43 +0400 Subject: [PATCH 128/863] fix(src): rename `cmd` to `cwd` --- src/config/config.ts | 2 +- src/env.ts | 12 ++++++------ src/types/if-env.ts | 2 +- src/types/process-args.ts | 2 +- src/util/args.ts | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index 13acbd9b0..0f96019f2 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -97,7 +97,7 @@ export const CONFIG = { alias: 'i', description: '[command to install package.json]', }, - cmd: { + cwd: { type: Boolean, optional: true, alias: 'c', diff --git a/src/env.ts b/src/env.ts index 5a9f3bd8f..e2232d8f4 100644 --- a/src/env.ts +++ b/src/env.ts @@ -33,13 +33,13 @@ const IfEnv = async () => { folderPath: process.env.CURRENT_DIR || process.cwd(), install: !!commandArgs.install, dependencies: {}, - cmd: !!commandArgs.cmd, + cwd: !!commandArgs.cwd, }; if (commandArgs && commandArgs.manifest) { const {folderPath, install, dependencies} = await getOptionsFromArgs(commandArgs); - options.folderPath = commandArgs.cmd ? options.folderPath : folderPath; + options.folderPath = commandArgs.cwd ? options.folderPath : folderPath; options.install = !!install; options.dependencies = {...dependencies}; } @@ -116,7 +116,7 @@ const extractPathsWithVersion = ( */ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { try { - const {folderPath, install, cmd, dependencies} = options; + const {folderPath, install, cwd, dependencies} = options; const packageJsonPath = await initPackageJsonIfNotExists(folderPath); await updatePackageJsonProperties(packageJsonPath); @@ -124,7 +124,7 @@ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { if (install) { await installDependencies(folderPath, dependencies); } else { - await updatePackageJsonDependencies(packageJsonPath, dependencies, cmd); + await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); } } catch (error) { console.log(FAILURE_MESSAGE); @@ -163,12 +163,12 @@ const updatePackageJsonProperties = async (packageJsonPath: string) => { const updatePackageJsonDependencies = async ( packageJsonPath: string, dependencies: PathWithVersion, - cmd: boolean + cwd: boolean ) => { const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); const packageJson = JSON.parse(packageJsonContent); - if (cmd) { + if (cwd) { packageJson.dependencies = { ...packageJson.dependencies, ...dependencies, diff --git a/src/types/if-env.ts b/src/types/if-env.ts index 547787cea..796fd0ca8 100644 --- a/src/types/if-env.ts +++ b/src/types/if-env.ts @@ -1,7 +1,7 @@ export type EnvironmentOptions = { folderPath: string; install: boolean; - cmd: boolean; + cwd: boolean; dependencies: {[path: string]: string}; }; diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 83561e55c..40dece54d 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -14,7 +14,7 @@ export interface IFDiffArgs { export interface IFEnvArgs { manifest?: string; install?: boolean; - cmd?: boolean; + cwd?: boolean; } export interface Options { diff --git a/src/util/args.ts b/src/util/args.ts index 3f7d2c066..fce459016 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -173,7 +173,7 @@ const validateAndParseIfEnvArgs = () => { * Checks if the `manifest` command is provided and it is valid manifest file. */ export const parseIfEnvArgs = async () => { - const {manifest, install, cmd} = validateAndParseIfEnvArgs(); + const {manifest, install, cwd} = validateAndParseIfEnvArgs(); if (manifest) { const isManifestFileExists = await isFileExists(manifest); @@ -185,11 +185,11 @@ export const parseIfEnvArgs = async () => { if (checkIfFileIsYaml(manifest)) { const response = prependFullFilePath(manifest); - return {manifest: response, install, cmd}; + return {manifest: response, install, cwd}; } throw new CliInputError(FILE_IS_NOT_YAML); } - return {install, cmd}; + return {install, cwd}; }; From 6819c5c487a47dd5a68ae64aec41875d8f0e395d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:23:07 +0100 Subject: [PATCH 129/863] fix(lib): fix import for error strings --- src/config/strings.ts | 8 +++++--- src/util/helpers.ts | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 7efa57a76..caf8d2bb0 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -1,4 +1,4 @@ -import {ManifestParameter} from '../types/manifest'; +import { ManifestParameter } from '../types/manifest'; export const STRINGS = { FILE_IS_NOT_YAML: 'Provided manifest is not in yaml format.', @@ -27,8 +27,7 @@ You are using plugin ${path} which is not part of the Impact Framework standard AVOIDING_PADDING: (description: string) => `Avoiding padding at ${description}`, AVOIDING_PADDING_BY_EDGES: (start: boolean, end: boolean) => - `Avoiding padding at ${ - start && end ? 'start and end' : start ? 'start' : 'end' + `Avoiding padding at ${start && end ? 'start and end' : start ? 'start' : 'end' }`, INVALID_AGGREGATION_METHOD: (metric: string) => `Aggregation is not possible for given ${metric} since method is 'none'.`, @@ -58,6 +57,9 @@ Note that for the '--output' option you also need to define the output type in y MISSING_GLOBAL_CONFIG: 'Global config is not provided.', MISSING_INPUT_DATA: (param: string) => `${param} is missing from the input array.`, + MANIFEST_NOT_FOUND: 'Manifest file not found.', + INITIALIZING_PACKAGE_JSON: 'Initializing package.json.', + INSTALLING_NPM_PACKAGES: 'Installing npm packages...', NOT_NUMERIC_VALUE: (str: any) => `${str} is not numberic.`, MISSING_FUNCTIONAL_UNIT_CONFIG: '`functional-unit` should be provided in your global config', diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 98af5209d..cc61f93ac 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,18 +1,18 @@ import * as fs from 'fs/promises'; import * as path from 'path'; -import {createInterface} from 'node:readline/promises'; -import {exec} from 'node:child_process'; -import {promisify} from 'node:util'; +import { createInterface } from 'node:readline/promises'; +import { exec } from 'node:child_process'; +import { promisify } from 'node:util'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { ERRORS } from '@grnsft/if-core/utils'; -import {logger} from './logger'; +import { logger } from './logger'; -import {STRINGS} from '../config'; +import { STRINGS } from '../config'; -import {Difference} from '../types/lib/compare'; +import { Difference } from '../types/lib/compare'; -const {UNSUPPORTED_ERROR} = STRINGS; +const { UNSUPPORTED_ERROR, INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES } = STRINGS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -200,7 +200,7 @@ export const initPackageJsonIfNotExists = async (folderPath: string) => { if (!isPackageJsonExists) { logger.info(INITIALIZING_PACKAGE_JSON); - await execPromise('npm init -y', {cwd: folderPath}); + await execPromise('npm init -y', { cwd: folderPath }); } return packageJsonPath; @@ -211,7 +211,7 @@ export const initPackageJsonIfNotExists = async (folderPath: string) => { */ export const installDependencies = async ( folderPath: string, - dependencies: {[path: string]: string} + dependencies: { [path: string]: string } ) => { const packages = Object.entries(dependencies).map( ([dependency, version]) => `${dependency}@${version.replace('^', '')}` From c9b6db6eba04f4b3e3943584e4c3549451962a0d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:23:54 +0100 Subject: [PATCH 130/863] fix(lib): apply linter --- src/config/strings.ts | 5 +++-- src/util/helpers.ts | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index caf8d2bb0..bf57a11d5 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -1,4 +1,4 @@ -import { ManifestParameter } from '../types/manifest'; +import {ManifestParameter} from '../types/manifest'; export const STRINGS = { FILE_IS_NOT_YAML: 'Provided manifest is not in yaml format.', @@ -27,7 +27,8 @@ You are using plugin ${path} which is not part of the Impact Framework standard AVOIDING_PADDING: (description: string) => `Avoiding padding at ${description}`, AVOIDING_PADDING_BY_EDGES: (start: boolean, end: boolean) => - `Avoiding padding at ${start && end ? 'start and end' : start ? 'start' : 'end' + `Avoiding padding at ${ + start && end ? 'start and end' : start ? 'start' : 'end' }`, INVALID_AGGREGATION_METHOD: (metric: string) => `Aggregation is not possible for given ${metric} since method is 'none'.`, diff --git a/src/util/helpers.ts b/src/util/helpers.ts index cc61f93ac..9abcf9ba4 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,18 +1,19 @@ import * as fs from 'fs/promises'; import * as path from 'path'; -import { createInterface } from 'node:readline/promises'; -import { exec } from 'node:child_process'; -import { promisify } from 'node:util'; +import {createInterface} from 'node:readline/promises'; +import {exec} from 'node:child_process'; +import {promisify} from 'node:util'; -import { ERRORS } from '@grnsft/if-core/utils'; +import {ERRORS} from '@grnsft/if-core/utils'; -import { logger } from './logger'; +import {logger} from './logger'; -import { STRINGS } from '../config'; +import {STRINGS} from '../config'; -import { Difference } from '../types/lib/compare'; +import {Difference} from '../types/lib/compare'; -const { UNSUPPORTED_ERROR, INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES } = STRINGS; +const {UNSUPPORTED_ERROR, INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = + STRINGS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -200,7 +201,7 @@ export const initPackageJsonIfNotExists = async (folderPath: string) => { if (!isPackageJsonExists) { logger.info(INITIALIZING_PACKAGE_JSON); - await execPromise('npm init -y', { cwd: folderPath }); + await execPromise('npm init -y', {cwd: folderPath}); } return packageJsonPath; @@ -211,7 +212,7 @@ export const initPackageJsonIfNotExists = async (folderPath: string) => { */ export const installDependencies = async ( folderPath: string, - dependencies: { [path: string]: string } + dependencies: {[path: string]: string} ) => { const packages = Object.entries(dependencies).map( ([dependency, version]) => `${dependency}@${version.replace('^', '')}` From 39931f516b08bb6a50bdf39a4ff24743857d3d7a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 19 Jun 2024 17:22:31 +0400 Subject: [PATCH 131/863] fix(util): optimize error classes usage in args --- src/util/args.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index c54117c75..523791f2a 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -11,17 +11,11 @@ import {CONFIG, STRINGS} from '../config'; import {IFDiffArgs, IEArgs, ProcessArgsOutputs} from '../types/process-args'; import {LoadDiffParams} from '../types/util/args'; -const { - CliInputError, - ParseCliParamsError, - CliTargetFileError, - CliSourceFileError, -} = ERRORS; +const {ParseCliParamsError, CliTargetFileError, CliSourceFileError} = ERRORS; const {IE, IF_DIFF} = CONFIG; const { - FILE_IS_NOT_YAML, MANIFEST_IS_MISSING, NO_OUTPUT, SOURCE_IS_NOT_YAML, @@ -37,7 +31,7 @@ const validateAndParseProcessArgs = () => { return parse(IE.ARGS, IE.HELP); } catch (error) { if (error instanceof Error) { - throw new CliInputError(error.message); + throw new ParseCliParamsError(error.message); } throw error; @@ -63,7 +57,7 @@ const prependFullFilePath = (filePath: string) => { * 3. If output params are missing, warns user about it. * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. * If it is, then returns object containing full path. - * 4. If params are missing or invalid, then rejects with `CliInputError`. + * 4. If params are missing or invalid, then rejects with `ParseCliParamsError`. */ export const parseIEProcessArgs = (): ProcessArgsOutputs => { const { @@ -91,7 +85,7 @@ export const parseIEProcessArgs = (): ProcessArgsOutputs => { }; } - throw new CliSourceFileError(FILE_IS_NOT_YAML); + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); } throw new CliSourceFileError(MANIFEST_IS_MISSING); @@ -140,5 +134,5 @@ export const parseIfDiffArgs = () => { throw new CliTargetFileError(TARGET_IS_NOT_YAML); } - throw new CliInputError(INVALID_TARGET); + throw new ParseCliParamsError(INVALID_TARGET); }; From d235e6fe1cc68b76ecd1d45bfdf913fadad4a18d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 19 Jun 2024 18:11:21 +0400 Subject: [PATCH 132/863] fix(config): drop unused string, fix typo --- src/config/strings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 7efa57a76..82e6d388b 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -1,7 +1,6 @@ import {ManifestParameter} from '../types/manifest'; export const STRINGS = { - FILE_IS_NOT_YAML: 'Provided manifest is not in yaml format.', MANIFEST_IS_MISSING: 'Manifest is missing.', MISSING_METHOD: "Initalization param 'method' is missing.", MISSING_PATH: "Initalization param 'path' is missing.", @@ -49,7 +48,7 @@ You have not selected an output method. To see your output data, you can choose --output : this will save your output data to the given filepath (do not provide file extension) Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`, SOURCE_IS_NOT_YAML: 'Given source file is not in yaml format.', - TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', + TARGET_IS_NOT_YAML: 'Given target file is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', UNSUPPORTED_ERROR: (errorName: string) => From 990a7c7016ba578f20db28c43573560c665875f0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 19 Jun 2024 18:11:53 +0400 Subject: [PATCH 133/863] test(util): apply specific errors to args --- src/__tests__/unit/util/args.test.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index 045bf2807..61c8c4577 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -76,11 +76,10 @@ import {parseIEProcessArgs, parseIfDiffArgs} from '../../../util/args'; import {STRINGS} from '../../../config'; -const {CliInputError, CliSourceFileError} = ERRORS; +const {CliSourceFileError, ParseCliParamsError} = ERRORS; const { MANIFEST_IS_MISSING, - FILE_IS_NOT_YAML, TARGET_IS_NOT_YAML, INVALID_TARGET, SOURCE_IS_NOT_YAML, @@ -106,8 +105,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(MANIFEST_IS_MISSING)); + expect(error).toBeInstanceOf(ParseCliParamsError); + expect(error).toEqual(new ParseCliParamsError(MANIFEST_IS_MISSING)); } process.env.result = 'manifest-is-missing'; @@ -196,7 +195,7 @@ describe('util/args: ', () => { parseIEProcessArgs(); } catch (error) { expect(error).toBeInstanceOf(CliSourceFileError); - expect(error).toEqual(new CliSourceFileError(FILE_IS_NOT_YAML)); + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); } }); @@ -226,7 +225,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(INVALID_TARGET)); + expect(error).toEqual(new ParseCliParamsError(INVALID_TARGET)); } } }); @@ -239,7 +238,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(TARGET_IS_NOT_YAML)); + expect(error).toEqual(new ParseCliParamsError(TARGET_IS_NOT_YAML)); } } }); @@ -260,7 +259,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(SOURCE_IS_NOT_YAML)); + expect(error).toEqual(new ParseCliParamsError(SOURCE_IS_NOT_YAML)); } } }); @@ -282,7 +281,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError('mock-error')); + expect(error).toEqual(new ParseCliParamsError('mock-error')); } } }); From 3c09a5002723ea4ab1f094b903b26472e56f344d Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 18:56:42 +0400 Subject: [PATCH 134/863] fix(config): move template manifest into config directory --- src/{ => config}/env-template.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => config}/env-template.yml (100%) diff --git a/src/env-template.yml b/src/config/env-template.yml similarity index 100% rename from src/env-template.yml rename to src/config/env-template.yml From 14b2b38bf20a8b63ba1bf736024bbb12777f8092 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 19 Jun 2024 18:57:49 +0400 Subject: [PATCH 135/863] fix(src): update template manifest path --- src/env.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/env.ts b/src/env.ts index e2232d8f4..759ae0be5 100644 --- a/src/env.ts +++ b/src/env.ts @@ -185,7 +185,10 @@ const updatePackageJsonDependencies = async ( */ const addTemplateManifest = async (destinationDir: string) => { try { - const templateManifest = path.resolve(__dirname, './env-template.yml'); + const templateManifest = path.resolve( + __dirname, + './config/env-template.yml' + ); const destinationPath = path.resolve(destinationDir, 'manifest.yml'); const data = await fs.readFile(templateManifest, 'utf-8'); From a6a8b320068584d68bb8fe860240c230dbcb6d38 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 20 Jun 2024 12:40:47 +0400 Subject: [PATCH 136/863] fix(manifests): update bugs to use builtins --- .../bugs/aggregation-error-wrong-metric.yml | 24 ++++++++++++------- .../bugs/azure-importer-ignoring-defaults.yml | 9 ++++--- .../azure-importer-incorrect-calculation.yml | 9 ++++--- manifests/bugs/pipeline-ordering-error.yml | 11 +++++---- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml index e9a9af6ea..f95a9eed7 100644 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ b/manifests/bugs/aggregation-error-wrong-metric.yml @@ -12,15 +12,23 @@ initialize: method: TeadsCurve global-config: interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + "sum-energy-components": + path: "builtin" + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci @@ -43,9 +51,9 @@ tree: child-1: pipeline: - teads-curve - - sci-e + - sum-energy-components - sci-embodied - - sci-o + - operational-carbon - time-sync - sci config: diff --git a/manifests/bugs/azure-importer-ignoring-defaults.yml b/manifests/bugs/azure-importer-ignoring-defaults.yml index 424be5e84..b6749ee70 100644 --- a/manifests/bugs/azure-importer-ignoring-defaults.yml +++ b/manifests/bugs/azure-importer-ignoring-defaults.yml @@ -28,9 +28,12 @@ initialize: input-parameter: network/energy coefficient: 1000 output-parameter: network/energy - "sci-o": - method: SciO - path: "@grnsft/if-plugins" + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "group-by": path: "builtin" method: GroupBy diff --git a/manifests/bugs/azure-importer-incorrect-calculation.yml b/manifests/bugs/azure-importer-incorrect-calculation.yml index fa4cc17d0..bbac70ae2 100644 --- a/manifests/bugs/azure-importer-incorrect-calculation.yml +++ b/manifests/bugs/azure-importer-incorrect-calculation.yml @@ -20,9 +20,12 @@ initialize: input-parameter: network/energy coefficient: 1000 output-parameter: network/energy - sci-o: - path: '@grnsft/if-plugins' - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" group-by: path: builtin method: GroupBy diff --git a/manifests/bugs/pipeline-ordering-error.yml b/manifests/bugs/pipeline-ordering-error.yml index 3538465ea..554134287 100644 --- a/manifests/bugs/pipeline-ordering-error.yml +++ b/manifests/bugs/pipeline-ordering-error.yml @@ -19,9 +19,12 @@ initialize: "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu/energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci @@ -41,7 +44,7 @@ tree: child-1: pipeline: - teads-curve - - sci-o + - operational-carbon - sum - sci-embodied - time-sync From ec099f839f0c273bd3c47af36c8da7939f4fa099 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 20 Jun 2024 12:42:45 +0400 Subject: [PATCH 137/863] fix(manifests): update examples to use builtins --- manifests/examples/basic.yml | 28 --- manifests/examples/instance-metadata.yml | 25 +-- .../examples/mock-cpu-util-to-carbon.yml | 10 +- manifests/examples/nesting.yml | 11 +- manifests/examples/pipeline-teads-sci.yml | 11 +- .../examples/pipeline-with-aggregate.yml | 178 +++++++++++------- manifests/examples/pipeline-with-mocks.yml | 169 ++++++++++------- 7 files changed, 240 insertions(+), 192 deletions(-) delete mode 100644 manifests/examples/basic.yml diff --git a/manifests/examples/basic.yml b/manifests/examples/basic.yml deleted file mode 100644 index e737f5d5b..000000000 --- a/manifests/examples/basic.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: basic -description: a minimal manifest executing a single plugin on a single component for a single timestep -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/examples/instance-metadata.yml b/manifests/examples/instance-metadata.yml index c3e514773..ea0998241 100644 --- a/manifests/examples/instance-metadata.yml +++ b/manifests/examples/instance-metadata.yml @@ -1,23 +1,6 @@ name: csv-demo -<<<<<<< add-tdp-manifest description: tags: -initialize: - plugins: - cloud-instance-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: "cloud/instance-type" - output: "*" - extract-processor-name: - method: Regex - path: "builtin" -======= -description: null -tags: null initialize: plugins: cloud-instance-metadata: @@ -32,16 +15,12 @@ initialize: extract-processor-name: path: builtin method: Regex ->>>>>>> main global-config: parameter: cpu-model-name match: /^([^,])+/g output: cpu/name -<<<<<<< add-tdp-manifest -======= - outputs: - - yaml ->>>>>>> main + # outputs: + # - yaml tree: children: child: diff --git a/manifests/examples/mock-cpu-util-to-carbon.yml b/manifests/examples/mock-cpu-util-to-carbon.yml index 35f7cea26..64e6d6719 100644 --- a/manifests/examples/mock-cpu-util-to-carbon.yml +++ b/manifests/examples/mock-cpu-util-to-carbon.yml @@ -21,8 +21,14 @@ initialize: global-config: interpolation: spline cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] mock-observations: path: 'builtin' method: MockObservations diff --git a/manifests/examples/nesting.yml b/manifests/examples/nesting.yml index e56e8bb18..a5bf89230 100644 --- a/manifests/examples/nesting.yml +++ b/manifests/examples/nesting.yml @@ -29,9 +29,12 @@ initialize: sci-embodied: path: "builtin" method: SciEmbodied - sci-o: - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" sci: path: "builtin" method: Sci @@ -68,7 +71,7 @@ tree: - teads-curve - sum - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci diff --git a/manifests/examples/pipeline-teads-sci.yml b/manifests/examples/pipeline-teads-sci.yml index 01c491cdc..bf20cc251 100644 --- a/manifests/examples/pipeline-teads-sci.yml +++ b/manifests/examples/pipeline-teads-sci.yml @@ -19,9 +19,12 @@ initialize: "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu/energy", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci @@ -50,7 +53,7 @@ tree: - teads-curve - sum - sci-embodied - - sci-o + - operational-carbon - sum-carbon - sci config: diff --git a/manifests/examples/pipeline-with-aggregate.yml b/manifests/examples/pipeline-with-aggregate.yml index bd3e637ac..d1b90b152 100644 --- a/manifests/examples/pipeline-with-aggregate.yml +++ b/manifests/examples/pipeline-with-aggregate.yml @@ -7,25 +7,63 @@ aggregation: type: "both" initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci global-config: - functional-unit: "requests" + functional-unit-time: 1 sec + functional-unit: requests # factor to convert per time to per f.unit "sum-carbon": path: "builtin" method: Sum @@ -42,20 +80,21 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - "group-by": - path: builtin - method: GroupBy tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - - sci + # - sci config: group-by: group: @@ -67,8 +106,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -94,50 +133,55 @@ tree: cloud/region: uk-west cpu/utilization: 15 requests: 30 - child-2: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 150 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 110 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 180 + # child-2: + # pipeline: + # - interpolate + # - cpu-factor-to-wattage + # - wattage-times-duration + # - wattage-to-energy-kwh + # - calculate-vcpu-ratio + # - correct-cpu-energy-for-vcpu-ratio + # - sci-e + # - sci-embodied + # - sci-o + # - sum-carbon + # - time-sync + # - sci + # config: + # group-by: + # group: + # - cloud/region + # - cloud/instance-type + # defaults: + # cpu/thermal-design-power: 100 + # grid/carbon-intensity: 800 + # device/emissions-embodied: 1533.120 # gCO2eq + # time-reserved: 3600 # 1hr in seconds + # device/expected-lifespan: 94608000 # 3 years in seconds + # resources-reserved: 1 + # resources-total: 8 + # inputs: + # - timestamp: "2023-12-12T00:00:00.000Z" + # duration: 1 + # cpu/utilization: 30 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 100 + # - timestamp: "2023-12-12T00:00:01.000Z" + # duration: 5 + # cpu/utilization: 28 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 150 + # - timestamp: "2023-12-12T00:00:06.000Z" + # duration: 7 + # cpu/utilization: 40 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 110 + # - timestamp: "2023-12-12T00:00:13.000Z" + # duration: 30 + # cpu/utilization: 33 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 180 diff --git a/manifests/examples/pipeline-with-mocks.yml b/manifests/examples/pipeline-with-mocks.yml index 008e319b1..fde8963ef 100644 --- a/manifests/examples/pipeline-with-mocks.yml +++ b/manifests/examples/pipeline-with-mocks.yml @@ -25,20 +25,57 @@ initialize: cpu/utilization: min: 1 max: 99 - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sum-carbon": path: "builtin" method: Sum @@ -68,13 +105,17 @@ tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - - sci + # - sci config: group-by: group: @@ -86,8 +127,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" @@ -114,51 +155,51 @@ tree: cloud/region: uk-west cpu/utilization: 15 requests: 50 - child-2: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 40 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 50 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 60 + # child-2: + # pipeline: + # - teads-curve + # - sci-e + # - sci-embodied + # - sci-o + # - sum-carbon + # - time-sync + # - sci + # config: + # group-by: + # group: + # - cloud/region + # - cloud/instance-type + # defaults: + # cpu/thermal-design-power: 100 + # grid/carbon-intensity: 800 + # device/emissions-embodied: 1533.120 # gCO2eq + # time-reserved: 3600 # 1hr in seconds + # device/expected-lifespan: 94608000 # 3 years in seconds + # resources-reserved: 1 + # resources-total: 8 + # functional-unit-time: "1 min" + # inputs: + # - timestamp: "2023-12-12T00:00:00.000Z" + # duration: 1 + # cpu/utilization: 30 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 30 + # - timestamp: "2023-12-12T00:00:01.000Z" + # duration: 5 + # cpu/utilization: 28 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 40 + # - timestamp: "2023-12-12T00:00:06.000Z" + # duration: 7 + # cpu/utilization: 40 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 50 + # - timestamp: "2023-12-12T00:00:13.000Z" + # duration: 30 + # cpu/utilization: 33 + # cloud/instance-type: A1 + # cloud/region: uk-west + # requests: 60 From 918fde8c1b1c4e0aa20afcd1112f4319b5ef29a4 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 20 Jun 2024 12:43:54 +0400 Subject: [PATCH 138/863] fix(manifests): update features to use builtins --- ...ics.yml => aggregate-failure-invalid-metrics.yml} | 12 +++++++++--- .../aggregate-failure-missing-metric-in-inputs.yml | 12 +++++++++--- manifests/features/aggregate-horizontal.yml | 10 ++++++++-- manifests/features/aggregate-vertical.yml | 10 ++++++++-- manifests/features/aggregate.yml | 10 ++++++++-- 5 files changed, 42 insertions(+), 12 deletions(-) rename manifests/features/{aggregate-failure-inalid-metrics.yml => aggregate-failure-invalid-metrics.yml} (75%) diff --git a/manifests/features/aggregate-failure-inalid-metrics.yml b/manifests/features/aggregate-failure-invalid-metrics.yml similarity index 75% rename from manifests/features/aggregate-failure-inalid-metrics.yml rename to manifests/features/aggregate-failure-invalid-metrics.yml index cf2e31bce..7e4692509 100644 --- a/manifests/features/aggregate-failure-inalid-metrics.yml +++ b/manifests/features/aggregate-failure-invalid-metrics.yml @@ -1,5 +1,5 @@ name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations +description: Fails with invalid metric. aggregation: metrics: - 'test' @@ -7,8 +7,14 @@ aggregation: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: application: diff --git a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml b/manifests/features/aggregate-failure-missing-metric-in-inputs.yml index 3857d0f76..eeff85290 100644 --- a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml +++ b/manifests/features/aggregate-failure-missing-metric-in-inputs.yml @@ -1,5 +1,5 @@ name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations +description: Fails with missing metric in inputs. aggregation: metrics: - 'cpu/utilization' @@ -7,8 +7,14 @@ aggregation: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: application: diff --git a/manifests/features/aggregate-horizontal.yml b/manifests/features/aggregate-horizontal.yml index 114074795..8003c4214 100644 --- a/manifests/features/aggregate-horizontal.yml +++ b/manifests/features/aggregate-horizontal.yml @@ -7,8 +7,14 @@ aggregation: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: application: diff --git a/manifests/features/aggregate-vertical.yml b/manifests/features/aggregate-vertical.yml index b37f8e22a..6308a01d0 100644 --- a/manifests/features/aggregate-vertical.yml +++ b/manifests/features/aggregate-vertical.yml @@ -7,8 +7,14 @@ aggregation: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: application: diff --git a/manifests/features/aggregate.yml b/manifests/features/aggregate.yml index f320a13ea..04672cf38 100644 --- a/manifests/features/aggregate.yml +++ b/manifests/features/aggregate.yml @@ -7,8 +7,14 @@ aggregation: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: application: From b80ab76e34f5901615c9424702d3717d01c7fdb7 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 20 Jun 2024 12:45:11 +0400 Subject: [PATCH 139/863] fix(manifests): update integrations to use builtins --- .../cloud-metadata-divide-boavizta.yml | 10 ++++-- .../failure-invalid-instance-type.yaml | 33 +++++++++++++++++++ .../failure-invalid-provider.yaml | 33 +++++++++++++++++++ .../failure-missing-queried-input.yml | 33 +++++++++++++++++++ .../instance-metadata/success.yml | 33 +++++++++++++++++++ .../mock-obs-group-by-cloud-meta.yml | 10 ++++-- 6 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml create mode 100644 manifests/integrations/instance-metadata/failure-invalid-provider.yaml create mode 100644 manifests/integrations/instance-metadata/failure-missing-queried-input.yml create mode 100644 manifests/integrations/instance-metadata/success.yml diff --git a/manifests/integrations/cloud-metadata-divide-boavizta.yml b/manifests/integrations/cloud-metadata-divide-boavizta.yml index cafd1467b..efb48f0ab 100644 --- a/manifests/integrations/cloud-metadata-divide-boavizta.yml +++ b/manifests/integrations/cloud-metadata-divide-boavizta.yml @@ -4,8 +4,14 @@ tags: initialize: plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" diff --git a/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml b/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml new file mode 100644 index 000000000..810dee072 --- /dev/null +++ b/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml @@ -0,0 +1,33 @@ +name: instance-metadata +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: "cloud/instance-type" + output: "*" + extract-processor-name: + method: Regex + path: "builtin" + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: m6 \ No newline at end of file diff --git a/manifests/integrations/instance-metadata/failure-invalid-provider.yaml b/manifests/integrations/instance-metadata/failure-invalid-provider.yaml new file mode 100644 index 000000000..a362132e7 --- /dev/null +++ b/manifests/integrations/instance-metadata/failure-invalid-provider.yaml @@ -0,0 +1,33 @@ +name: instance-metadata +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: "cloud/provider" + output: "*" + extract-processor-name: + method: Regex + path: "builtin" + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: 6568 + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 diff --git a/manifests/integrations/instance-metadata/failure-missing-queried-input.yml b/manifests/integrations/instance-metadata/failure-missing-queried-input.yml new file mode 100644 index 000000000..37f4001ae --- /dev/null +++ b/manifests/integrations/instance-metadata/failure-missing-queried-input.yml @@ -0,0 +1,33 @@ +name: instance-metadata +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: "cloud/provider" + output: "*" + extract-processor-name: + method: Regex + path: "builtin" + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + # cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 \ No newline at end of file diff --git a/manifests/integrations/instance-metadata/success.yml b/manifests/integrations/instance-metadata/success.yml new file mode 100644 index 000000000..d95115896 --- /dev/null +++ b/manifests/integrations/instance-metadata/success.yml @@ -0,0 +1,33 @@ +name: instance-metadata +description: +tags: +initialize: + plugins: + cloud-instance-metadata: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: "cloud/instance-type" + output: "*" + extract-processor-name: + method: Regex + path: "builtin" + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 \ No newline at end of file diff --git a/manifests/integrations/mock-obs-group-by-cloud-meta.yml b/manifests/integrations/mock-obs-group-by-cloud-meta.yml index b0d43f2a5..6b6196cab 100644 --- a/manifests/integrations/mock-obs-group-by-cloud-meta.yml +++ b/manifests/integrations/mock-obs-group-by-cloud-meta.yml @@ -14,8 +14,14 @@ initialize: input-parameters: ['cpu/energy', 'grid/carbon-intensity'] output-parameter: 'carbon' cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-tdp'] mock-observations: path: 'builtin' method: MockObservations From ae53a1cc1fc13449b1707e2c6243377e8395d080 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 20 Jun 2024 12:46:12 +0400 Subject: [PATCH 140/863] fix(manifests): update plugins to use builtins --- .../failure-invalid-instance-type.yaml | 12 ++++++--- .../failure-invalid-vendor.yaml | 10 +++++-- .../failure-missing-cloud-vendor.yml | 12 ++++++--- .../cloud-metadata/success.yml | 10 +++++-- .../failure-missing-column.yml | 0 .../failure-missing-output.yml | 0 .../success-renaming.yml | 0 .../{ => region-metadata}/success.yml | 0 .../failure-missing-input-param.yml | 23 ++++++++++++++++ ...failure-unsupported-physical-processor.yml | 24 +++++++++++++++++ .../plugins/csv-lookup/tdp-finder/success.yml | 24 +++++++++++++++++ .../divide/failure-denominator-equal-zero.yml | 10 +++++-- .../failure-invalid-config-denominator.yml | 10 +++++-- .../divide/failure-missing-numerator.yml | 10 +++++-- manifests/plugins/divide/success.yml | 10 +++++-- manifests/plugins/exponent/success.yml | 26 +++++++++++++++++++ manifests/plugins/interpolation/success.yml | 24 +++++++++++++++++ manifests/plugins/subtract/success.yml | 25 ++++++++++++++++++ .../failure-missing-input-param.yml | 18 ------------- ...failure-unsupported-physical-processor.yml | 19 -------------- manifests/plugins/tdp-finder/success.yml | 19 -------------- 21 files changed, 212 insertions(+), 74 deletions(-) rename manifests/plugins/{ => csv-lookup}/cloud-metadata/failure-invalid-instance-type.yaml (57%) rename manifests/plugins/{ => csv-lookup}/cloud-metadata/failure-invalid-vendor.yaml (59%) rename manifests/plugins/{ => csv-lookup}/cloud-metadata/failure-missing-cloud-vendor.yml (56%) rename manifests/plugins/{ => csv-lookup}/cloud-metadata/success.yml (57%) rename manifests/plugins/csv-lookup/{ => region-metadata}/failure-missing-column.yml (100%) rename manifests/plugins/csv-lookup/{ => region-metadata}/failure-missing-output.yml (100%) rename manifests/plugins/csv-lookup/{ => region-metadata}/success-renaming.yml (100%) rename manifests/plugins/csv-lookup/{ => region-metadata}/success.yml (100%) create mode 100644 manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml create mode 100644 manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml create mode 100644 manifests/plugins/csv-lookup/tdp-finder/success.yml create mode 100644 manifests/plugins/exponent/success.yml create mode 100644 manifests/plugins/interpolation/success.yml create mode 100644 manifests/plugins/subtract/success.yml delete mode 100644 manifests/plugins/tdp-finder/failure-missing-input-param.yml delete mode 100644 manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml delete mode 100644 manifests/plugins/tdp-finder/success.yml diff --git a/manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml similarity index 57% rename from manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml rename to manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index 9bb4581ef..fa55623c2 100644 --- a/manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -2,11 +2,17 @@ name: cloud-metadata description: cloud/instance-type instance type is not supported in the cloud vendor tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml b/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml similarity index 59% rename from manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml rename to manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 9e2ebe4f2..c474c91fe 100644 --- a/manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -5,8 +5,14 @@ initialize: #outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml similarity index 56% rename from manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml rename to manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index 9b80c4301..33c5cc4b1 100644 --- a/manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -2,11 +2,17 @@ name: cloud-metadata description: failing because cloud/vendor is not provided tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/cloud-metadata/success.yml b/manifests/plugins/csv-lookup/cloud-metadata/success.yml similarity index 57% rename from manifests/plugins/cloud-metadata/success.yml rename to manifests/plugins/csv-lookup/cloud-metadata/success.yml index dec29460d..bd3cfdbb7 100644 --- a/manifests/plugins/cloud-metadata/success.yml +++ b/manifests/plugins/csv-lookup/cloud-metadata/success.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/csv-lookup/failure-missing-column.yml b/manifests/plugins/csv-lookup/region-metadata/failure-missing-column.yml similarity index 100% rename from manifests/plugins/csv-lookup/failure-missing-column.yml rename to manifests/plugins/csv-lookup/region-metadata/failure-missing-column.yml diff --git a/manifests/plugins/csv-lookup/failure-missing-output.yml b/manifests/plugins/csv-lookup/region-metadata/failure-missing-output.yml similarity index 100% rename from manifests/plugins/csv-lookup/failure-missing-output.yml rename to manifests/plugins/csv-lookup/region-metadata/failure-missing-output.yml diff --git a/manifests/plugins/csv-lookup/success-renaming.yml b/manifests/plugins/csv-lookup/region-metadata/success-renaming.yml similarity index 100% rename from manifests/plugins/csv-lookup/success-renaming.yml rename to manifests/plugins/csv-lookup/region-metadata/success-renaming.yml diff --git a/manifests/plugins/csv-lookup/success.yml b/manifests/plugins/csv-lookup/region-metadata/success.yml similarity index 100% rename from manifests/plugins/csv-lookup/success.yml rename to manifests/plugins/csv-lookup/region-metadata/success.yml diff --git a/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml new file mode 100644 index 000000000..b14e57d1d --- /dev/null +++ b/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -0,0 +1,23 @@ +name: tdp-finder +description: failure with `inputs` missing `physical-processor` param +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 diff --git a/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml new file mode 100644 index 000000000..47f392fcc --- /dev/null +++ b/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 302 diff --git a/manifests/plugins/csv-lookup/tdp-finder/success.yml b/manifests/plugins/csv-lookup/tdp-finder/success.yml new file mode 100644 index 000000000..42545b0df --- /dev/null +++ b/manifests/plugins/csv-lookup/tdp-finder/success.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e diff --git a/manifests/plugins/divide/failure-denominator-equal-zero.yml b/manifests/plugins/divide/failure-denominator-equal-zero.yml index af5ed2ae0..8c48e42b9 100644 --- a/manifests/plugins/divide/failure-denominator-equal-zero.yml +++ b/manifests/plugins/divide/failure-denominator-equal-zero.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" diff --git a/manifests/plugins/divide/failure-invalid-config-denominator.yml b/manifests/plugins/divide/failure-invalid-config-denominator.yml index 063274bc0..bc93f4f5f 100644 --- a/manifests/plugins/divide/failure-invalid-config-denominator.yml +++ b/manifests/plugins/divide/failure-invalid-config-denominator.yml @@ -5,8 +5,14 @@ initialize: outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" diff --git a/manifests/plugins/divide/failure-missing-numerator.yml b/manifests/plugins/divide/failure-missing-numerator.yml index 7f03d5eba..ebf250961 100644 --- a/manifests/plugins/divide/failure-missing-numerator.yml +++ b/manifests/plugins/divide/failure-missing-numerator.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" diff --git a/manifests/plugins/divide/success.yml b/manifests/plugins/divide/success.yml index ed75a7c5c..24626c8f4 100644 --- a/manifests/plugins/divide/success.yml +++ b/manifests/plugins/divide/success.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" diff --git a/manifests/plugins/exponent/success.yml b/manifests/plugins/exponent/success.yml new file mode 100644 index 000000000..c123b3a24 --- /dev/null +++ b/manifests/plugins/exponent/success.yml @@ -0,0 +1,26 @@ +name: exponent demo +description: +tags: +initialize: + # outputs: + # - yaml + plugins: + exponent: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'cpu/energy' + exponent: 2 + output-parameter: 'energy' +tree: + children: + child: + pipeline: + - exponent + config: + exponent: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 diff --git a/manifests/plugins/interpolation/success.yml b/manifests/plugins/interpolation/success.yml new file mode 100644 index 000000000..35d750e48 --- /dev/null +++ b/manifests/plugins/interpolation/success.yml @@ -0,0 +1,24 @@ +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: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 diff --git a/manifests/plugins/subtract/success.yml b/manifests/plugins/subtract/success.yml new file mode 100644 index 000000000..276128171 --- /dev/null +++ b/manifests/plugins/subtract/success.yml @@ -0,0 +1,25 @@ +name: subtract demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + subtract: + method: Subtract + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy/diff' +tree: + children: + child: + pipeline: + - subtract + config: + subtract: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 \ No newline at end of file diff --git a/manifests/plugins/tdp-finder/failure-missing-input-param.yml b/manifests/plugins/tdp-finder/failure-missing-input-param.yml deleted file mode 100644 index 7877b56ce..000000000 --- a/manifests/plugins/tdp-finder/failure-missing-input-param.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: tdp-finder -description: failure with `inputs` missing `physical-processor` param -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 diff --git a/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml deleted file mode 100644 index 56c5c93a5..000000000 --- a/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 302 diff --git a/manifests/plugins/tdp-finder/success.yml b/manifests/plugins/tdp-finder/success.yml deleted file mode 100644 index 26f905ecd..000000000 --- a/manifests/plugins/tdp-finder/success.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 3020e From ef26d4ba4e8e5a277ce913b45c6c27d148b1a5dc Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:09:20 +0100 Subject: [PATCH 141/863] feat(lib): add copy-param README --- src/builtins/copy-param/README.md | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/builtins/copy-param/README.md diff --git a/src/builtins/copy-param/README.md b/src/builtins/copy-param/README.md new file mode 100644 index 000000000..1ec04f249 --- /dev/null +++ b/src/builtins/copy-param/README.md @@ -0,0 +1,104 @@ +# Copy-param + +`copy-param` is a generic plugin that duplicates an existing parameter in the `input` data and assigns it to a new key. You can either keep or delete the original copied parameter. A common use case for this is to rename parameters in the `inputs` array. + +You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or del;et the original copied value. + +For example, you could copy `energy` into `energy-copy`, with `keep-existing=true`. In this case your inputs: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 +``` + +would become + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 + energy-copy: 30 +``` + +but with `keep-existing=false`, the same inputs would yield: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy-copy: 30 +``` + +## Parameters + +### Config + +Three parameters are required in config: `from` and `to` and `keep-existing`. + +`from`: an array of strings. Each string should match an existing key in the `inputs` array +`to`: a string defining the name to use to add the result of summing the input parameters to the output array. +`keep-existing`: toggles whether to keep or delete the copied parameter (defined in `to`) + +### Inputs + +As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. + +## Returns + +The plugin adds a new parameter with the name defined in `to` to the `input` data. + + +## Implementation + +To run the plugin, you must first create an instance of `Copy`. Then, you can call `execute()`. + +```typescript +import { Copy } from "."; + +const plugin = Copy({ 'keep-existing': true, from: 'from-param', to: 'to-param' }); + +const result = plugin.execute([{ + timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + 'from-param': 'hello', +}]) + +console.log(result) + +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `sum`: + +```yaml +name: copy-param +description: +tags: +initialize: + plugins: + copy-param: + path: builtin + method: Copy + global-config: + keep-existing: true + from: original + to: copy +tree: + children: + child-1: + pipeline: + - copy-param + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + original: 'hello' + +``` + +You can run this example by saving it as `./manifests/examples/copy.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./manifests/examples/copy.yml -s +``` + +The results will be displayed in the console. From 4fefa36c75c076dab96a9a89c1a5f40cb6b9de6c Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:09:54 +0100 Subject: [PATCH 142/863] feat(lib): export copy-param --- src/builtins/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builtins/index.ts b/src/builtins/index.ts index 1a98e3273..d22491aca 100644 --- a/src/builtins/index.ts +++ b/src/builtins/index.ts @@ -13,3 +13,4 @@ export {Exponent} from './exponent'; export {CSVLookup} from './csv-lookup'; export {Shell} from './shell'; export {Regex} from './regex'; +export {Copy} from './copy-param'; From b95c7e1baf210f2cb66177be4c33bc3b2e6f70b3 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:10:28 +0100 Subject: [PATCH 143/863] feat(lib): add copy-param source code --- src/builtins/copy-param/index.ts | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/builtins/copy-param/index.ts diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts new file mode 100644 index 000000000..3f3e1f5ae --- /dev/null +++ b/src/builtins/copy-param/index.ts @@ -0,0 +1,78 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; + +import {validate} from '../../util/validations'; + +import {STRINGS} from '../../config'; + +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; +const {GlobalConfigError, MissingInputDataError} = ERRORS; +// global-config: +// 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): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + 'keep-existing': z.boolean(), + from: z.string().min(1), + to: z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, parameter: string) => { + if (!input[parameter]) { + throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); + } + + return input; + }; + + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const keepExisting = safeGlobalConfig['keep-existing'] === true; + const from = safeGlobalConfig['from']; + const to = safeGlobalConfig['to']; + + return inputs.map(input => { + const safeInput = validateSingleInput(input, from); + + const outputValue = safeInput[from]; + if (safeInput[from]) { + if (!keepExisting) { + delete safeInput[from]; + } + } + return { + ...safeInput, // need to return or what you provide won't be outputted, don't be evil! + [to]: outputValue, + }; + }); + }; + + return { + metadata, + execute, + }; +}; From 57e64df04ce4be5819c19291dae1a5bd88e225df Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:10:58 +0100 Subject: [PATCH 144/863] feat(lib): add unit tests for copy-param --- .../unit/builtins/copy-param.test.ts | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/__tests__/unit/builtins/copy-param.test.ts diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts new file mode 100644 index 000000000..c3fcd9639 --- /dev/null +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -0,0 +1,95 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Copy} from '../../../builtins/copy-param'; + +import {STRINGS} from '../../../config'; + +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; + +describe('builtins/copy: ', () => { + describe('Copy: ', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(copy).toHaveProperty('metadata'); + expect(copy).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Copy strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + original: '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 copy = Copy(config!); + + expect.assertions(1); + + try { + copy.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + original: 1, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + expect.assertions(1); + + try { + copy.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new MissingInputDataError(MISSING_INPUT_DATA('original')) + ); + } + }); + }); + }); +}); From 22a34001b723d1f05e9b2a2946f5c1597f92391d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 14:12:15 +0100 Subject: [PATCH 145/863] feat(manifests): add example manifest for copy-param --- manifests/examples/copy.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 manifests/examples/copy.yaml diff --git a/manifests/examples/copy.yaml b/manifests/examples/copy.yaml new file mode 100644 index 000000000..f2ee816e4 --- /dev/null +++ b/manifests/examples/copy.yaml @@ -0,0 +1,20 @@ +name: copy-param +description: +tags: +initialize: + plugins: + copy-param: + path: builtin + method: Copy + global-config: + keep-existing: true + from: original + to: copy +tree: + children: + child-1: + pipeline: + - copy-param + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + original: 'hello' From a2bb35a3844eb9709c63fd911eb8340eb78b7758 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:27:25 +0100 Subject: [PATCH 146/863] feat(lib): add errors to coefficient readme --- src/builtins/coefficient/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index bf8808e8c..629059799 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -90,3 +90,19 @@ if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outpu ``` The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Coefficient exposes one of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameter`: this must be a string +- `coefficient`: this must be a number +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. From dcca6efc4e0602cd671d05088426cdc80ac99a65 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:28:04 +0100 Subject: [PATCH 147/863] feat(lib): add errors to csv readme --- src/builtins/csv-lookup/README.md | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index d1aece699..19d8642ec 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -140,3 +140,39 @@ if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/cs ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +`Coefficient exposes six of the IF error classes. + +### FetchingFileError + +This error is caused by problems finding the file at the path provided in the `filepath`. If the file is on your local filesystem, you can check that the file is definitely there. For a remote file, check your internet connection. You can check your connection to the server using a tool such as `ping` or `curl`. if you still experience problems, you could retrieve the remote file onto your local filesystem using a tool such as `wget`. + +### ReadFileError, + +This error is caused by problems reading the CSV file provided in the `filepath`. To fix it, check that the file contains valid CSV data. The file should have a `.csv` file extension and the data inside should be formatted correctly. + +### MissingCSVColumnError, + +This error is caused by `CsvLookup` failing to find a column in the CSV file whose name matches what was provided in `query`. To debug, check that you do not have any typos in your `query` and confirm that the requested column name definitely exists in the target file. + +### QueryDataNotFoundError, + +This error is caused by the `CsvLookup` plugin failing to find data that matches your query. Try revising your query parameters. + +### CSVParseError, + +This error arises due to problems parsing CSV data into IF. This can occur when the CSV data is incorrectly formatted or contains unexpected characters that IF does not recognize. These errors are expected to be unusual edge cases as incorrectly formatted data will usually be identified during file loading and cause a `ReadFileError`. To debug, check your CSV file for any unexpected formatting or unusual characters. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `filepath`: This must be a path to a csv file +- `query`: this must be an array of key-value pairs where the key is a string containing a column name an the value is a string containing the name of a value in `inputs` +- `output`: this must be a string containing a name or a wildcard character (`"*"`) + +You can fix this error by checking you are providing valid values for each parameter in the config. From 12312e55c46972d4544205c880bc03f5260e6ca7 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:32:19 +0100 Subject: [PATCH 148/863] feat(lib): add errors for divide --- src/builtins/divide/README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index 20ed19f55..a80108d04 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -93,3 +93,28 @@ if-run --manifest ./examples/manifests/divide.yml --output ./examples/outputs/di ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + +## Errors + +`Divide` exposes two of IF's error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `numerator`: a string containing the name of the input parameter whose value should be divided by `denominator` +- `denominator`: a number to use as the denominator +- ``output`: a string containing the name to assign the result of the division + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `numerator` + + From e5cc8d67cbf73ae5ca545298f95ce771b2ba70aa Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:36:35 +0100 Subject: [PATCH 149/863] feat(lib): add errors to exponent readme --- src/builtins/exponent/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index d84020d63..9a263e4be 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -95,3 +95,21 @@ if-run --manifest manifests/examples/test/exponent.yml --output manifests/output ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Exponent` exposes two of IF's error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: + +- `timestamp` +- `duration` +- whatever value you passed to `input-parameter` + + +### `InputValidationError` + +This error arises when an invalid value is passed to `Exponent`. 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. From 0f91086da064de4cc2b805c640f6796dbe83d507 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:42:10 +0100 Subject: [PATCH 150/863] feat(lib): add errors for interpolate --- src/builtins/interpolation/README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md index 670a65ef2..cdb832818 100644 --- a/src/builtins/interpolation/README.md +++ b/src/builtins/interpolation/README.md @@ -166,3 +166,29 @@ You can execute this by passing it to `ie`. Run the impact using the following c npm i -g @grnsft/if if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml ``` + +## Errors + +`Interpolation` exposes one of IF's error classes. + +## `GlobalConfigError` + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `method`: a string containing either `linear`, `spline` or `polynomial` +- `x`: an array of numbers +- `y`: an array of numbers +- `input-parameter`: a string containing the name of a value present in the `inputs` array' +- `output-parameter`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### Validation errors + +There are also several validation errors that can arise, including: +- if the lengths of `x` and `y` are not equal +- if `x` or `y` are empty +- if the requested point to interpolate at is outside the range of `x` From e8e2c5a70d9d59d8953e8c6c394706a1c1ae1518 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:44:12 +0100 Subject: [PATCH 151/863] feat(lib): add errors to Multiply --- src/builtins/multiply/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index 695d89331..f0e5d6dad 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -92,3 +92,17 @@ if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/out ``` The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Multiply` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` + From f6c6ce18d19975ba85c061a940a95875e9765a41 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 18:44:46 +0400 Subject: [PATCH 152/863] feat(util): move the isFileExists funtion to the relevant file --- src/util/fs.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/util/fs.ts diff --git a/src/util/fs.ts b/src/util/fs.ts new file mode 100644 index 000000000..92ca9684a --- /dev/null +++ b/src/util/fs.ts @@ -0,0 +1,13 @@ +import * as fs from 'fs/promises'; + +/** + * Checks if file exists with the given `filePath`. + */ +export const isFileExists = async (filePath: string) => { + try { + await fs.stat(filePath); + return true; + } catch (error) { + return false; + } +}; From 9ff31c85e9557da6247c3e14186de992305d6cdd Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 18:47:12 +0400 Subject: [PATCH 153/863] feat(util): move the npm related funtions to the relevant file --- src/types/npm.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/types/npm.ts diff --git a/src/types/npm.ts b/src/types/npm.ts new file mode 100644 index 000000000..cbb3e0680 --- /dev/null +++ b/src/types/npm.ts @@ -0,0 +1,3 @@ +export type PathWithVersion = {[path: string]: string}; + +export type ManifestPlugin = {[key: string]: {path: string; method: string}}; From 5e382707b2545e6289c5cb479f3d3b3c44376e8b Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 18:48:41 +0400 Subject: [PATCH 154/863] fix(util): move some functions to the coresponding files --- src/util/helpers.ts | 49 +-------------------------------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 9abcf9ba4..0c422c96f 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,5 +1,3 @@ -import * as fs from 'fs/promises'; -import * as path from 'path'; import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; @@ -12,8 +10,7 @@ import {STRINGS} from '../config'; import {Difference} from '../types/lib/compare'; -const {UNSUPPORTED_ERROR, INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = - STRINGS; +const {UNSUPPORTED_ERROR} = STRINGS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -179,47 +176,3 @@ export const parseManifestFromStdin = async () => { return match![1]; }; - -/** - * Checks if file exists with the given `filePath`. - */ -export const isFileExists = async (filePath: string) => { - try { - await fs.stat(filePath); - return true; - } catch (error) { - return false; - } -}; - -/** - * Checks if the package.json is exists, if not, inisializes it. - */ -export const initPackageJsonIfNotExists = async (folderPath: string) => { - const packageJsonPath = path.resolve(folderPath, 'package.json'); - const isPackageJsonExists = await isFileExists(packageJsonPath); - - if (!isPackageJsonExists) { - logger.info(INITIALIZING_PACKAGE_JSON); - await execPromise('npm init -y', {cwd: folderPath}); - } - - return packageJsonPath; -}; - -/** - * Installs packages from the specified dependencies in the specified folder. - */ -export const installDependencies = async ( - folderPath: string, - dependencies: {[path: string]: string} -) => { - const packages = Object.entries(dependencies).map( - ([dependency, version]) => `${dependency}@${version.replace('^', '')}` - ); - - logger.info(INSTALLING_NPM_PACKAGES); - await execPromise(`npm install ${packages.join(' ')}`, { - cwd: folderPath, - }); -}; From e6440049d18dd428207fdf2ca87a50de15002332 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:49:25 +0100 Subject: [PATCH 155/863] feat(lib): add errors for regex to readme --- src/builtins/regex/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index 52a99db9f..a0e88c7cc 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -89,3 +89,33 @@ if --manifest manifests/examples/regex.yml --output manifests/outputs/regex.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Regex` uses three of IF's error classes: + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `parameter` + + +### `GlobalConfigError` + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: + +- `parameter`: a string containing the name of a value in the inputs array +- `match`: a valid regex pattern +- `output`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + + +### `RegexMismatchError` + +This error arises when the requested regex cannot find any matches in the given data. If there are multiple matches, the plugin returns the first, but if there are none, it throws this error. From 7a764ae96ff58888cd6520a04f09d198aae82455 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:53:02 +0100 Subject: [PATCH 156/863] feat(lib): add error info to sci readme --- src/builtins/sci/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 658209f1a..21dca0e19 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -87,3 +87,22 @@ if-run --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml ``` The results will be saved to a new `yaml` file. + +## Errors + +`SCI` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. + +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- `carbon`: a numeric value named `carbon` must exist in the inputs array +- whatever value you passed to `functional-unit` + + +### Validation errors + +There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. From 5483ad71f4f153f2cc723aa2222e1682cfc31c4a Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 18:59:22 +0400 Subject: [PATCH 157/863] fix(util): update isFileExists path --- src/util/args.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 031c2250e..67e38890c 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -5,7 +5,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {checkIfFileIsYaml} from './yaml'; -import {isFileExists} from './helpers'; +import {isFileExists} from './fs'; import {logger} from './logger'; @@ -176,15 +176,14 @@ export const parseIfEnvArgs = async () => { const {manifest, install, cwd} = validateAndParseIfEnvArgs(); if (manifest) { - const isManifestFileExists = await isFileExists(manifest); + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); if (!isManifestFileExists) { throw new CliInputError(MANIFEST_NOT_FOUND); } if (checkIfFileIsYaml(manifest)) { - const response = prependFullFilePath(manifest); - return {manifest: response, install, cwd}; } From 43a79aa22741265c25adc779d3c85a060706572e Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:01:30 +0100 Subject: [PATCH 158/863] feat(lib): add error info to sci-embodied and shell --- src/builtins/sci-embodied/README.md | 11 +++++++++++ src/builtins/shell/README.md | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md index 70307fee1..3fd169211 100644 --- a/src/builtins/sci-embodied/README.md +++ b/src/builtins/sci-embodied/README.md @@ -108,3 +108,14 @@ if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/ ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`SciEmbodied` uses one of IF's error classes + +### `SciEmbodiedError` + +This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. + +You will receive a specific error message explaining which parameter is problematic, and you can check and replace where appropriate. diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md index 54ccac285..61987958e 100644 --- a/src/builtins/shell/README.md +++ b/src/builtins/shell/README.md @@ -128,3 +128,12 @@ if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.y ``` The results will be saved to a new `yaml` file. + + +## Errors + +`Shell` uses one of the error classes provided by IF + +### `ProcessExecutionError` + +This error is thrown when the program invoked in the spawned shell fails for some reason that is not known to IF. Since the shell executes arbitrary code, it is difficult for IF to provide specific errors - this is delegated to the developers of the executed program. From 2a6f242ed73f48e0fd66c68724b6fc9273a99ca7 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:02:37 +0400 Subject: [PATCH 159/863] feat(util): move the npm related funtions to the relevant file --- src/util/npm.ts | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/util/npm.ts diff --git a/src/util/npm.ts b/src/util/npm.ts new file mode 100644 index 000000000..bfdf82ca6 --- /dev/null +++ b/src/util/npm.ts @@ -0,0 +1,135 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {execPromise} from './helpers'; +import {isFileExists} from './fs'; +import {logger} from './logger'; + +import {STRINGS} from '../config'; +import {ManifestPlugin, PathWithVersion} from '../types/npm'; + +const packageJson = require('../../package.json'); + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; + +/** + * Checks if the package.json is exists, if not, inisializes it. + */ +export const initPackageJsonIfNotExists = async (folderPath: string) => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + const isPackageJsonExists = await isFileExists(packageJsonPath); + + if (!isPackageJsonExists) { + logger.info(INITIALIZING_PACKAGE_JSON); + await execPromise('npm init -y', {cwd: folderPath}); + } + + return packageJsonPath; +}; + +/** + * Installs packages from the specified dependencies in the specified folder. + */ +export const installDependencies = async ( + folderPath: string, + dependencies: {[path: string]: string} +) => { + const packages = Object.entries(dependencies).map( + ([dependency, version]) => `${dependency}@${version.replace('^', '')}` + ); + + logger.info(INSTALLING_NPM_PACKAGES); + await execPromise(`npm install ${packages.join(' ')}`, { + cwd: folderPath, + }); +}; + +/** + * Updates package.json dependencies. + */ +export const updatePackageJsonDependencies = async ( + packageJsonPath: string, + dependencies: PathWithVersion, + cwd: boolean +) => { + const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); + + const parsedPackageJson = JSON.parse(packageJsonContent); + + if (cwd) { + parsedPackageJson.dependencies = { + ...parsedPackageJson.dependencies, + ...dependencies, + }; + } else { + parsedPackageJson.dependencies = {...dependencies}; + } + + await fs.writeFile( + packageJsonPath, + JSON.stringify(parsedPackageJson, null, 2) + ); +}; + +/** + * Gets depencecies with versions. + */ +export const extractPathsWithVersion = ( + plugins: ManifestPlugin, + dependencies: string[] +) => { + const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); + const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); + const pathsWithVersion: PathWithVersion = {}; + + uniquePaths.forEach(pluginPath => { + const dependency = dependencies.find((dependency: string) => + dependency.startsWith(pluginPath) + ); + + if (dependency) { + const splittedDependency = dependency.split('@'); + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[pluginPath] = `^${version}`; + } + }); + + return pathsWithVersion; +}; + +/** + * Update the package.json properties. + */ +export const updatePackageJsonProperties = async ( + newPackageJsonPath: string +) => { + const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); + const parsedPackageJsonContent = JSON.parse(packageJsonContent); + + const properties = { + name: 'if-environment', + description: packageJson.description, + author: packageJson.author, + bugs: packageJson.bugs, + engines: packageJson.engines, + homepage: packageJson.homepage, + dependencies: {}, + }; + + const newPackageJson = Object.assign( + {}, + parsedPackageJsonContent, + properties + ); + + await fs.writeFile( + newPackageJsonPath, + JSON.stringify(newPackageJson, null, 2) + ); +}; From ad1cbcb768c76760c9b06cb52c2d87306c3d67d4 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:03:13 +0100 Subject: [PATCH 160/863] feat(lib): add error info to subtract readme --- src/builtins/subtract/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md index bb8435548..5869d93a7 100644 --- a/src/builtins/subtract/README.md +++ b/src/builtins/subtract/README.md @@ -92,3 +92,12 @@ if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/sub ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +`Subtract` uses one of IF's error classes: + +### `InputValidationError` + +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. From 0b403b2f04e481c9782747e36af526a92f0b05a5 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:03:41 +0400 Subject: [PATCH 161/863] test(util): fix isFileExists path --- src/__tests__/unit/util/args.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index 61874dd35..b0605260e 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -1,6 +1,6 @@ const processRunningPath = process.cwd(); -jest.mock('../../../util/helpers', () => ({ +jest.mock('../../../util/fs', () => ({ isFileExists: () => { if (process.env.fileExists === 'true') { return true; From ab544404eb40c86c9a42d5e07e0ffbb2b6eb5ce1 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:05:18 +0400 Subject: [PATCH 162/863] feat(mocks): add mocks for util/npm functionality --- src/__mocks__/fs/index.ts | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index eab90532e..b7731b4b8 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -1,10 +1,19 @@ import * as YAML from 'js-yaml'; +import * as fs from 'fs'; +import * as fsAsync from 'fs/promises'; export const readFile = async (filePath: string) => { + /** mock for util/npm */ + if (filePath.includes('package.json-npm')) { + const updatedPath = filePath.replace('-npm', ''); + return fs.readFileSync(updatedPath, 'utf8'); + } + /** mock for util/json */ if (filePath.includes('json-reject')) { return Promise.reject(new Error('rejected')); } + if (filePath.includes('json')) { if (filePath.includes('param')) { return JSON.stringify({ @@ -80,18 +89,25 @@ cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,g export const mkdir = (dirPath: string) => dirPath; export const writeFile = async (pathToFile: string, content: string) => { - if (pathToFile === 'reject') { - throw new Error('Wrong file path'); - } + if (pathToFile.includes('package.json-npm')) { + const updatedPath = pathToFile.replace('-npm', ''); - const mockPathToFile = 'mock-pathToFile'; - const mockContent = { - name: 'mock-name', - }; - const mockObject = YAML.dump(mockContent, {noRefs: true}); + const content = await fsAsync.readFile(updatedPath, 'utf8'); + expect(content).toBe(content); + } else { + if (pathToFile === 'reject') { + throw new Error('Wrong file path'); + } - expect(pathToFile).toBe(mockPathToFile); - expect(content).toBe(mockObject); + const mockPathToFile = 'mock-pathToFile'; + const mockContent = { + name: 'mock-name', + }; + const mockObject = YAML.dump(mockContent, {noRefs: true}); + + expect(pathToFile).toBe(mockPathToFile); + expect(content).toBe(mockObject); + } }; export const stat = async (filePath: string) => { From 549230e3f92d25bef420e43da1ce390a5d874bcc Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:06:32 +0100 Subject: [PATCH 163/863] feat(lib): add error info to sum --- src/builtins/coefficient/README.md | 2 +- src/builtins/sum/README.md | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index 629059799..4f4d2b839 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -94,7 +94,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs` ## Errors -`Coefficient exposes one of the IF error classes. +`Coefficient` exposes one of the IF error classes. ### GlobalConfigError diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md index d3fd892da..5ffc85b37 100644 --- a/src/builtins/sum/README.md +++ b/src/builtins/sum/README.md @@ -89,3 +89,27 @@ if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.y ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`Sum` exposes two of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameters`: this must be an array of strings, each being the name of a value in the `inputs` array +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: + +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` From 6a3ab7b7b1bd5e8cfeab722f365987061a40d0e9 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:06:52 +0400 Subject: [PATCH 164/863] test(util): add test file for util/fs --- src/__tests__/unit/util/fs.test.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/__tests__/unit/util/fs.test.ts diff --git a/src/__tests__/unit/util/fs.test.ts b/src/__tests__/unit/util/fs.test.ts new file mode 100644 index 000000000..82f28bc75 --- /dev/null +++ b/src/__tests__/unit/util/fs.test.ts @@ -0,0 +1,21 @@ +import {isFileExists} from '../../../util/fs'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +describe('util/fs: ', () => { + describe('isFileExists(): ', () => { + it('returns true if the file exists.', async () => { + const result = await isFileExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns fale if the file does not exist.', async () => { + const result = await isFileExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); +}); From 83fd07200096be4234bfab8caed81e54d0a65b75 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:08:14 +0400 Subject: [PATCH 165/863] test(util): add test file for util/npm --- src/__tests__/unit/util/npm.test.ts | 230 ++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/__tests__/unit/util/npm.test.ts diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts new file mode 100644 index 000000000..5c904aa23 --- /dev/null +++ b/src/__tests__/unit/util/npm.test.ts @@ -0,0 +1,230 @@ +import * as fs from 'fs/promises'; +import * as fsSync from 'fs'; +import * as path from 'path'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +const mockInfo = jest.fn(); + +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); +jest.mock('../../../util/logger', () => ({ + logger: { + info: mockInfo, + }, +})); + +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, +} from '../../../util/npm'; +import {isFileExists} from '../../../util/fs'; + +import {STRINGS} from '../../../config/strings'; +import {ManifestPlugin} from '../../../types/npm'; + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; + +describe('util/npm: ', () => { + const helpers = require('../../../util/helpers'); + const folderPath = path.resolve(__dirname, 'npm-test'); + + beforeAll(() => { + if (!fsSync.existsSync(folderPath)) { + fsSync.mkdirSync(folderPath, {recursive: true}); + } + }); + + afterAll(() => { + if (fsSync.existsSync(folderPath)) { + fsSync.rmSync(folderPath, {recursive: true, force: true}); + } + }); + + describe('initPackageJsonIfNotExists(): ', () => { + it('initializes package.json if it does not exist.', async () => { + const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + isFileExists('true'); + + await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); + expect(spyExecPromise).toHaveBeenCalledWith('npm init -y', { + cwd: folderPath, + }); + }); + + it('returns the package.json path if it exists.', async () => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + isFileExists('false'); + + const result = await initPackageJsonIfNotExists(folderPath); + + expect.assertions(1); + expect(result).toBe(packageJsonPath); + }); + }); + + describe('installDependencies(): ', () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + it('calls execPromise with the correct arguments.', async () => { + const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + const formattedDependencies = ['@grnsft/if@0.3.3-beta.0']; + expect.assertions(1); + + await installDependencies(folderPath, dependencies); + + expect(spyExecPromise).toHaveBeenCalledWith( + `npm install ${formattedDependencies.join(' ')}`, + {cwd: folderPath} + ); + }, 30000); + + it('logs the installation message.', async () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + await installDependencies(folderPath, dependencies); + + expect.assertions(1); + expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); + }); + }); + + describe('updatePackageJsonDependencies(): ', () => { + it('successfully updates the package.json dependencies when cwd is false.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if': '^0.3.3-beta.0', + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, false); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + + it('successfully updates the package.json dependencies when cwd is true.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if': '^0.3.3-beta.0', + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, true); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + }); + + describe('extractPathsWithVersion(): ', () => { + it('extracts paths with correct versions.', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + '@commitlint/cli@18.6.0', + '@commitlint/config-conventional@18.6.0', + '@grnsft/if-core@0.0.7', + '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models', + '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', + '@jest/globals@29.7.0', + ]; + + const result = extractPathsWithVersion(plugins, dependencies); + + expect.assertions(1); + expect(result).toEqual({ + '@grnsft/if-plugins': '^v0.3.2', + '@grnsft/if-unofficial-plugins': '^v0.3.0', + }); + }); + + it('returns an empty object if no matches found', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + ]; + + expect.assertions(1); + const result = extractPathsWithVersion(plugins, dependencies); + expect(result).toEqual({}); + }); + }); + + describe('updatePackageJsonProperties(): ', () => { + it('updates the package.json properties correctly.', async () => { + const newPackageJsonPath = path.resolve(folderPath, '/package.json-npm'); + await updatePackageJsonProperties(newPackageJsonPath); + + expect.assertions(2); + expect(fs.readFile).toHaveBeenCalledWith(newPackageJsonPath, 'utf8'); + }); + }); +}); From 46afe5a65c9b4d21f061a2b8e24cdcc6bbcd72ae Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:09:47 +0400 Subject: [PATCH 166/863] fix(types): move some type to the corresponding file --- src/types/if-env.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/types/if-env.ts b/src/types/if-env.ts index 796fd0ca8..03ace8ec9 100644 --- a/src/types/if-env.ts +++ b/src/types/if-env.ts @@ -4,7 +4,3 @@ export type EnvironmentOptions = { cwd: boolean; dependencies: {[path: string]: string}; }; - -export type PathWithVersion = {[path: string]: string}; - -export type ManifestPlugin = {[key: string]: {path: string; method: string}}; From 07d91a4e204d52c26c51b6f584425ccb9ea3a800 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:11:14 +0400 Subject: [PATCH 167/863] test(util): move not related tests --- src/__tests__/unit/util/helpers.test.ts | 100 ------------------------ 1 file changed, 100 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index e093a3468..ba89850a3 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -1,9 +1,3 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -const mockInfo = jest.fn(); const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -12,7 +6,6 @@ jest.mock('node:readline/promises', () => ); jest.mock('../../../util/logger', () => ({ logger: { - info: mockInfo, warn: mockWarn, error: mockError, }, @@ -27,15 +20,10 @@ import { mergeObjects, oneIsPrimitive, parseManifestFromStdin, - isFileExists, - installDependencies, - initPackageJsonIfNotExists, } from '../../../util/helpers'; import {Difference} from '../../../types/lib/compare'; -import {STRINGS} from '../../../config/strings'; const {WriteFileError} = ERRORS; -const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; describe('util/helpers: ', () => { describe('andHandle(): ', () => { @@ -411,92 +399,4 @@ description: mock-description expect(response).toBeFalsy(); }); }); - - describe('isFileExists(): ', () => { - it('returns true if the file exists.', async () => { - const result = await isFileExists('true'); - - expect.assertions(1); - expect(result).toEqual(true); - }); - - it('returns fale if the file does not exist.', async () => { - const result = await isFileExists('false'); - - expect.assertions(1); - expect(result).toEqual(false); - }); - }); - - describe('npm manipulation tests.', () => { - const helpers = require('../../../util/helpers'); - const folderPath = path.resolve(__dirname, 'npm-test'); - - beforeAll(() => { - if (!fs.existsSync(folderPath)) { - fs.mkdirSync(folderPath, {recursive: true}); - } - }); - - afterAll(() => { - if (fs.existsSync(folderPath)) { - fs.rmSync(folderPath, {recursive: true, force: true}); - } - }); - - describe('initPackageJsonIfNotExists(): ', () => { - it('initializes package.json if it does not exist.', async () => { - const spyExecPromise = jest.spyOn(helpers, 'execPromise'); - isFileExists('true'); - - await initPackageJsonIfNotExists(folderPath); - - expect.assertions(2); - expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); - expect(spyExecPromise).toHaveBeenCalledWith('npm init -y', { - cwd: folderPath, - }); - }); - - it('returns the package.json path if it exists.', async () => { - const packageJsonPath = path.resolve(folderPath, 'package.json'); - isFileExists('false'); - - const result = await initPackageJsonIfNotExists(folderPath); - - expect.assertions(1); - expect(result).toBe(packageJsonPath); - }); - }); - - describe('installDependencies(): ', () => { - const dependencies = { - '@grnsft/if': '^0.3.3-beta.0', - }; - - it('calls execPromise with the correct arguments.', async () => { - const spyExecPromise = jest.spyOn(helpers, 'execPromise'); - const formattedDependencies = ['@grnsft/if@0.3.3-beta.0']; - expect.assertions(1); - - await installDependencies(folderPath, dependencies); - - expect(spyExecPromise).toHaveBeenCalledWith( - `npm install ${formattedDependencies.join(' ')}`, - {cwd: folderPath} - ); - }, 30000); - - it('logs the installation message.', async () => { - const dependencies = { - '@grnsft/if': '^0.3.3-beta.0', - }; - - await installDependencies(folderPath, dependencies); - - expect.assertions(1); - expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); - }); - }); - }); }); From d8a61815df19e4b9451288c6afd8cfea27d5aad4 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:11:40 +0100 Subject: [PATCH 168/863] feat(lib): add link out to docs to all readmes --- src/builtins/coefficient/README.md | 2 ++ src/builtins/csv-lookup/README.md | 2 ++ src/builtins/divide/README.md | 1 + src/builtins/exponent/README.md | 2 ++ src/builtins/interpolation/README.md | 2 ++ src/builtins/multiply/README.md | 1 + src/builtins/regex/README.md | 2 ++ src/builtins/sci-embodied/README.md | 3 +++ src/builtins/sci/README.md | 2 ++ src/builtins/shell/README.md | 2 ++ src/builtins/subtract/README.md | 2 ++ src/builtins/sum/README.md | 3 +++ 12 files changed, 24 insertions(+) diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index 4f4d2b839..4579cd5b8 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -106,3 +106,5 @@ The required parameters are: - `output-parameter`: this must be a string You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index 19d8642ec..eb62f8c7e 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -176,3 +176,5 @@ The required parameters are: - `output`: this must be a string containing a name or a wildcard character (`"*"`) You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index a80108d04..cb98c7141 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -118,3 +118,4 @@ Every element in the ``inputs` array must contain: - whatever value you passed to `numerator` +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index 9a263e4be..e484ea74d 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -113,3 +113,5 @@ Every element in the ``inputs` array must contain: ### `InputValidationError` This error arises when an invalid value is passed to `Exponent`. 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 diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md index cdb832818..498c26c6e 100644 --- a/src/builtins/interpolation/README.md +++ b/src/builtins/interpolation/README.md @@ -192,3 +192,5 @@ There are also several validation errors that can arise, including: - if the lengths of `x` and `y` are not equal - if `x` or `y` are empty - if the requested point to interpolate at is outside the range of `x` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index f0e5d6dad..ae410bba5 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -106,3 +106,4 @@ Every element in the ``inputs` array must contain: - `duration` - whatever values you passed to `input-parameters` +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index a0e88c7cc..62f05bca9 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -119,3 +119,5 @@ You can fix this error by checking you are providing valid values for each param ### `RegexMismatchError` This error arises when the requested regex cannot find any matches in the given data. If there are multiple matches, the plugin returns the first, but if there are none, it throws this error. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md index 3fd169211..97b6ce4af 100644 --- a/src/builtins/sci-embodied/README.md +++ b/src/builtins/sci-embodied/README.md @@ -119,3 +119,6 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. 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 diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 21dca0e19..d9a117d60 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -106,3 +106,5 @@ Every element in the `inputs` array must contain: ### Validation errors There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md index 61987958e..bacba1255 100644 --- a/src/builtins/shell/README.md +++ b/src/builtins/shell/README.md @@ -137,3 +137,5 @@ The results will be saved to a new `yaml` file. ### `ProcessExecutionError` This error is thrown when the program invoked in the spawned shell fails for some reason that is not known to IF. Since the shell executes arbitrary code, it is difficult for IF to provide specific errors - this is delegated to the developers of the executed program. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md index 5869d93a7..8ff9a922f 100644 --- a/src/builtins/subtract/README.md +++ b/src/builtins/subtract/README.md @@ -101,3 +101,5 @@ The results will be saved to a new `yaml` file in `manifests/outputs`. ### `InputValidationError` 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 diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md index 5ffc85b37..ea0f0113d 100644 --- a/src/builtins/sum/README.md +++ b/src/builtins/sum/README.md @@ -113,3 +113,6 @@ Every element in the ``inputs` array must contain: - `timestamp` - `duration` - whatever values you passed to `input-parameters` + + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors). From 041098c8d20f42b316c23e85062e1fd9e651d59e Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 20 Jun 2024 19:13:00 +0400 Subject: [PATCH 169/863] feat(src): move some function to the corresponding files --- src/env.ts | 94 +++++------------------------------------------------- 1 file changed, 8 insertions(+), 86 deletions(-) diff --git a/src/env.ts b/src/env.ts index 759ae0be5..e1fd42a57 100644 --- a/src/env.ts +++ b/src/env.ts @@ -3,7 +3,13 @@ import * as fs from 'fs/promises'; import * as path from 'path'; -import {installDependencies, initPackageJsonIfNotExists} from './util/helpers'; +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, +} from './util/npm'; import {parseIfEnvArgs} from './util/args'; import {logger} from './util/logger'; @@ -11,13 +17,7 @@ import {load} from './lib/load'; import {CONFIG} from './config'; -import { - EnvironmentOptions, - ManifestPlugin, - PathWithVersion, -} from './types/if-env'; - -const packageJson = require('../package.json'); +import {EnvironmentOptions} from './types/if-env'; const {IF_ENV} = CONFIG; const { @@ -81,36 +81,6 @@ const getOptionsFromArgs = async (commandArgs: { }; }; -/** - * Gets depencecies with versions. - */ -const extractPathsWithVersion = ( - plugins: ManifestPlugin, - dependencies: string[] -) => { - const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); - const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); - const pathsWithVersion: PathWithVersion = {}; - - uniquePaths.forEach(pluginPath => { - const dependency = dependencies.find((dependency: string) => - dependency.startsWith(pluginPath) - ); - - if (dependency) { - const splittedDependency = dependency.split('@'); - const version = - splittedDependency.length > 2 - ? splittedDependency[2].split(' ')[0] - : splittedDependency[1]; - - pathsWithVersion[pluginPath] = `^${version}`; - } - }); - - return pathsWithVersion; -}; - /** * Creates folder if not exists, installs dependencies if required, update depenedencies. */ @@ -132,54 +102,6 @@ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { } }; -/** - * Update the package.json properties. - */ -const updatePackageJsonProperties = async (packageJsonPath: string) => { - const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); - const parsedPackageJsonContent = JSON.parse(packageJsonContent); - - const properties = { - name: 'if-environment', - description: packageJson.description, - author: packageJson.author, - bugs: packageJson.bugs, - engines: packageJson.engines, - homepage: packageJson.homepage, - }; - - const newPackageJson = Object.assign( - {}, - parsedPackageJsonContent, - properties - ); - - await fs.writeFile(packageJsonPath, JSON.stringify(newPackageJson, null, 2)); -}; - -/** - * Updates package.json dependencies. - */ -const updatePackageJsonDependencies = async ( - packageJsonPath: string, - dependencies: PathWithVersion, - cwd: boolean -) => { - const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); - const packageJson = JSON.parse(packageJsonContent); - - if (cwd) { - packageJson.dependencies = { - ...packageJson.dependencies, - ...dependencies, - }; - } else { - packageJson.dependencies = {...dependencies}; - } - - await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); -}; - /** * Adds a manifest template to the folder where the if-env CLI command runs. */ From e361448f5f62be3295e2fa52ea524ca8ce0f1ae8 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:38:00 +0100 Subject: [PATCH 170/863] feat(lib): add unit test to cover keep-existing==false --- .../unit/builtins/copy-param.test.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts index c3fcd9639..cf5166107 100644 --- a/src/__tests__/unit/builtins/copy-param.test.ts +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -90,6 +90,33 @@ describe('builtins/copy: ', () => { ); } }); + it('does not persist the original value when keep-existing==false.', () => { + expect.assertions(1); + const globalConfig = { + 'keep-existing': false, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + const expectedResult = [ + { + duration: 3600, + 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); + }); }); }); }); From 5c2f6abb13a69a6c4af0cddda5431f9d4559108d Mon Sep 17 00:00:00 2001 From: Arne Tarara Date: Fri, 21 Jun 2024 12:21:10 +0200 Subject: [PATCH 171/863] Eco-CI integration on v4.0-rc3 and being explicit about send-data Signed-off-by: Arne Tarara --- .github/workflows/nodejs-ci.yml | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index e8aac6e88..94cd1c93e 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -3,21 +3,83 @@ on: push jobs: build: runs-on: ubuntu-latest + permissions: + pull-requests: write # this allows to show carbon and energy data table in PRs steps: + - name: Eco CI Energy Estimation - Initialize + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: start-measurement + continue-on-error: true + - name: Checkout code uses: actions/checkout@v4 + - name: Eco CI Energy Estimation - Get Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: get-measurement + label: "checkout" + continue-on-error: true + - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 18 cache: 'npm' + - name: Eco CI Energy Estimation - Get Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: get-measurement + label: "setup node" + continue-on-error: true + + - name: Install dependencies run: npm install + - name: Eco CI Energy Estimation - Get Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: get-measurement + label: "npm install" + continue-on-error: true + + - name: Run lint run: npm run lint + + - name: Eco CI Energy Estimation - Get Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: get-measurement + label: "npm run lint" + continue-on-error: true + - name: Run tests run: npm run test --silent + + - name: Eco CI Energy Estimation - Get Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: get-measurement + label: "npm run test" + continue-on-error: true + + - name: Eco CI Energy Estimation - End Measurement + uses: green-coding-solutions/eco-ci-energy-estimation@v4.0-rc3 + + with: + task: display-results + send-data: true + pr-comment: true + continue-on-error: true + From cf78e06f3ded72786331628b34aaf3efdb4d5bc7 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 21 Jun 2024 16:51:34 +0400 Subject: [PATCH 172/863] fix(util): add boolean argument to check if need to update package dependencies --- src/util/npm.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/npm.ts b/src/util/npm.ts index bfdf82ca6..0cbfe27e1 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -107,7 +107,8 @@ export const extractPathsWithVersion = ( * Update the package.json properties. */ export const updatePackageJsonProperties = async ( - newPackageJsonPath: string + newPackageJsonPath: string, + resetDependencies: boolean ) => { const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); const parsedPackageJsonContent = JSON.parse(packageJsonContent); @@ -119,7 +120,7 @@ export const updatePackageJsonProperties = async ( bugs: packageJson.bugs, engines: packageJson.engines, homepage: packageJson.homepage, - dependencies: {}, + dependencies: resetDependencies ? {} : packageJson.dependencies, }; const newPackageJson = Object.assign( From 1545fcdc92facbf885cb694d5fdd32b1400098ae Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 21 Jun 2024 16:52:53 +0400 Subject: [PATCH 173/863] test(util): update the test according to changes --- src/__tests__/unit/util/npm.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 5c904aa23..9680bf722 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -221,7 +221,7 @@ describe('util/npm: ', () => { describe('updatePackageJsonProperties(): ', () => { it('updates the package.json properties correctly.', async () => { const newPackageJsonPath = path.resolve(folderPath, '/package.json-npm'); - await updatePackageJsonProperties(newPackageJsonPath); + await updatePackageJsonProperties(newPackageJsonPath, false); expect.assertions(2); expect(fs.readFile).toHaveBeenCalledWith(newPackageJsonPath, 'utf8'); From 8e78685f2d44e83b20e5476631c39116da4dcdfc Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 21 Jun 2024 16:54:45 +0400 Subject: [PATCH 174/863] fix(src): update package depenedencies depend on cwd flag --- src/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/env.ts b/src/env.ts index e1fd42a57..1775c3fd3 100644 --- a/src/env.ts +++ b/src/env.ts @@ -89,7 +89,7 @@ const initializeAndInstallLibs = async (options: EnvironmentOptions) => { const {folderPath, install, cwd, dependencies} = options; const packageJsonPath = await initPackageJsonIfNotExists(folderPath); - await updatePackageJsonProperties(packageJsonPath); + await updatePackageJsonProperties(packageJsonPath, !cwd); if (install) { await installDependencies(folderPath, dependencies); From 9a816dddba19af4cb37ec886701a849d0bd00e8a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:00:51 +0400 Subject: [PATCH 175/863] fix(config): drop unused non numeric value message --- src/config/strings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 82e6d388b..ba6e8a918 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -56,8 +56,7 @@ Note that for the '--output' option you also need to define the output type in y /** Plugin messages */ MISSING_GLOBAL_CONFIG: 'Global config is not provided.', MISSING_INPUT_DATA: (param: string) => - `${param} is missing from the input array.`, - NOT_NUMERIC_VALUE: (str: any) => `${str} is not numberic.`, + `${param} is missing from the input array, or has nullish value.`, MISSING_FUNCTIONAL_UNIT_CONFIG: '`functional-unit` should be provided in your global config', MISSING_FUNCTIONAL_UNIT_INPUT: From 33ffea161f73ef5ee30514d1fb7b07767b3465ce Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:07:32 +0400 Subject: [PATCH 176/863] fix(builtins): tune sum plugin validation --- src/builtins/sum/index.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts index ecce47cf3..57437ba31 100644 --- a/src/builtins/sum/index.ts +++ b/src/builtins/sum/index.ts @@ -6,8 +6,8 @@ import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_INPUT_DATA, MISSING_GLOBAL_CONFIG} = STRINGS; +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; export const Sum = (globalConfig: SumConfig): ExecutePlugin => { const metadata = { @@ -23,11 +23,11 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { const outputParameter = safeGlobalConfig['output-parameter']; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); + validateSingleInput(input, inputParameters); return { ...input, - [outputParameter]: calculateSum(safeInput, inputParameters), + [outputParameter]: calculateSum(input, inputParameters), }; }); }; @@ -58,11 +58,16 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToSum => { - if (!input[metricToSum]) { - throw new MissingInputDataError(MISSING_INPUT_DATA(metricToSum)); - } - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); return input; }; From fe8f0fbe88a504c2998695f5b8b8311a0591db8c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:15:16 +0400 Subject: [PATCH 177/863] fix(builtins): tune subtract plugin validation --- src/builtins/subtract/index.ts | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts index 20a61b5b6..797b259c1 100644 --- a/src/builtins/subtract/index.ts +++ b/src/builtins/subtract/index.ts @@ -1,5 +1,4 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; import { ExecutePlugin, PluginParams, @@ -8,11 +7,6 @@ import { import {validate} from '../../util/validations'; -import {STRINGS} from '../../config'; - -const {InputValidationError} = ERRORS; -const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; - export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { const metadata = { kind: 'execute', @@ -40,24 +34,20 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToSubtract => { - validateParamExists(input, metricToSubtract); - validateNumericString(input[metricToSubtract]); - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; - return input; - }; + return acc; + }, + {} as Record + ); - const validateParamExists = (input: PluginParams, param: string) => { - if (input[param] === undefined) { - throw new InputValidationError(MISSING_INPUT_DATA(param)); - } - }; + const validationSchema = z.record(z.string(), z.number()); - const validateNumericString = (str: string) => { - if (isNaN(+Number(str))) { - throw new InputValidationError(NOT_NUMERIC_VALUE(str)); - } + validate(validationSchema, inputData); + + return input; }; /** From 3a0cc9c1c3b7174236839d85ab5aeb51573c974f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:16:06 +0400 Subject: [PATCH 178/863] fix(builtins): simplify execute in sci embodied --- src/builtins/sci-embodied/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/builtins/sci-embodied/index.ts b/src/builtins/sci-embodied/index.ts index 678d41336..a88017e9f 100644 --- a/src/builtins/sci-embodied/index.ts +++ b/src/builtins/sci-embodied/index.ts @@ -24,8 +24,8 @@ export const SciEmbodied = (): ExecutePlugin => { /** * Calculate the Embodied carbon for a list of inputs. */ - const execute = (inputs: PluginParams[]) => { - return inputs.map(input => { + const execute = (inputs: PluginParams[]) => + inputs.map(input => { const safeInput = validateInput(input); return { @@ -33,7 +33,6 @@ export const SciEmbodied = (): ExecutePlugin => { 'carbon-embodied': calculateEmbodiedCarbon(safeInput), }; }); - }; /** * Calculate the Embodied carbon for the input. From edc02c9ef853434852f75443a8a4edd776408f8c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:20:42 +0400 Subject: [PATCH 179/863] feat(config): add zero division message to strings --- src/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index ba6e8a918..b89822794 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -128,4 +128,6 @@ ${error}`, `Exporting to csv file: ${savepath}`, EXPORTING_RAW_CSV_FILE: (savepath: string) => `Exporting raw csv file: ${savepath}`, + ZERO_DIVISION: (moduleName: string, index: number) => + `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, }; From 402bfbe66b67aabc593d434e5d4bfa3b88ad869a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:22:38 +0400 Subject: [PATCH 180/863] feat(builtins): tune zero devision in sci --- src/builtins/sci/index.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index 223493f3a..f119f667a 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -7,7 +7,11 @@ import {validate, allDefined} from '../../util/validations'; import {STRINGS} from '../../config'; const {MissingInputDataError} = ERRORS; -const {MISSING_FUNCTIONAL_UNIT_CONFIG, MISSING_FUNCTIONAL_UNIT_INPUT} = STRINGS; +const { + MISSING_FUNCTIONAL_UNIT_CONFIG, + MISSING_FUNCTIONAL_UNIT_INPUT, + ZERO_DIVISION, +} = STRINGS; export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -33,12 +37,22 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { * Calculate the total emissions for a list of inputs. */ const execute = (inputs: PluginParams[]): PluginParams[] => - inputs.map(input => { + inputs.map((input, index) => { const safeInput = validateInput(input); - const sci = - safeInput['carbon'] > 0 - ? safeInput['carbon'] / input[globalConfig['functional-unit']] - : 0; + const functionalUnit = input[globalConfig['functional-unit']]; + + let sci: any = {}; + + if (safeInput['carbon'] > 0) { + if (functionalUnit === 0) { + console.warn(ZERO_DIVISION(Sci.name, index)); + sci = safeInput['carbon']; + } else { + sci = safeInput['carbon'] / functionalUnit; + } + } else { + sci = 0; + } return { ...input, @@ -57,7 +71,7 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { if ( !( validatedConfig['functional-unit'] in input && - input[validatedConfig['functional-unit']] > 0 + input[validatedConfig['functional-unit']] >= 0 ) ) { throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); From 0bffd851a6410413e782197d143bba526f45e42a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:23:09 +0400 Subject: [PATCH 181/863] feat(builtins): tune validation in multiply --- src/builtins/multiply/index.ts | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts index 717c68507..cd2a74837 100644 --- a/src/builtins/multiply/index.ts +++ b/src/builtins/multiply/index.ts @@ -1,5 +1,4 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; import { ExecutePlugin, PluginParams, @@ -8,11 +7,6 @@ import { import {validate} from '../../util/validations'; -import {STRINGS} from '../../config'; - -const {MissingInputDataError} = ERRORS; -const {MISSING_INPUT_DATA} = STRINGS; - export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { const metadata = { kind: 'execute', @@ -40,14 +34,18 @@ export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToMultiply => { - if ( - input[metricToMultiply] === undefined || - isNaN(input[metricToMultiply]) - ) { - throw new MissingInputDataError(MISSING_INPUT_DATA(metricToMultiply)); - } - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.number()); + + validate(validationSchema, inputData); return input; }; @@ -61,17 +59,17 @@ export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { const outputParameter = safeGlobalConfig['output-parameter']; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); + validateSingleInput(input, inputParameters); return { ...input, - [outputParameter]: calculateProduct(safeInput, inputParameters), + [outputParameter]: calculateProduct(input, inputParameters), }; }); }; /** - * Calculates the product of the energy components. + * Calculates the product of the components. */ const calculateProduct = (input: PluginParams, inputParameters: string[]) => inputParameters.reduce( From 887d91210ce9298c66c72f27b26529ca71a0116c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:23:42 +0400 Subject: [PATCH 182/863] feat(builtins): tune validation in exponent --- src/builtins/exponent/index.ts | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 90d66cd72..493993fc9 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -1,5 +1,4 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; import { ExecutePlugin, PluginParams, @@ -8,11 +7,6 @@ import { import {validate} from '../../util/validations'; -import {STRINGS} from '../../config'; - -const {MissingInputDataError, InputValidationError} = ERRORS; -const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS; - export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const metadata = { kind: 'execute', @@ -38,20 +32,13 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { * Checks for required fields in input. */ const validateSingleInput = (input: PluginParams, inputParameter: string) => { - validateParamExists(input, inputParameter); - validateNumericString(input[inputParameter]); - }; + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); - const validateParamExists = (input: PluginParams, param: string) => { - if (input[param] === undefined) { - throw new MissingInputDataError(MISSING_INPUT_DATA(param)); - } - }; - - const validateNumericString = (str: string) => { - if (isNaN(+Number(str))) { - throw new InputValidationError(NOT_NUMERIC_VALUE(str)); - } + return input; }; /** @@ -60,9 +47,10 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const execute = (inputs: PluginParams[]): PluginParams[] => { const { 'input-parameter': inputParameter, - exponent: exponent, + exponent, 'output-parameter': outputParameter, } = validateGlobalConfig(); + return inputs.map(input => { validateSingleInput(input, inputParameter); From a15c28edc3eeaf9fcc0c23d6cd8ae3afaaac4502 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:24:48 +0400 Subject: [PATCH 183/863] feat(builtins): tune validation and zero devision in divide --- src/builtins/divide/index.ts | 38 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts index a38e3601b..453a50921 100644 --- a/src/builtins/divide/index.ts +++ b/src/builtins/divide/index.ts @@ -7,7 +7,7 @@ import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -21,16 +21,16 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const safeGlobalConfig = validateGlobalConfig(); const {numerator, denominator, output} = safeGlobalConfig; - return inputs.map(input => { + return inputs.map((input, index) => { const safeInput = Object.assign( {}, input, - validateSingleInput(input, numerator, denominator) + validateSingleInput(input, {numerator, denominator}) ); return { ...input, - [output]: calculateDivide(safeInput, numerator, denominator), + [output]: calculateDivide(safeInput, index, {numerator, denominator}), }; }); }; @@ -45,7 +45,7 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const schema = z.object({ numerator: z.string().min(1), - denominator: z.string().or(z.number().gt(0)), + denominator: z.string().or(z.number()), output: z.string(), }); @@ -57,9 +57,13 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateSingleInput = ( input: PluginParams, - numerator: string, - denominator: number | string + params: { + numerator: string; + denominator: number | string; + } ) => { + const {numerator, denominator} = params; + const schema = z .object({ [numerator]: z.number(), @@ -69,6 +73,7 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { if (typeof denominator === 'string' && !input[denominator]) { throw new MissingInputDataError(MISSING_INPUT_DATA(denominator)); } + return true; }); @@ -80,9 +85,22 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const calculateDivide = ( input: PluginParams, - numerator: string, - denominator: number | string - ) => input[numerator] / (input[denominator] || denominator); + index: number, + params: { + numerator: string; + denominator: number | string; + } + ) => { + const {denominator, numerator} = params; + const finalDenominator = input[denominator] || denominator; + + if (finalDenominator === 0) { + console.warn(ZERO_DIVISION(Divide.name, index)); + return input[numerator]; + } + + return input[numerator] / finalDenominator; + }; return { metadata, From 11e832327f70046235124c6b6f96169ea89c053c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:27:38 +0400 Subject: [PATCH 184/863] feat(builtins): tune validation in coefficient --- src/builtins/coefficient/index.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts index aed444ad3..2d4f6a1c9 100644 --- a/src/builtins/coefficient/index.ts +++ b/src/builtins/coefficient/index.ts @@ -28,6 +28,8 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { const coefficient = safeGlobalConfig['coefficient']; return inputs.map(input => { + validateSingleInput(input, inputParameter); + return { ...input, [outputParameter]: calculateProduct(input, inputParameter, coefficient), @@ -35,6 +37,19 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { }); }; + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); + + return input; + }; + /** * Calculates the product of the energy components. */ From 9df90fbd245e2fb0a7f059919f0da237733a76f5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:30:10 +0400 Subject: [PATCH 185/863] test(builtins): fix units after refactor --- src/__tests__/unit/builtins/divide.test.ts | 30 +++++++++++--------- src/__tests__/unit/builtins/exponent.test.ts | 13 +++++---- src/__tests__/unit/builtins/multiply.test.ts | 11 ++++--- src/__tests__/unit/builtins/subtract.test.ts | 7 ++--- src/__tests__/unit/builtins/sum.test.ts | 8 ++++-- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts index 79fc6c0b5..ba75e3879 100644 --- a/src/__tests__/unit/builtins/divide.test.ts +++ b/src/__tests__/unit/builtins/divide.test.ts @@ -126,9 +126,6 @@ describe('builtins/divide: ', () => { }); it('throws an error when `denominator` is 0.', async () => { - const expectedMessage = - '"denominator" parameter is number must be greater than 0. Error code: too_small.'; - const globalConfig = { numerator: 'vcpus-allocated', denominator: 0, @@ -138,17 +135,22 @@ describe('builtins/divide: ', () => { expect.assertions(1); - try { - await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, - ]); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(expectedMessage)); - } + const response = await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]); + + expect(response).toEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + 'vcpus-allocated-per-second': 24, + }, + ]); }); it('throws an error when `denominator` is string.', async () => { diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts index c139a5608..ad438179d 100644 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ b/src/__tests__/unit/builtins/exponent.test.ts @@ -2,10 +2,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Exponent} from '../../../builtins/exponent'; -import {STRINGS} from '../../../config'; - -const {InputValidationError, MissingInputDataError} = ERRORS; -const {NOT_NUMERIC_VALUE, MISSING_INPUT_DATA} = STRINGS; +const {InputValidationError} = ERRORS; describe('builtins/exponent: ', () => { describe('Exponent: ', () => { @@ -59,7 +56,9 @@ describe('builtins/exponent: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new MissingInputDataError(MISSING_INPUT_DATA('energy/base')) + new InputValidationError( + '"input-parameter" parameter is required. Error code: invalid_type.' + ) ); } }); @@ -78,7 +77,9 @@ describe('builtins/exponent: ', () => { await exponent.execute(input); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(NOT_NUMERIC_VALUE(input[0]['energy/base'])) + new InputValidationError( + '"input-parameter" parameter is expected number, received string. Error code: invalid_type.' + ) ); } }); diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts index f191ae169..d15a7e8f9 100644 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ b/src/__tests__/unit/builtins/multiply.test.ts @@ -2,10 +2,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Multiply} from '../../../builtins/multiply'; -import {STRINGS} from '../../../config'; - -const {MissingInputDataError} = ERRORS; -const {MISSING_INPUT_DATA} = STRINGS; +const {InputValidationError} = ERRORS; describe('builtins/multiply: ', () => { describe('Multiply: ', () => { @@ -62,7 +59,9 @@ describe('builtins/multiply: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new MissingInputDataError(MISSING_INPUT_DATA('cpu/energy')) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); @@ -88,10 +87,10 @@ describe('builtins/multiply: ', () => { const expectedResult = [ { duration: 3600, + timestamp: '2021-01-01T00:00:00Z', carbon: 3, 'other-carbon': 2, 'carbon-product': 6, - timestamp: '2021-01-01T00:00:00Z', }, ]; diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts index b84b05db8..fd4cf7c96 100644 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ b/src/__tests__/unit/builtins/subtract.test.ts @@ -2,10 +2,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Subtract} from '../../../builtins/subtract'; -import {STRINGS} from '../../../config'; - const {InputValidationError} = ERRORS; -const {MISSING_INPUT_DATA} = STRINGS; describe('builtins/subtract: ', () => { describe('Subtract: ', () => { @@ -62,7 +59,9 @@ describe('builtins/subtract: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(MISSING_INPUT_DATA('cpu/energy')) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts index dbd05a783..1810fc13a 100644 --- a/src/__tests__/unit/builtins/sum.test.ts +++ b/src/__tests__/unit/builtins/sum.test.ts @@ -4,8 +4,8 @@ import {Sum} from '../../../builtins/sum'; import {STRINGS} from '../../../config'; -const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; describe('builtins/sum: ', () => { describe('Sum: ', () => { @@ -85,7 +85,9 @@ describe('builtins/sum: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new MissingInputDataError(MISSING_INPUT_DATA('cpu/energy')) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); From 8c090cc7233209e83f1d75a01af1694deda5ff04 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 23 Jun 2024 20:49:15 +0400 Subject: [PATCH 186/863] chore(config): add coverage ignore patterns --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index 2e770bcad..016be5863 100644 --- a/jest.config.js +++ b/jest.config.js @@ -15,4 +15,5 @@ module.exports = { './src/__tests__/integration/helpers', './src/__tests__/integration/test-data', ], + coveragePathIgnorePatterns: ['src/config', 'src/types'], }; From 6f3089d1623bba9a8ce41d06d4f82a8a3825e4c1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 00:15:21 +0400 Subject: [PATCH 187/863] fix(builtins): sci logic --- src/builtins/sci/index.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index f119f667a..3bc4fedf0 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -41,22 +41,18 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { const safeInput = validateInput(input); const functionalUnit = input[globalConfig['functional-unit']]; - let sci: any = {}; - - if (safeInput['carbon'] > 0) { - if (functionalUnit === 0) { - console.warn(ZERO_DIVISION(Sci.name, index)); - sci = safeInput['carbon']; - } else { - sci = safeInput['carbon'] / functionalUnit; - } - } else { - sci = 0; + if (functionalUnit === 0) { + console.warn(ZERO_DIVISION(Sci.name, index)); + + return { + ...input, + sci: safeInput['carbon'], + }; } return { ...input, - sci, + sci: safeInput['carbon'] / functionalUnit, }; }); From 317119c5f05c063ab685a745962e57ad4167cbd7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 00:15:54 +0400 Subject: [PATCH 188/863] test(builtins): add zero case to sci --- src/__tests__/unit/builtins/sci.test.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts index c12085d4e..6a8ddc8db 100644 --- a/src/__tests__/unit/builtins/sci.test.ts +++ b/src/__tests__/unit/builtins/sci.test.ts @@ -140,5 +140,26 @@ describe('builtins/sci:', () => { } }); }); + + it('fallbacks to carbon value, if functional unit is 0.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 1, + requests: 0, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); + }); }); }); From 791b38f03a28f71f2c78fdf6dd8d26996a668f51 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 00:40:57 +0400 Subject: [PATCH 189/863] fix(builtins): exponent limitation --- src/builtins/exponent/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 493993fc9..ce4e959ef 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -18,7 +18,7 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const validateGlobalConfig = () => { const globalConfigSchema = z.object({ 'input-parameter': z.string().min(1), - exponent: z.number().min(1), + exponent: z.number(), 'output-parameter': z.string().min(1), }); @@ -70,6 +70,7 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { exponent: number ) => { const base = input[inputParameter]; + return Math.pow(base, exponent); }; From fbd34a62436a1c3fe8e41ee5759fd731826950b6 Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:01:23 +0100 Subject: [PATCH 190/863] Update src/builtins/copy-param/index.ts Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/copy-param/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts index 3f3e1f5ae..4501dccc8 100644 --- a/src/builtins/copy-param/index.ts +++ b/src/builtins/copy-param/index.ts @@ -8,7 +8,6 @@ import {STRINGS} from '../../config'; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; const {GlobalConfigError, MissingInputDataError} = ERRORS; -// global-config: // 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) From 332bc6b35aa37b9fd717d213b45bcc2c2ce448a8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 12:16:55 +0400 Subject: [PATCH 191/863] fix(builtins): fix typo in csv lookup readme Signed-off-by: Narek Hovhannisyan --- src/builtins/csv-lookup/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index eb62f8c7e..3663f4123 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -144,7 +144,7 @@ The results will be saved to a new `yaml` file in `manifests/outputs`. ## Errors -`Coefficient exposes six of the IF error classes. +Coefficient exposes six of the IF error classes. ### FetchingFileError From 85c89f25e03809b59c5dde49d89d842107c57da8 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:35:24 +0100 Subject: [PATCH 192/863] fix(lib): use zod to validate single inputs --- src/builtins/copy-param/index.ts | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts index 4501dccc8..6301bbf25 100644 --- a/src/builtins/copy-param/index.ts +++ b/src/builtins/copy-param/index.ts @@ -6,8 +6,8 @@ import {validate} from '../../util/validations'; import {STRINGS} from '../../config'; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; -const {GlobalConfigError, MissingInputDataError} = ERRORS; +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) @@ -40,10 +40,22 @@ export const Copy = (globalConfig: Record): ExecutePlugin => { /** * Checks for required fields in input. */ - const validateSingleInput = (input: PluginParams, parameter: string) => { - if (!input[parameter]) { - throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); - } + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.string()); + + validate(validationSchema, inputData); return input; }; @@ -55,7 +67,7 @@ export const Copy = (globalConfig: Record): ExecutePlugin => { const to = safeGlobalConfig['to']; return inputs.map(input => { - const safeInput = validateSingleInput(input, from); + const safeInput = validateSingleInput(input, [from]); const outputValue = safeInput[from]; if (safeInput[from]) { From 46440a8c78fd8162e5bcf31d3276e629a862589f Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:37:59 +0100 Subject: [PATCH 193/863] fix(lib): update unit tests to expect errors to surface from zod --- src/__tests__/unit/builtins/copy-param.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts index cf5166107..64809e44a 100644 --- a/src/__tests__/unit/builtins/copy-param.test.ts +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -4,8 +4,8 @@ import {Copy} from '../../../builtins/copy-param'; import {STRINGS} from '../../../config'; -const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; describe('builtins/copy: ', () => { describe('Copy: ', () => { @@ -86,7 +86,9 @@ describe('builtins/copy: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new MissingInputDataError(MISSING_INPUT_DATA('original')) + new InputValidationError( + '"original" parameter is required. Error code: invalid_type.' + ) ); } }); From 3e6c970277e8e86b7f28bbdf45879f56e772e58d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 14:23:35 +0400 Subject: [PATCH 194/863] fix(config): add sci missing functional unit to strings --- src/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index b89822794..31e485b24 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -86,6 +86,8 @@ ${error}`, `Unexpected date datatype: ${typeof date}: ${date}`, INVALID_OBSERVATION_OVERLAP: 'Observation timestamps overlap, please check inputs.', + SCI_MISSING_FN_UNIT: (functionalUnit: string) => + `'carbon' and ${functionalUnit} should be present in your input data.`, /** Exhaust messages */ OUTPUT_REQUIRED: 'Output path is required, please make sure output is configured properly.', From b12e968062e647bc59bba2289aca48afa44b3c1a Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:48:44 +0100 Subject: [PATCH 195/863] Update src/builtins/regex/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/regex/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index 62f05bca9..f079b0461 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -97,7 +97,7 @@ The results will be saved to a new `yaml` file in `manifests/outputs`. ### `MissingInputDataError` This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the ``inputs` array must contain: +Every element in the `inputs` array must contain: - `timestamp` - `duration` - whatever value you passed to `parameter` From c561cda14a8c74598516f13c27d8f061fda5658f Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:48:51 +0100 Subject: [PATCH 196/863] Update src/builtins/multiply/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/multiply/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index ae410bba5..7e9c2dfbd 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -101,7 +101,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs` ### `MissingInputDataError` This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the ``inputs` array must contain: +Every element in the `inputs` array must contain: - `timestamp` - `duration` - whatever values you passed to `input-parameters` From 2c1b26be991d9dc2a1fd3a1244b4b3e32599736c Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:48:56 +0100 Subject: [PATCH 197/863] Update src/builtins/exponent/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/exponent/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index e484ea74d..91d938cef 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -103,7 +103,7 @@ The results will be saved to a new `yaml` file in `manifests/outputs`. ### `MissingInputDataError` This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the ``inputs` array must contain: +Every element in the `inputs` array must contain: - `timestamp` - `duration` From 04ef096e4aed3be1071075604dd3342217e727eb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 15:17:21 +0400 Subject: [PATCH 198/863] docs(builtins): add note for zero devision --- src/builtins/divide/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index 20ed19f55..0d753dd53 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -26,6 +26,8 @@ For example, `boavizta-cpu` need `cpu/number-cores` to work, however `cloud-meta The plugin throws an exception if the division result is not a number. +>Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. + ## Calculation ```pseudocode From 34832d1e3860c03f900d84d25ee0b2c5add2c1fd Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 16:49:10 +0400 Subject: [PATCH 199/863] fix(builtins): use error message from config in sci --- src/builtins/sci/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index 3bc4fedf0..47d495351 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -10,6 +10,7 @@ const {MissingInputDataError} = ERRORS; const { MISSING_FUNCTIONAL_UNIT_CONFIG, MISSING_FUNCTIONAL_UNIT_INPUT, + SCI_MISSING_FN_UNIT, ZERO_DIVISION, } = STRINGS; @@ -60,8 +61,6 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { * Checks for fields in input. */ const validateInput = (input: PluginParams) => { - const message = `'carbon' and ${globalConfig['functional-unit']} should be present in your input data.`; - const validatedConfig = validateConfig(globalConfig); if ( @@ -78,7 +77,9 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { carbon: z.number().gte(0), duration: z.number().gte(1), }) - .refine(allDefined, {message}); + .refine(allDefined, { + message: SCI_MISSING_FN_UNIT(globalConfig['functional-unit']), + }); return validate>(schema, input); }; From 6df9a5cdddc0193c9812224d3f8b0f9a3e4fc185 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 24 Jun 2024 16:49:45 +0400 Subject: [PATCH 200/863] docs(builtins): add note for zero devision in sci --- src/builtins/sci/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 658209f1a..f46bb2b03 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -19,6 +19,8 @@ - `sci`: carbon expressed in terms of the given functional unit +>Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. + ## Calculation SCI is calculated as: From 67e1595e668b4de45866d84e7fd25419a40fa079 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 24 Jun 2024 19:28:10 +0400 Subject: [PATCH 201/863] fix(util): add some function into helpers.ts from env.ts --- src/util/helpers.ts | 102 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 0c422c96f..612ee6e85 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,15 +1,38 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; -import {ERRORS} from '@grnsft/if-core/utils'; +import * as fs from 'fs/promises'; +import * as path from 'path'; -import {logger} from './logger'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {STRINGS} from '../config'; +import {STRINGS, CONFIG} from '../config'; import {Difference} from '../types/lib/compare'; +import {load} from '../lib/load'; + +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, +} from './npm'; + +import {logger} from './logger'; +import {EnvironmentOptions} from '../types/if-env'; + +const {IF_ENV} = CONFIG; +const { + FAILURE_MESSAGE, + FAILURE_MESSAGE_TEMPLATE, + FAILURE_MESSAGE_DEPENDENCIES, +} = IF_ENV; + const {UNSUPPORTED_ERROR} = STRINGS; /** @@ -176,3 +199,76 @@ export const parseManifestFromStdin = async () => { return match![1]; }; + +/** + * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + */ +export const getOptionsFromArgs = async (commandArgs: { + manifest: string; + install: boolean | undefined; +}) => { + const {manifest, install} = commandArgs; + const folderPath = path.dirname(manifest); + const loadedManifest = await load(manifest); + const rawManifest = loadedManifest.rawManifest; + const plugins = rawManifest?.initialize?.plugins || {}; + const dependencies = rawManifest?.execution?.environment.dependencies || []; + + if (!dependencies.length) { + throw new Error(FAILURE_MESSAGE_DEPENDENCIES); + } + + const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); + + return { + folderPath, + dependencies: pathsWithVersion, + install, + }; +}; + +/** + * Creates folder if not exists, installs dependencies if required, update depenedencies. + */ +export const initializeAndInstallLibs = async (options: EnvironmentOptions) => { + try { + const {folderPath, install, cwd, dependencies} = options; + const packageJsonPath = await initPackageJsonIfNotExists(folderPath); + + await updatePackageJsonProperties(packageJsonPath, !cwd); + + if (install) { + await installDependencies(folderPath, dependencies); + } else { + await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); + } + } catch (error) { + console.log(FAILURE_MESSAGE); + process.exit(2); + } +}; + +/** + * Adds a manifest template to the folder where the if-env CLI command runs. + */ +export const addTemplateManifest = async (destinationDir: string) => { + try { + const templateManifest = path.resolve( + __dirname, + '../config/env-template.yml' + ); + + console.log('--templateManifest', templateManifest); + + const destinationPath = path.resolve(destinationDir, 'manifest.yml'); + + const data = await fs.readFile(templateManifest, 'utf-8'); + console.log('--after read'); + await fs.writeFile(destinationPath, '', 'utf-8'); + await fs.writeFile(destinationPath, data, 'utf-8'); + } catch (error) { + console.log('---errr', error); + console.log(FAILURE_MESSAGE_TEMPLATE); + process.exit(1); + } +}; From b3e49bb629be161efea00601239c0d3874f3cc1b Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 24 Jun 2024 19:29:57 +0400 Subject: [PATCH 202/863] fix(util): remove unnecessary logs --- src/util/helpers.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 612ee6e85..3912b63e0 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -258,16 +258,12 @@ export const addTemplateManifest = async (destinationDir: string) => { '../config/env-template.yml' ); - console.log('--templateManifest', templateManifest); - const destinationPath = path.resolve(destinationDir, 'manifest.yml'); - const data = await fs.readFile(templateManifest, 'utf-8'); - console.log('--after read'); + await fs.writeFile(destinationPath, '', 'utf-8'); await fs.writeFile(destinationPath, data, 'utf-8'); } catch (error) { - console.log('---errr', error); console.log(FAILURE_MESSAGE_TEMPLATE); process.exit(1); } From 3bfa2858025cda8ae9eab4bc604ebc22ced0c1cf Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 24 Jun 2024 19:39:16 +0400 Subject: [PATCH 203/863] test(util): add test for helpers function --- src/__tests__/unit/util/helpers.test.ts | 106 ++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index ba89850a3..5757628ad 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -1,3 +1,5 @@ +import {jest} from '@jest/globals'; + const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -11,6 +13,67 @@ jest.mock('../../../util/logger', () => ({ }, })); +jest.mock('path', () => { + const actualPath = jest.requireActual('path') as Record; + return { + __esModule: true, + ...actualPath, + dirname: jest.fn(() => './mock-path'), + }; +}); + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +jest.mock('../../../lib/load', () => ({ + load: jest.fn(() => { + if (process.env.manifest === 'true') { + return { + rawManifest: { + name: 'divide', + initialize: { + plugins: { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + 'global-config': { + numerator: 'vcpus-allocated', + denominator: 2, + output: 'cpu/number-cores', + }, + }, + }, + }, + execution: { + environment: { + dependencies: [ + '@grnsft/if-core@0.0.7', + '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models', + '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', + ], + }, + }, + }, + }; + } + return { + rawManifest: { + initialize: { + plugins: {'@grnsft/if-plugins': '1.0.0'}, + }, + execution: { + environment: { + dependencies: [], + }, + }, + }, + }; + }), +})); + import {ERRORS} from '@grnsft/if-core/utils'; import { @@ -20,8 +83,13 @@ import { mergeObjects, oneIsPrimitive, parseManifestFromStdin, + getOptionsFromArgs, } from '../../../util/helpers'; import {Difference} from '../../../types/lib/compare'; +import {CONFIG} from '../../../config'; + +const {IF_ENV} = CONFIG; +const {FAILURE_MESSAGE_DEPENDENCIES} = IF_ENV; const {WriteFileError} = ERRORS; @@ -399,4 +467,42 @@ description: mock-description expect(response).toBeFalsy(); }); }); + + describe('getOptionsFromArgs(): ', () => { + it('returns the correct options when dependencies are present.', async () => { + const commandArgs = { + manifest: '/path/to/mock-manifest.json', + install: false, + }; + + process.env.manifest = 'true'; + + const result = await getOptionsFromArgs(commandArgs); + expect.assertions(1); + + expect(result).toEqual({ + folderPath: './mock-path', + dependencies: { + '@grnsft/if-plugins': '^v0.3.2', + }, + install: false, + }); + }); + + it('throws an error when there are no dependencies.', async () => { + const commandArgs = { + manifest: '/path/to/mock-manifest.json', + install: false, + }; + + process.env.manifest = 'false'; + + expect.assertions(1); + try { + await getOptionsFromArgs(commandArgs); + } catch (error) { + expect(error).toEqual(new Error(FAILURE_MESSAGE_DEPENDENCIES)); + } + }); + }); }); From 276589f69d0d16c09d4b27992e695d18ce5ffd4e Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 24 Jun 2024 19:41:09 +0400 Subject: [PATCH 204/863] fix(src): move some funcions into helpers --- src/env.ts | 92 ++++-------------------------------------------------- 1 file changed, 6 insertions(+), 86 deletions(-) diff --git a/src/env.ts b/src/env.ts index 1775c3fd3..48b0b76b9 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,31 +1,19 @@ #!/usr/bin/env node /* eslint-disable no-process-exit */ -import * as fs from 'fs/promises'; -import * as path from 'path'; - -import { - installDependencies, - initPackageJsonIfNotExists, - updatePackageJsonDependencies, - extractPathsWithVersion, - updatePackageJsonProperties, -} from './util/npm'; import {parseIfEnvArgs} from './util/args'; import {logger} from './util/logger'; -import {load} from './lib/load'; - import {CONFIG} from './config'; import {EnvironmentOptions} from './types/if-env'; +import { + addTemplateManifest, + getOptionsFromArgs, + initializeAndInstallLibs, +} from './util/helpers'; const {IF_ENV} = CONFIG; -const { - SUCCESS_MESSAGE, - FAILURE_MESSAGE, - FAILURE_MESSAGE_TEMPLATE, - FAILURE_MESSAGE_DEPENDENCIES, -} = IF_ENV; +const {SUCCESS_MESSAGE} = IF_ENV; const IfEnv = async () => { const commandArgs = await parseIfEnvArgs(); @@ -54,74 +42,6 @@ const IfEnv = async () => { process.exit(0); }; -/** - * Gets the folder path of manifest file, dependencies from manifest file and install argument from the given arguments. - */ -const getOptionsFromArgs = async (commandArgs: { - manifest: string; - install: boolean | undefined; -}) => { - const {manifest: manifestPath, install} = commandArgs; - const folderPath = path.dirname(manifestPath); - const manifest = await load(manifestPath); - const plugins = manifest.rawManifest?.initialize?.plugins || {}; - const dependencies = - manifest.rawManifest?.execution?.environment.dependencies || []; - - if (!dependencies.length) { - throw new Error(FAILURE_MESSAGE_DEPENDENCIES); - } - - const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); - - return { - folderPath, - dependencies: pathsWithVersion, - install, - }; -}; - -/** - * Creates folder if not exists, installs dependencies if required, update depenedencies. - */ -const initializeAndInstallLibs = async (options: EnvironmentOptions) => { - try { - const {folderPath, install, cwd, dependencies} = options; - const packageJsonPath = await initPackageJsonIfNotExists(folderPath); - - await updatePackageJsonProperties(packageJsonPath, !cwd); - - if (install) { - await installDependencies(folderPath, dependencies); - } else { - await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); - } - } catch (error) { - console.log(FAILURE_MESSAGE); - process.exit(2); - } -}; - -/** - * Adds a manifest template to the folder where the if-env CLI command runs. - */ -const addTemplateManifest = async (destinationDir: string) => { - try { - const templateManifest = path.resolve( - __dirname, - './config/env-template.yml' - ); - const destinationPath = path.resolve(destinationDir, 'manifest.yml'); - - const data = await fs.readFile(templateManifest, 'utf-8'); - await fs.writeFile(destinationPath, '', 'utf-8'); - await fs.writeFile(destinationPath, data, 'utf-8'); - } catch (error) { - console.log(FAILURE_MESSAGE_TEMPLATE); - process.exit(1); - } -}; - IfEnv().catch(error => { if (error instanceof Error) { logger.error(error); From 13a7019d59f4d23062c38399c27108bdc8261811 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 15:49:20 +0400 Subject: [PATCH 205/863] fix(util): change `CliInputError` to `ParseCliParamsError` error --- src/util/args.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 4f537328d..5d9524390 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -156,7 +156,7 @@ const validateAndParseIfEnvArgs = () => { return parse(IF_ENV.ARGS, IF_ENV.HELP); } catch (error) { if (error instanceof Error) { - throw new CliInputError(error.message); + throw new ParseCliParamsError(error.message); } throw error; @@ -174,14 +174,14 @@ export const parseIfEnvArgs = async () => { const isManifestFileExists = await isFileExists(response); if (!isManifestFileExists) { - throw new CliInputError(MANIFEST_NOT_FOUND); + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); } if (checkIfFileIsYaml(manifest)) { return {manifest: response, install, cwd}; } - throw new CliInputError(FILE_IS_NOT_YAML); + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); } return {install, cwd}; From 66a1c4c49e8bf3c4155508f3e031fb22fdcac701 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 15:50:07 +0400 Subject: [PATCH 206/863] test(util): fix npm test --- src/__tests__/unit/util/npm.test.ts | 31 +++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 9680bf722..403a1138c 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -110,7 +110,6 @@ describe('util/npm: ', () => { const expectedPackageJsonContent = JSON.stringify( { dependencies: { - '@grnsft/if': '^0.3.3-beta.0', '@grnsft/if-plugins': '^0.3.3-beta.0', }, }, @@ -137,7 +136,6 @@ describe('util/npm: ', () => { const expectedPackageJsonContent = JSON.stringify( { dependencies: { - '@grnsft/if': '^0.3.3-beta.0', '@grnsft/if-plugins': '^0.3.3-beta.0', }, }, @@ -220,11 +218,32 @@ describe('util/npm: ', () => { describe('updatePackageJsonProperties(): ', () => { it('updates the package.json properties correctly.', async () => { - const newPackageJsonPath = path.resolve(folderPath, '/package.json-npm'); - await updatePackageJsonProperties(newPackageJsonPath, false); + const packageJsonPath = path.join(folderPath, 'package.json-npm1'); - expect.assertions(2); - expect(fs.readFile).toHaveBeenCalledWith(newPackageJsonPath, 'utf8'); + const expectedPackageJsonContent = JSON.stringify( + { + name: 'if-environment', + description: 'mock-description', + author: {}, + bugs: {}, + engines: {}, + homepage: 'mock-homepage', + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonProperties(packageJsonPath, true); + + expect.assertions(8); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); }); }); }); From 0e789b16468f65b38197ea88fb7acb1372b09d8f Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 15:51:20 +0400 Subject: [PATCH 207/863] test(mocks): add mocks for fs.writeFile --- src/__mocks__/fs/index.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index b7731b4b8..3853ad7ee 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -1,6 +1,7 @@ import * as YAML from 'js-yaml'; import * as fs from 'fs'; import * as fsAsync from 'fs/promises'; +import * as path from 'path'; export const readFile = async (filePath: string) => { /** mock for util/npm */ @@ -89,11 +90,28 @@ cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,g export const mkdir = (dirPath: string) => dirPath; export const writeFile = async (pathToFile: string, content: string) => { - if (pathToFile.includes('package.json-npm')) { + if (pathToFile.includes('package.json-npm1')) { + const updatedPath = pathToFile.replace('-npm1', ''); + const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); + const fileContentObject = JSON.parse(fileContent); + const parsedContent = JSON.parse(content); + + for (const property in fileContentObject) { + expect(parsedContent).toHaveProperty(property); + } + } else if (pathToFile.includes('package.json-npm')) { const updatedPath = pathToFile.replace('-npm', ''); + const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); + + expect(content).toBe(fileContent); + } else if (pathToFile.includes('/manifest.yml')) { + const templateManifest = path.resolve( + __dirname, + '../../config/env-template.yml' + ); + const fileContent = await fsAsync.readFile(templateManifest, 'utf8'); - const content = await fsAsync.readFile(updatedPath, 'utf8'); - expect(content).toBe(content); + expect(content).toBe(fileContent); } else { if (pathToFile === 'reject') { throw new Error('Wrong file path'); From accf32f3d7f957c22b610a9b78f0177af7a9e1ca Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 15:56:06 +0400 Subject: [PATCH 208/863] test(util): add missied tests --- src/__tests__/unit/util/helpers.test.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 5757628ad..24ef57a2d 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -84,12 +84,14 @@ import { oneIsPrimitive, parseManifestFromStdin, getOptionsFromArgs, + addTemplateManifest, + // initializeAndInstallLibs, } from '../../../util/helpers'; import {Difference} from '../../../types/lib/compare'; import {CONFIG} from '../../../config'; const {IF_ENV} = CONFIG; -const {FAILURE_MESSAGE_DEPENDENCIES} = IF_ENV; +const {FAILURE_MESSAGE_DEPENDENCIES, FAILURE_MESSAGE} = IF_ENV; const {WriteFileError} = ERRORS; @@ -505,4 +507,23 @@ description: mock-description } }); }); + + describe('addTemplateManifest(): ', () => { + it('successfully adds the template manifest to the directory.', async () => { + await addTemplateManifest('./'); + + expect.assertions(1); + }); + + it('throws an error when the manifest is not added into the directory.', async () => { + expect.assertions(1); + + try { + await addTemplateManifest(''); + } catch (error) { + const logSpy = jest.spyOn(global.console, 'log'); + expect(logSpy).toEqual(FAILURE_MESSAGE); + } + }); + }); }); From d46d71c3833c519c25088bfcc366ac3917a5ffae Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 15:57:22 +0400 Subject: [PATCH 209/863] fix(util): add `MissingPluginDependenciesError` custom error class --- src/util/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 3912b63e0..b000af60e 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -34,6 +34,7 @@ const { } = IF_ENV; const {UNSUPPORTED_ERROR} = STRINGS; +const {MissingPluginDependenciesError} = ERRORS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -215,7 +216,7 @@ export const getOptionsFromArgs = async (commandArgs: { const dependencies = rawManifest?.execution?.environment.dependencies || []; if (!dependencies.length) { - throw new Error(FAILURE_MESSAGE_DEPENDENCIES); + throw new MissingPluginDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); } const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); @@ -261,7 +262,6 @@ export const addTemplateManifest = async (destinationDir: string) => { const destinationPath = path.resolve(destinationDir, 'manifest.yml'); const data = await fs.readFile(templateManifest, 'utf-8'); - await fs.writeFile(destinationPath, '', 'utf-8'); await fs.writeFile(destinationPath, data, 'utf-8'); } catch (error) { console.log(FAILURE_MESSAGE_TEMPLATE); From 04e514a33186adf5f37bd3d6abdb95dcd0773dbe Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 16:46:52 +0400 Subject: [PATCH 210/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8eb3478c2..3e66c802a 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.7", + "@grnsft/if-core": "^0.0.9", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1183,9 +1183,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.7.tgz", - "integrity": "sha512-+4w8Sq1KRPDb+Jy638wgrTXlXIZzewOBceT+rAy3Oaov1M/veY3gu3AV15SXcPHrsBoFmZ6QeI9g1rF3RKB0ww==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.9.tgz", + "integrity": "sha512-F0niYe1j+NfhH+okz5sjP/CD7w/9BeXXe13bHkCsdOnk0WfXrq0DGKwpqh9TiLbKc9f1P3/XuojeFANMQu5nig==", "dependencies": { "typescript": "^5.1.6" }, diff --git a/package.json b/package.json index 2f3257216..0e03be3ee 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.7", + "@grnsft/if-core": "^0.0.9", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From ad2f87da76d53933afc5589d46739225d76cfec9 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 25 Jun 2024 16:55:08 +0400 Subject: [PATCH 211/863] fix(util): fix dependencies append logic --- src/util/helpers.ts | 2 +- src/util/npm.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b000af60e..e69b9e0e9 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -236,7 +236,7 @@ export const initializeAndInstallLibs = async (options: EnvironmentOptions) => { const {folderPath, install, cwd, dependencies} = options; const packageJsonPath = await initPackageJsonIfNotExists(folderPath); - await updatePackageJsonProperties(packageJsonPath, !cwd); + await updatePackageJsonProperties(packageJsonPath, cwd); if (install) { await installDependencies(folderPath, dependencies); diff --git a/src/util/npm.ts b/src/util/npm.ts index 0cbfe27e1..e7fd8d62b 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -108,7 +108,7 @@ export const extractPathsWithVersion = ( */ export const updatePackageJsonProperties = async ( newPackageJsonPath: string, - resetDependencies: boolean + appendDependencies: boolean ) => { const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); const parsedPackageJsonContent = JSON.parse(packageJsonContent); @@ -120,7 +120,9 @@ export const updatePackageJsonProperties = async ( bugs: packageJson.bugs, engines: packageJson.engines, homepage: packageJson.homepage, - dependencies: resetDependencies ? {} : packageJson.dependencies, + dependencies: appendDependencies + ? parsedPackageJsonContent.dependencies + : {}, }; const newPackageJson = Object.assign( From 621a311092255dd135525828e8edb307b5903efb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 26 Jun 2024 10:01:19 +0400 Subject: [PATCH 212/863] fix(util): typo in npm --- src/util/npm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/npm.ts b/src/util/npm.ts index e7fd8d62b..e453b771b 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -15,7 +15,7 @@ const packageJson = require('../../package.json'); const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; /** - * Checks if the package.json is exists, if not, inisializes it. + * Checks if the package.json is exists, if not, initializes it. */ export const initPackageJsonIfNotExists = async (folderPath: string) => { const packageJsonPath = path.resolve(folderPath, 'package.json'); From 136f062d45788f8ac06a92bd171d5afbf2a152dc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 26 Jun 2024 10:01:53 +0400 Subject: [PATCH 213/863] test(util): add cases for initializeAndInstallLibs --- src/__tests__/unit/util/helpers.test.ts | 144 +++++++++++++++++++++++- 1 file changed, 141 insertions(+), 3 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 24ef57a2d..cef643247 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -1,5 +1,4 @@ -import {jest} from '@jest/globals'; - +/* eslint-disable @typescript-eslint/ban-ts-comment */ const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -74,6 +73,67 @@ jest.mock('../../../lib/load', () => ({ }), })); +const initPackage = jest.fn(() => Promise.resolve('mock-path')); +const updatePackage = jest.fn(() => Promise.resolve(true)); +const installdeps = jest.fn(); +const updatedeps = jest.fn(); +jest.mock('../../../util/npm', () => { + const actualNPMUtil = jest.requireActual('../../../util/npm'); + + return { + ...actualNPMUtil, + initPackageJsonIfNotExists: (folderPath: string) => { + if (process.env.NPM_MOCK === 'true') { + return initPackage(); + } + + if (process.env.NPM_MOCK === 'error') { + throw new Error('mock-error'); + } + + return actualNPMUtil.initPackageJsonIfNotExists(folderPath); + }, + updatePackageJsonProperties: ( + newPackageJsonPath: string, + appendDependencies: boolean + ) => { + if (process.env.NPM_MOCK === 'true') { + return updatePackage(); + } + + return actualNPMUtil.updatePackageJsonProperties( + newPackageJsonPath, + appendDependencies + ); + }, + installDependencies: ( + folderPath: string, + dependencies: {[path: string]: string} + ) => { + if (process.env.NPM_MOCK === 'true') { + return installdeps(); + } + + return actualNPMUtil.installDependencies(folderPath, dependencies); + }, + updatePackageJsonDependencies: ( + packageJsonPath: string, + dependencies: any, + cwd: boolean + ) => { + if (process.env.NPM_MOCK === 'true') { + return updatedeps(); + } + + return actualNPMUtil.updatePackageJsonDependencies( + packageJsonPath, + dependencies, + cwd + ); + }, + }; +}); + import {ERRORS} from '@grnsft/if-core/utils'; import { @@ -85,10 +145,11 @@ import { parseManifestFromStdin, getOptionsFromArgs, addTemplateManifest, + initializeAndInstallLibs, // initializeAndInstallLibs, } from '../../../util/helpers'; -import {Difference} from '../../../types/lib/compare'; import {CONFIG} from '../../../config'; +import {Difference} from '../../../types/lib/compare'; const {IF_ENV} = CONFIG; const {FAILURE_MESSAGE_DEPENDENCIES, FAILURE_MESSAGE} = IF_ENV; @@ -526,4 +587,81 @@ description: mock-description } }); }); + + describe('initializeAndInstallLibs(): ', () => { + beforeEach(() => { + initPackage.mockReset(); + updatePackage.mockReset(); + installdeps.mockReset(); + updatedeps.mockReset(); + }); + + it('installs dependencies if install flag is truthy.', async () => { + process.env.NPM_MOCK = 'true'; + // @ts-ignore + process.exit = (code: any) => code; + const options = { + folderPath: 'mock-folderPath', + install: true, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(4); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(1); + expect(updatePackage).toHaveBeenCalledTimes(1); + expect(installdeps).toHaveBeenCalledTimes(1); + expect(updatedeps).toHaveBeenCalledTimes(0); + }); + + it('updates dependencies if install flag is falsy.', async () => { + process.env.NPM_MOCK = 'true'; + // @ts-ignore + process.exit = (code: any) => code; + const options = { + folderPath: 'mock-folderPath', + install: false, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(4); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(1); + expect(updatePackage).toHaveBeenCalledTimes(1); + expect(installdeps).toHaveBeenCalledTimes(0); + expect(updatedeps).toHaveBeenCalledTimes(1); + }); + + it('exits process if error is thrown.', async () => { + process.env.NPM_MOCK = 'error'; + const mockExit = jest.fn(); + // @ts-ignore + process.exit = mockExit; + const options = { + folderPath: 'mock-folderPath', + install: false, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(5); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(0); + expect(updatePackage).toHaveBeenCalledTimes(0); + expect(installdeps).toHaveBeenCalledTimes(0); + expect(updatedeps).toHaveBeenCalledTimes(0); + expect(mockExit).toHaveBeenCalledTimes(1); + }); + }); }); From 7a466ccccd16dba64133d9b79a2b73c09fbedb0c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 26 Jun 2024 10:04:47 +0400 Subject: [PATCH 214/863] test(util): put back original process exit --- src/__tests__/unit/util/helpers.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index cef643247..d04ad43d2 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -642,6 +642,7 @@ description: mock-description it('exits process if error is thrown.', async () => { process.env.NPM_MOCK = 'error'; + const originalProcessExit = process.exit; const mockExit = jest.fn(); // @ts-ignore process.exit = mockExit; @@ -662,6 +663,8 @@ description: mock-description expect(installdeps).toHaveBeenCalledTimes(0); expect(updatedeps).toHaveBeenCalledTimes(0); expect(mockExit).toHaveBeenCalledTimes(1); + + process.exit = originalProcessExit; }); }); }); From ed31d52cb1320ede6ac2c8f3f96b3a6f22c5bd3a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 26 Jun 2024 10:14:16 +0400 Subject: [PATCH 215/863] fix(src): add newline to package.json Signed-off-by: Narek Hovhannisyan --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e03be3ee..e9f2f2777 100644 --- a/package.json +++ b/package.json @@ -88,4 +88,4 @@ }, "stability": "stable", "types": "src/index.d.ts" -} \ No newline at end of file +} From d56cd86d07246546fdf7259ab8768afeea486bae Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:59:27 +0100 Subject: [PATCH 216/863] fix(doc): update config in refactor guide --- Refactor-migration-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 95269e1a5..d315d5c41 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -186,7 +186,6 @@ There have also been some changes to the structure of manifest files. Some of th device/expected-lifespan: 94608000 # 3 years in seconds resources-reserved: 1 resources-total: 8 - functional-unit-time: "1 min" ``` From dc85178880cb7ee65897f79b38de16bcd941fa13 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:00:57 +0100 Subject: [PATCH 217/863] fix(manifests): fix sci config in example manifests --- manifests/bugs/aggregation-error-wrong-metric.yml | 3 --- manifests/bugs/pipeline-ordering-error.yml | 1 - manifests/examples/generics.yml | 1 - manifests/examples/pipeline-with-aggregate.yml | 1 - manifests/examples/pipeline-with-mocks.yml | 2 -- manifests/plugins/sci/failure-missing-input-param.yml | 8 ++------ manifests/plugins/sci/success.yml | 3 --- 7 files changed, 2 insertions(+), 17 deletions(-) diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml index f95a9eed7..536508b59 100644 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ b/manifests/bugs/aggregation-error-wrong-metric.yml @@ -34,7 +34,6 @@ initialize: method: Sci global-config: functional-unit: "requests" - functional-unit-time: "1 minute" "time-sync": method: TimeSync path: "builtin" @@ -69,7 +68,6 @@ tree: device/expected-lifespan: 94608000 # 3 years in seconds resources-reserved: 1 resources-total: 8 - functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -112,7 +110,6 @@ tree: device/expected-lifespan: 94608000 # 3 years in seconds resources-reserved: 1 resources-total: 8 - functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/bugs/pipeline-ordering-error.yml b/manifests/bugs/pipeline-ordering-error.yml index 554134287..a561ea24d 100644 --- a/manifests/bugs/pipeline-ordering-error.yml +++ b/manifests/bugs/pipeline-ordering-error.yml @@ -30,7 +30,6 @@ initialize: method: Sci global-config: functional-unit: "" - functional-unit-time: "1-day" "time-sync": method: TimeSync path: "builtin" diff --git a/manifests/examples/generics.yml b/manifests/examples/generics.yml index c3ffa52e2..b3de5e007 100644 --- a/manifests/examples/generics.yml +++ b/manifests/examples/generics.yml @@ -33,7 +33,6 @@ tree: children: child-1: pipeline: - - teads-curve - sum - coefficient - multiply diff --git a/manifests/examples/pipeline-with-aggregate.yml b/manifests/examples/pipeline-with-aggregate.yml index d1b90b152..65d6c9d26 100644 --- a/manifests/examples/pipeline-with-aggregate.yml +++ b/manifests/examples/pipeline-with-aggregate.yml @@ -62,7 +62,6 @@ initialize: path: "builtin" method: Sci global-config: - functional-unit-time: 1 sec functional-unit: requests # factor to convert per time to per f.unit "sum-carbon": path: "builtin" diff --git a/manifests/examples/pipeline-with-mocks.yml b/manifests/examples/pipeline-with-mocks.yml index fde8963ef..801b7bfd9 100644 --- a/manifests/examples/pipeline-with-mocks.yml +++ b/manifests/examples/pipeline-with-mocks.yml @@ -129,7 +129,6 @@ tree: device/expected-lifespan: 94608000 # 3 years in seconds vcpus-total: 8 vcpus-allocated: 1 - functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -177,7 +176,6 @@ tree: # device/expected-lifespan: 94608000 # 3 years in seconds # resources-reserved: 1 # resources-total: 8 - # functional-unit-time: "1 min" # inputs: # - timestamp: "2023-12-12T00:00:00.000Z" # duration: 1 diff --git a/manifests/plugins/sci/failure-missing-input-param.yml b/manifests/plugins/sci/failure-missing-input-param.yml index 44ced7374..54514a8e5 100644 --- a/manifests/plugins/sci/failure-missing-input-param.yml +++ b/manifests/plugins/sci/failure-missing-input-param.yml @@ -8,17 +8,13 @@ initialize: kind: plugin method: Sci path: "builtin" - # global-config: - # functional-unit: requests + global-config: + functional-unit: requests tree: children: child: pipeline: - sci - config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/plugins/sci/success.yml b/manifests/plugins/sci/success.yml index c7e6dbde6..cddfe5755 100644 --- a/manifests/plugins/sci/success.yml +++ b/manifests/plugins/sci/success.yml @@ -16,9 +16,6 @@ tree: pipeline: - sci config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 From a853e10f074516e57840888c27ec15d7b71baf5d Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:03:33 +0100 Subject: [PATCH 218/863] fix(lib): fix sci config in csv export test --- src/__mocks__/builtins/export-csv.ts | 5 ----- src/__tests__/unit/builtins/export-csv-raw.test.ts | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/__mocks__/builtins/export-csv.ts b/src/__mocks__/builtins/export-csv.ts index e8fc2a26f..1f0e00e73 100644 --- a/src/__mocks__/builtins/export-csv.ts +++ b/src/__mocks__/builtins/export-csv.ts @@ -14,7 +14,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', }, inputs: [ { @@ -43,7 +42,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', 'cpu/energy': 0.000008888888888888888, "carbon-plus-energy'": 10.000008888888889, 'carbon-embodied': 0.0000020256215119228817, @@ -65,7 +63,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', }, inputs: [ { @@ -94,7 +91,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', 'cpu/energy': 0.00001650338753387534, "carbon-plus-energy'": 10.000016503387533, 'carbon-embodied': 0.0000020256215119228817, @@ -154,7 +150,6 @@ export const context: Context = { method: 'Sci', 'global-config': { 'functional-unit': 'requests', - 'functional-unit-time': '1 minute', }, }, }, diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts index ab71e0e34..e97242a4d 100644 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ b/src/__tests__/unit/builtins/export-csv-raw.test.ts @@ -35,7 +35,7 @@ describe('builtins/export-csv-raw: ', () => { it('generates CSV file with correct data.', async () => { const outputPath = 'output#carbon'; const content = - "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,functional-unit-time,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,1 min,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,1 min,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,,8000.000004051243,"; + "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,8000.000004051243,"; await exportCSVRaw.execute(tree, context, outputPath); From 992739668db3d399172c732a45855d3b9f796cd6 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:04:09 +0100 Subject: [PATCH 219/863] fix(lib): rm functional-unit-time from params --- src/config/params.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/config/params.ts b/src/config/params.ts index 377538391..76732e57b 100644 --- a/src/config/params.ts +++ b/src/config/params.ts @@ -62,12 +62,6 @@ export const PARAMETERS: Parameters = { unit: 'none', aggregation: 'sum', }, - 'functional-unit-time': { - description: - 'string describing the unit of time in which the final SCI calculation should be expressed, e.g. "1-min"', - unit: 'none', - aggregation: 'none', - }, 'gpu-util': { description: 'refers to CPU utilization.', unit: 'percentage', From 93769573c2741e9d8463e5edcface259f060a88a Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:48:21 +0100 Subject: [PATCH 220/863] Update src/builtins/copy-param/README.md Co-authored-by: Manushak Keramyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/copy-param/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/copy-param/README.md b/src/builtins/copy-param/README.md index 1ec04f249..634b45448 100644 --- a/src/builtins/copy-param/README.md +++ b/src/builtins/copy-param/README.md @@ -2,7 +2,7 @@ `copy-param` is a generic plugin that duplicates an existing parameter in the `input` data and assigns it to a new key. You can either keep or delete the original copied parameter. A common use case for this is to rename parameters in the `inputs` array. -You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or del;et the original copied value. +You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or delete the original copied value. For example, you could copy `energy` into `energy-copy`, with `keep-existing=true`. In this case your inputs: From 700138c2035ca3403d49dd30361561bdf6097a80 Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:48:28 +0100 Subject: [PATCH 221/863] Update src/builtins/copy-param/README.md Co-authored-by: Manushak Keramyan Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/builtins/copy-param/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/copy-param/README.md b/src/builtins/copy-param/README.md index 634b45448..78ab5f656 100644 --- a/src/builtins/copy-param/README.md +++ b/src/builtins/copy-param/README.md @@ -69,7 +69,7 @@ console.log(result) ## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `sum`: +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 and does not have to be done explicitly by the user. The following is an example manifest that calls `copy-param`: ```yaml name: copy-param From e7034c50f1b6f4fb546b275f273d5d3f3ab623ee Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 26 Jun 2024 17:53:43 +0400 Subject: [PATCH 222/863] feat(util): add isDirectoryExists function --- src/util/fs.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/util/fs.ts b/src/util/fs.ts index 92ca9684a..70cec75e4 100644 --- a/src/util/fs.ts +++ b/src/util/fs.ts @@ -11,3 +11,15 @@ export const isFileExists = async (filePath: string) => { return false; } }; + +/** + * Checks if the directory exists with the given `filePath`. + */ +export const isDirectoryExists = async (directoryPath: string) => { + try { + await fs.access(directoryPath); + return true; + } catch (error) { + return false; + } +}; From ac56ed1150516f77a3df00a241484c15bb8d3fd7 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 26 Jun 2024 18:12:46 +0400 Subject: [PATCH 223/863] fix(util): remove the node_modules folder if the package.json does not persist --- src/util/npm.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/util/npm.ts b/src/util/npm.ts index e453b771b..61baf75b8 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -4,7 +4,7 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import {execPromise} from './helpers'; -import {isFileExists} from './fs'; +import {isDirectoryExists, isFileExists} from './fs'; import {logger} from './logger'; import {STRINGS} from '../config'; @@ -23,6 +23,14 @@ export const initPackageJsonIfNotExists = async (folderPath: string) => { if (!isPackageJsonExists) { logger.info(INITIALIZING_PACKAGE_JSON); + + const nodeModulesPath = path.resolve(folderPath, 'node_modules'); + const isNodeModulesExists = await isDirectoryExists(nodeModulesPath); + + if (isNodeModulesExists) { + await fs.rm(nodeModulesPath, {recursive: true}); + } + await execPromise('npm init -y', {cwd: folderPath}); } From 0258ec68afc31141a83fd87053eeb69118631ab7 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 01:13:27 +0400 Subject: [PATCH 224/863] fix(manifests): update teads usage in bugs --- .../bugs/aggregation-error-wrong-metric.yml | 81 ++++++++++++++----- manifests/bugs/initialize-error-no-config.yml | 9 +-- manifests/bugs/initialize-error-no-path.yml | 14 ++-- .../bugs/input-error-missing-duration.yml | 16 ++-- .../bugs/pipeline-error-naming-mismatch.yml | 12 ++- .../pipeline-error-uninitialized-plugin.yml | 14 ++-- manifests/bugs/pipeline-ordering-error.yml | 75 +++++++++-------- 7 files changed, 140 insertions(+), 81 deletions(-) diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml index 536508b59..60a8dd8dd 100644 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ b/manifests/bugs/aggregation-error-wrong-metric.yml @@ -7,19 +7,48 @@ aggregation: type: "both" initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum-energy-components": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied @@ -27,7 +56,7 @@ initialize: method: Multiply path: builtin global-config: - input-parameters: ["energy", "grid/carbon-intensity"] + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" "sci": path: "builtin" @@ -49,12 +78,16 @@ tree: children: child-1: pipeline: - - teads-curve - - sum-energy-components + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - operational-carbon - time-sync - - sci + # - sci config: group-by: group: @@ -66,8 +99,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -91,12 +124,16 @@ tree: cpu/utilization: 15 child-2: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - time-sync - - sci + # - sci config: group-by: group: @@ -108,8 +145,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/bugs/initialize-error-no-config.yml b/manifests/bugs/initialize-error-no-config.yml index 67973b53f..466c7f5f9 100644 --- a/manifests/bugs/initialize-error-no-config.yml +++ b/manifests/bugs/initialize-error-no-config.yml @@ -3,18 +3,17 @@ description: a negative test case that fails due to plugin initialization missin tags: initialize: plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - outputs: ['yaml'] tree: children: child-0: defaults: cpu/thermal-design-power: 100 pipeline: - - teads-curve + - interpolate inputs: - timestamp: 2023-07-06T00:00 duration: 1 diff --git a/manifests/bugs/initialize-error-no-path.yml b/manifests/bugs/initialize-error-no-path.yml index 21210c544..279f304e6 100644 --- a/manifests/bugs/initialize-error-no-path.yml +++ b/manifests/bugs/initialize-error-no-path.yml @@ -3,19 +3,23 @@ description: a negative test case that fails because the path is mising in a plu tags: initialize: plugins: - teads-curve: + "interpolate": + method: Interpolation path: - method: TeadsCurve global-config: - interpolation: spline - outputs: ['yaml'] + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + # outputs: ['yaml'] tree: children: child-0: defaults: cpu/thermal-design-power: 100 pipeline: - - teads-curve + - interpolate inputs: - timestamp: 2023-07-06T00:00 duration: 1 diff --git a/manifests/bugs/input-error-missing-duration.yml b/manifests/bugs/input-error-missing-duration.yml index 1a4a5d9ef..a2e7f3ca4 100644 --- a/manifests/bugs/input-error-missing-duration.yml +++ b/manifests/bugs/input-error-missing-duration.yml @@ -3,19 +3,23 @@ description: a negative test case that fails due to the required `duration` fiel tags: initialize: plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve + "interpolate": + method: Interpolation + path: builtin global-config: - interpolation: spline - outputs: ['yaml'] + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + # outputs: ['yaml'] tree: children: child-0: defaults: cpu/thermal-design-power: 100 pipeline: - - teads-curve + - interpolate inputs: - timestamp: 2023-07-06T00:00 cpu/utilization: 20 diff --git a/manifests/bugs/pipeline-error-naming-mismatch.yml b/manifests/bugs/pipeline-error-naming-mismatch.yml index 22bb804a4..982e89088 100644 --- a/manifests/bugs/pipeline-error-naming-mismatch.yml +++ b/manifests/bugs/pipeline-error-naming-mismatch.yml @@ -3,11 +3,15 @@ description: a negative test case that fails due to the plugin name in the pipel tags: initialize: plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve + "interpolate": + method: Interpolation + path: builtin global-config: - interpolation: spline + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' outputs: ['yaml'] tree: children: diff --git a/manifests/bugs/pipeline-error-uninitialized-plugin.yml b/manifests/bugs/pipeline-error-uninitialized-plugin.yml index 95afc196b..7bead556b 100644 --- a/manifests/bugs/pipeline-error-uninitialized-plugin.yml +++ b/manifests/bugs/pipeline-error-uninitialized-plugin.yml @@ -4,18 +4,22 @@ tags: initialize: # outputs: ['yaml'] plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve + "interpolate": + method: Interpolation + path: builtin global-config: - interpolation: spline + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' tree: children: child-0: defaults: cpu/thermal-design-power: 100 pipeline: - - teads-curve + - interpolate - multiply inputs: - timestamp: 2023-07-06T00:00 diff --git a/manifests/bugs/pipeline-ordering-error.yml b/manifests/bugs/pipeline-ordering-error.yml index a561ea24d..7fa8836c1 100644 --- a/manifests/bugs/pipeline-ordering-error.yml +++ b/manifests/bugs/pipeline-ordering-error.yml @@ -3,51 +3,58 @@ description: a negative test case that fails because sci-o is invoked too early tags: initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": - path: "builtin" - method: Sum + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy - "sci-embodied": - path: "builtin" - method: SciEmbodied - "operational-carbon": + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": method: Multiply path: builtin global-config: - input-parameters: ["cpu/energy", "grid/carbon-intensity"] - output-parameter: "carbon-operational" - "sci": + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide path: "builtin" - method: Sci global-config: - functional-unit: "" - "time-sync": - method: TimeSync + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide path: "builtin" global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh tree: children: child-1: pipeline: - - teads-curve - - operational-carbon - - sum - - sci-embodied - - time-sync - - sci + - interpolate + - correct-cpu-energy-for-vcpu-ratio + - calculate-vcpu-ratio + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh config: defaults: cpu/thermal-design-power: 100 @@ -55,8 +62,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 From 4aff1f315ba9061ee13f29f03fe8d76d1ed32f16 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 01:14:08 +0400 Subject: [PATCH 225/863] fix(manifests): update teads usage in examples --- manifests/examples/generics.yml | 60 ++++++++--- manifests/examples/nesting.yml | 116 +++++++++++++++------- manifests/examples/pipeline-teads-sci.yml | 63 +++++++++--- 3 files changed, 176 insertions(+), 63 deletions(-) diff --git a/manifests/examples/generics.yml b/manifests/examples/generics.yml index b3de5e007..c319967f0 100644 --- a/manifests/examples/generics.yml +++ b/manifests/examples/generics.yml @@ -3,24 +3,53 @@ description: a pipeline that does arbitrary calculations using our generic arith tags: initialize: plugins: - teads-curve: - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy-sum + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "coefficient": path: "builtin" method: Coefficient global-config: - input-parameter: energy + input-parameter: cpu-energy-kwh coefficient: 2 output-parameter: energy-doubled "multiply": @@ -33,12 +62,19 @@ tree: children: child-1: pipeline: - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - coefficient - multiply config: defaults: cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 diff --git a/manifests/examples/nesting.yml b/manifests/examples/nesting.yml index a5bf89230..b274ae7f0 100644 --- a/manifests/examples/nesting.yml +++ b/manifests/examples/nesting.yml @@ -7,25 +7,53 @@ tags: aggregation: metrics: - "carbon" - - "energy" type: "both" params: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: - teads-curve: - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - sum: + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh sci-embodied: path: "builtin" method: SciEmbodied @@ -33,7 +61,7 @@ initialize: method: Multiply path: builtin global-config: - input-parameters: ["energy", "grid/carbon-intensity"] + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" sci: path: "builtin" @@ -65,16 +93,20 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - operational-carbon - sum-carbon - time-sync - - sci + # - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -111,16 +143,20 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - - sci + # - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -159,16 +195,20 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - - sci + # - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -205,16 +245,20 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - - sci + # - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 diff --git a/manifests/examples/pipeline-teads-sci.yml b/manifests/examples/pipeline-teads-sci.yml index bf20cc251..c07b093bd 100644 --- a/manifests/examples/pipeline-teads-sci.yml +++ b/manifests/examples/pipeline-teads-sci.yml @@ -3,19 +3,48 @@ description: a full pipeline seeded with some hardcoded input data and yielding tags: initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied @@ -23,7 +52,7 @@ initialize: method: Multiply path: builtin global-config: - input-parameters: ["cpu/energy", "grid/carbon-intensity"] + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" "sci": path: "builtin" @@ -50,8 +79,12 @@ tree: children: child-1: pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - operational-carbon - sum-carbon @@ -63,8 +96,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 component: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" From 366899e2ca29f7e73d7ec581826852dc29209014 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 01:14:19 +0400 Subject: [PATCH 226/863] fix(manifests): update teads usage in integrations --- manifests/integrations/mock-obs-time-sync.yml | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/manifests/integrations/mock-obs-time-sync.yml b/manifests/integrations/mock-obs-time-sync.yml index 727caf363..f1f176eb3 100644 --- a/manifests/integrations/mock-obs-time-sync.yml +++ b/manifests/integrations/mock-obs-time-sync.yml @@ -21,11 +21,48 @@ initialize: cpu/utilization: min: 1 max: 99 - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "time-sync": method: TimeSync path: "builtin" @@ -38,10 +75,18 @@ tree: children: child-1: pipeline: - - teads-curve + # - mock-observations + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - time-sync defaults: cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 From 448ecbad0a6207951adf6a61df5560f56aeee5d4 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:21:59 +0400 Subject: [PATCH 227/863] feat(types): add IFCheckArgs type --- src/types/process-args.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 40dece54d..0f3799f5a 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -17,6 +17,11 @@ export interface IFEnvArgs { cwd?: boolean; } +export interface IFCheckArgs { + manifest?: string; + directory?: string; +} + export interface Options { outputPath?: string; stdout?: boolean; From 61d727862bf71e083da21f9e95b69a359563f46c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:24:38 +0400 Subject: [PATCH 228/863] feat(config): add IF_CHECK config --- src/config/config.ts | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index 0f96019f2..b8f676924 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -2,7 +2,12 @@ import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; import {STRINGS} from './strings'; -import {IFDiffArgs, IEArgs, IFEnvArgs} from '../types/process-args'; +import { + IFDiffArgs, + IEArgs, + IFEnvArgs, + IFCheckArgs, +} from '../types/process-args'; const {DISCLAIMER_MESSAGE} = STRINGS; @@ -120,6 +125,31 @@ export const CONFIG = { 'Faied to create the environment with the template manifest!', FAILURE_MESSAGE_DEPENDENCIES: 'Manifest dependencies are not available!', }, + IF_CHECK: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + directory: { + type: String, + optional: true, + alias: 'd', + description: '[path to the manifests directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Check Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + }, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], From 5dfde08d23a0fe7e4c8b6f1b2c975f1334e43c04 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:26:10 +0400 Subject: [PATCH 229/863] test(mocks): add mock functions for fs --- src/__mocks__/fs/index.ts | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 3853ad7ee..6d4f61b8b 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -135,3 +135,53 @@ export const stat = async (filePath: string) => { throw new Error('File not found.'); } }; + +export const access = async (directoryPath: string) => { + if (directoryPath === 'true') { + return true; + } else { + throw new Error('Directory not found.'); + } +}; + +export const unlink = async (filePath: string) => { + if (filePath === 'true') { + return; + } else { + throw new Error('File not found.'); + } +}; + +export const readdir = (directoryPath: string) => { + if (directoryPath.includes('mock-empty-directory')) { + return []; + } + + if (directoryPath.includes('mock-directory')) { + return ['file1.yaml', 'file2.yml', 'file3.txt']; + } + + if (directoryPath.includes('mock-sub-directory')) { + return ['subdir/file2.yml', 'file1.yaml']; + } + + return []; +}; + +export const lstat = (filePath: string) => { + if ( + filePath.includes('mock-directory') || + filePath.includes('mock-sub-directory/subdir') + ) { + return { + isDirectory: () => true, + }; + } + + if (filePath.includes('mock-file')) { + return { + isDirectory: () => false, + }; + } + return; +}; From e18cf4ec063f91b0f7c15d127c0518700168193e Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:28:45 +0400 Subject: [PATCH 230/863] feat(util): add helpers functions --- src/util/fs.ts | 34 ++++++++++++++++++++++++++++++++++ src/util/helpers.ts | 11 +++++++++++ src/util/npm.ts | 42 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/util/fs.ts b/src/util/fs.ts index 70cec75e4..7438ced61 100644 --- a/src/util/fs.ts +++ b/src/util/fs.ts @@ -1,4 +1,5 @@ import * as fs from 'fs/promises'; +import * as path from 'path'; /** * Checks if file exists with the given `filePath`. @@ -23,3 +24,36 @@ export const isDirectoryExists = async (directoryPath: string) => { return false; } }; + +/** + * Gets all files that have either .yml or .yaml extension in the given directory. + */ +export const getYamlFiles = async (directory: string) => { + let yamlFiles: string[] = []; + + const files = await fs.readdir(directory); + + for (const file of files) { + const fullPath = path.join(directory, file); + const stat = await fs.lstat(fullPath); + + if (stat.isDirectory()) { + yamlFiles = yamlFiles.concat(await getYamlFiles(fullPath)); + } else { + if (file.endsWith('.yml') || file.endsWith('.yaml')) { + yamlFiles.push(fullPath); + } + } + } + + return yamlFiles; +}; + +/** + * Gets fileName from the given path without an extension. + */ +export const getFileName = (filePath: string) => { + const baseName = path.basename(filePath); + const extension = path.extname(filePath); + return baseName.replace(extension, ''); +}; diff --git a/src/util/helpers.ts b/src/util/helpers.ts index e69b9e0e9..3273fa8bc 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -268,3 +268,14 @@ export const addTemplateManifest = async (destinationDir: string) => { process.exit(1); } }; + +/** + * Logs the failure message from the stdout of an error. + */ +export const logStdoutFailMessage = (error: any) => { + const stdout = error.stdout; + const logs = stdout.split('\n\n'); + const failMessage = logs[logs.length - 1]; + + console.log(failMessage); +}; diff --git a/src/util/npm.ts b/src/util/npm.ts index 61baf75b8..8c66d37b5 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -4,7 +4,7 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import {execPromise} from './helpers'; -import {isDirectoryExists, isFileExists} from './fs'; +import {isDirectoryExists, getFileName, isFileExists} from './fs'; import {logger} from './logger'; import {STRINGS} from '../config'; @@ -144,3 +144,43 @@ export const updatePackageJsonProperties = async ( JSON.stringify(newPackageJson, null, 2) ); }; + +/** + * Executes a series of npm commands based on the provided manifest file. + */ +export const executeCommands = async (manifest: string, cwd: boolean) => { + // TODO: After release remove isGlobal and appropriate checks + const isGlobal = !!process.env.npm_config_global; + const manifestDirPath = path.dirname(manifest); + const manifestFileName = getFileName(manifest); + const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); + const ifEnv = `${isGlobal ? 'if-env' : 'npm run if-env --'} -m ${manifest}`; + const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; + const ifRunCommand = `${ + isGlobal ? 'if-run' : 'npm run if-run --' + } -m ${manifest} -o ${executedManifest}`; + const ifDiffCommand = `${ + isGlobal ? 'if-diff' : 'npm run if-diff --' + } -s ${executedManifest}.yaml -t ${manifest}`; + const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; + + const result = await execPromise( + `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, + { + cwd: process.env.CURRENT_DIR || process.cwd(), + } + ); + + if (!cwd) { + await fs.unlink(`${manifestDirPath}/package.json`); + } + + await fs.unlink(`${executedManifest}.yaml`); + + if (result.stdout) { + const logs = result.stdout.split('\n\n'); + const successMessage = logs[logs.length - 1]; + + console.log(successMessage); + } +}; From 94c3a4413381b43cd74938a03141111742f31ddc Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:31:43 +0400 Subject: [PATCH 231/863] test(util): add tests for utils functions --- src/__tests__/unit/util/args.test.ts | 122 +++++++++++++++++++++++- src/__tests__/unit/util/fs.test.ts | 106 +++++++++++++++++++- src/__tests__/unit/util/helpers.test.ts | 14 ++- src/__tests__/unit/util/npm.test.ts | 29 +++++- 4 files changed, 265 insertions(+), 6 deletions(-) diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index 03752acc4..f4238cbce 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -7,6 +7,12 @@ jest.mock('../../../util/fs', () => ({ } return false; }, + isDirectoryExists: () => { + if (process.env.directoryExists === 'true') { + return true; + } + return false; + }, })); jest.mock('ts-command-line-args', () => ({ @@ -70,8 +76,6 @@ jest.mock('ts-command-line-args', () => ({ case 'diff-throw': throw 'mock-error'; /** If-env mocks */ - // case 'env-manifest-is-missing': - // return; case 'manifest-install-provided': return { install: true, @@ -85,6 +89,13 @@ jest.mock('ts-command-line-args', () => ({ throw new Error('mock-error'); case 'env-throw': throw 'mock-error'; + /** If-check */ + case 'manifest-is-provided': + return {manifest: 'mock-manifest.yaml'}; + case 'directory-is-provided': + return {directory: '/mock-directory'}; + case 'flags-are-not-provided': + return {manifest: undefined, directory: undefined}; default: return { manifest: 'mock-manifest.yaml', @@ -99,13 +110,19 @@ import {ERRORS} from '@grnsft/if-core/utils'; import { parseIEProcessArgs, + parseIfCheckArgs, parseIfDiffArgs, parseIfEnvArgs, } from '../../../util/args'; import {STRINGS} from '../../../config'; -const {CliSourceFileError, ParseCliParamsError} = ERRORS; +const { + CliSourceFileError, + ParseCliParamsError, + InvalidDirectoryError, + MissingCliFlagsError, +} = ERRORS; const { MANIFEST_IS_MISSING, @@ -113,6 +130,8 @@ const { INVALID_TARGET, SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND, + DIRECTORY_NOT_FOUND, + IF_CHECK_FLAGS_MISSING, } = STRINGS; describe('util/args: ', () => { @@ -402,5 +421,102 @@ describe('util/args: ', () => { }); }); + describe('parseIfCheckArgs(): ', () => { + it('executes when `manifest` is provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-provided'; + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({manifest: 'mock-manifest.yaml'}); + }); + + it('executes when the `directory` is provided.', async () => { + process.env.directoryExists = 'true'; + process.env.result = 'directory-is-provided'; + + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({directory: '/mock-directory'}); + }); + + it('throws an error when the `directory` does not exist.', async () => { + process.env.directoryExists = 'false'; + process.env.result = 'directory-is-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new InvalidDirectoryError(DIRECTORY_NOT_FOUND)); + } + }); + + it('throws an error when both `manifest` and `directory` flags are not provided.', async () => { + process.env.result = 'flags-are-not-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING)); + } + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + process.env = originalEnv; }); diff --git a/src/__tests__/unit/util/fs.test.ts b/src/__tests__/unit/util/fs.test.ts index 82f28bc75..15cb0103d 100644 --- a/src/__tests__/unit/util/fs.test.ts +++ b/src/__tests__/unit/util/fs.test.ts @@ -1,4 +1,11 @@ -import {isFileExists} from '../../../util/fs'; +import * as fs from 'fs/promises'; + +import { + getFileName, + isDirectoryExists, + isFileExists, + getYamlFiles, +} from '../../../util/fs'; jest.mock('fs/promises', () => require('../../../__mocks__/fs')); @@ -18,4 +25,101 @@ describe('util/fs: ', () => { expect(result).toEqual(false); }); }); + + describe('isDirectoryExists(): ', () => { + it('returns true if directory exists.', async () => { + const result = await isDirectoryExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns false if directory does not exist.', async () => { + const result = await isDirectoryExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('getFileName(): ', () => { + it('returns the file name without extension for a file with an extension.', () => { + const filePath = '/path/to/file/example.yaml'; + const result = getFileName(filePath); + + expect.assertions(1); + expect(result).toBe('example'); + }); + + it('returns the file name without extension for a file with multiple dots.', () => { + const filePath = '/path/to/file/example.test.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example.test'); + }); + + it('returns the file name as is if there is no extension.', () => { + const filePath = '/path/to/file/example'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles file names with special characters.', () => { + const filePath = + '/path/to/file/complex-file.name.with-multiple.parts.yaml'; + const result = getFileName(filePath); + expect(result).toBe('complex-file.name.with-multiple.parts'); + }); + + it('handles file names with no path.', () => { + const filePath = 'example.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles empty string as file path.', () => { + const filePath = ''; + const result = getFileName(filePath); + expect(result).toBe(''); + }); + }); + + describe('getYamlFiles(): ', () => { + it('returns an empty array if the directory is empty.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + const result = await getYamlFiles('/mock-empty-directory'); + + expect(result).toEqual([]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-empty-directory'); + }); + + it('returns YAML files in the directory', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + + const result = await getYamlFiles('/mock-directory'); + expect.assertions(2); + expect(result).toEqual([ + '/mock-directory/file1.yaml', + '/mock-directory/file2.yml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + + it('recursively finds YAML files in nested directories.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + const result = await getYamlFiles('/mock-sub-directory'); + + expect.assertions(2); + expect(result).toEqual([ + '/mock-sub-directory/subdir/file2.yml', + '/mock-sub-directory/file1.yaml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + }); }); diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index d04ad43d2..42ff9450b 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -146,7 +146,7 @@ import { getOptionsFromArgs, addTemplateManifest, initializeAndInstallLibs, - // initializeAndInstallLibs, + logStdoutFailMessage, } from '../../../util/helpers'; import {CONFIG} from '../../../config'; import {Difference} from '../../../types/lib/compare'; @@ -667,4 +667,16 @@ description: mock-description process.exit = originalProcessExit; }); }); + + describe('logStdoutFailMessage(): ', () => { + it('successfully logs the failed message.', () => { + const errorMessage = {stdout: '\n\nmock error message'}; + const logSpy = jest.spyOn(global.console, 'log'); + logStdoutFailMessage(errorMessage); + + expect.assertions(1); + + expect(logSpy).toHaveBeenCalledWith('mock error message'); + }); + }); }); diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 403a1138c..0cf801583 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -21,6 +21,7 @@ import { updatePackageJsonDependencies, extractPathsWithVersion, updatePackageJsonProperties, + executeCommands, } from '../../../util/npm'; import {isFileExists} from '../../../util/fs'; @@ -176,7 +177,7 @@ describe('util/npm: ', () => { '@commitlint/cli@18.6.0', '@commitlint/config-conventional@18.6.0', '@grnsft/if-core@0.0.7', - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models', + '@grnsft/if-plugins@v0.3.2', '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', '@jest/globals@29.7.0', ]; @@ -246,4 +247,30 @@ describe('util/npm: ', () => { expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); }); }); + + describe('executeCommands(): ', () => { + it('successfully executes with correct commands.', async () => { + const manifest = './src/__mocks__/mock-manifest.yaml'; + const reManifest = 'src/__mocks__/re-mock-manifest.yaml'; + const command = `npm run if-env -- -m ${manifest} && npm run if-run -- -m ${manifest} -o ${reManifest.replace( + '.yaml', + '' + )} && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s ${reManifest} -t ${manifest}`; + const logSpy = jest.spyOn(global.console, 'log'); + const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + jest.spyOn(fs, 'unlink').mockResolvedValue(); + + await executeCommands(manifest, false); + + expect.assertions(2); + expect(spyExecPromise).toHaveBeenCalledWith(command, { + cwd: process.cwd(), + }); + expect(logSpy).toHaveBeenCalledWith('Files match!\n'); + + const packageJsonPath = 'src/__mocks__/package.json'; + fsSync.unlink(path.resolve(process.cwd(), reManifest), () => {}); + fsSync.unlink(path.resolve(process.cwd(), packageJsonPath), () => {}); + }, 70000); + }); }); From f6296f41dd277824760d6cdd35b07f9ed8e7ae20 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:33:33 +0400 Subject: [PATCH 232/863] chore(config): add string --- src/config/strings.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index 4da6defae..3a2fc84fe 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -132,4 +132,8 @@ ${error}`, `Exporting to csv file: ${savepath}`, EXPORTING_RAW_CSV_FILE: (savepath: string) => `Exporting raw csv file: ${savepath}`, + CHECKING: 'Checking...', + IF_CHECK_FLAGS_MISSING: + 'Either the `--manifest` or `--directory` command should be provided with a path', + DIRECTORY_NOT_FOUND: 'Directory not found.', }; From 24148df470471848188da93b1243a7bc79d82cdb Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 12:35:46 +0400 Subject: [PATCH 233/863] feat(mocks): add mock manifest file --- src/__mocks__/mock-manifest.yaml | 72 ++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/__mocks__/mock-manifest.yaml diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml new file mode 100644 index 000000000..1e38c1b13 --- /dev/null +++ b/src/__mocks__/mock-manifest.yaml @@ -0,0 +1,72 @@ +name: template manifest +description: auto-generated template +tags: null +initialize: + plugins: + memory-energy-from-memory-util: + path: builtin + method: Coefficient + global-config: + input-parameter: memory/utilization + coefficient: 0.0001 + output-parameter: memory/energy + outputs: + - yaml +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/index.ts -m + ./src/env-template.yml -o ./manifests/outputs/template + environment: + if-version: 0.4.0 + os: macOS + os-version: 13.6.6 + node-version: 20.12.2 + date-time: 2024-06-18T08:39:55.771Z (UTC) + dependencies: + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.3" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - memory-energy-from-memory-util + config: null + inputs: + - timestamp: 2023-12-12T00:00:00.000Z + duration: 3600 + memory/utilization: 10 + outputs: + - timestamp: 2023-12-12T00:00:00.000Z + duration: 3600 + memory/utilization: 10 + memory/energy: 0.001 From 5e9ae199a6299b116419ce14cb9e3b0edd32172f Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 13:00:55 +0400 Subject: [PATCH 234/863] feat(util): add if-check argument parsing functions --- src/util/args.ts | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/util/args.ts b/src/util/args.ts index 5d9524390..31da90461 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -5,7 +5,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {checkIfFileIsYaml} from './yaml'; -import {isFileExists} from './fs'; +import {isDirectoryExists, isFileExists} from './fs'; import {logger} from './logger'; @@ -16,12 +16,19 @@ import { IEArgs, ProcessArgsOutputs, IFEnvArgs, + IFCheckArgs, } from '../types/process-args'; import {LoadDiffParams} from '../types/util/args'; -const {ParseCliParamsError, CliTargetFileError, CliSourceFileError} = ERRORS; +const { + ParseCliParamsError, + CliTargetFileError, + CliSourceFileError, + InvalidDirectoryError, + MissingCliFlagsError, +} = ERRORS; -const {IE, IF_DIFF, IF_ENV} = CONFIG; +const {IE, IF_DIFF, IF_ENV, IF_CHECK} = CONFIG; const { MANIFEST_IS_MISSING, @@ -30,6 +37,8 @@ const { SOURCE_IS_NOT_YAML, TARGET_IS_NOT_YAML, INVALID_TARGET, + IF_CHECK_FLAGS_MISSING, + DIRECTORY_NOT_FOUND, } = STRINGS; /** @@ -186,3 +195,54 @@ export const parseIfEnvArgs = async () => { return {install, cwd}; }; + +/** -- IF Check -- */ + +/** + * Parses `if-check` process arguments. + */ +const validateAndParseIfCheckArgs = () => { + try { + return parse(IF_CHECK.ARGS, IF_CHECK.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if either `manifest` or `directory` command is provided. + */ +export const parseIfCheckArgs = async () => { + const {manifest, directory} = validateAndParseIfCheckArgs(); + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } else if (directory) { + const isDirExists = await isDirectoryExists(directory); + + if (!isDirExists) { + throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); + } + + const response = prependFullFilePath(directory); + + return {directory: response}; + } + + throw new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING); +}; From 5948600ebee8441d8c3fcfd54fcf2a26ba5970d8 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 13:03:09 +0400 Subject: [PATCH 235/863] feat(src): add if-check logic --- src/check.ts | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/check.ts diff --git a/src/check.ts b/src/check.ts new file mode 100644 index 000000000..56e659efb --- /dev/null +++ b/src/check.ts @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {logger} from './util/logger'; +import {parseIfCheckArgs} from './util/args'; +import {logStdoutFailMessage} from './util/helpers'; +import {getYamlFiles} from './util/fs'; + +import {STRINGS} from './config'; +import {executeCommands} from './util/npm'; + +const {CHECKING} = STRINGS; + +const IfCheck = async () => { + const commandArgs = await parseIfCheckArgs(); + + console.log(`${CHECKING}\n`); + + if (commandArgs.manifest) { + const manifest = commandArgs.manifest; + + try { + await executeCommands(manifest, false); + } catch (error: any) { + const fileName = path.basename(manifest); + const executedFile = manifest.replace(fileName, `re-${fileName}`); + const manifestDirPath = path.dirname(manifest); + + logStdoutFailMessage(error); + + await fs.unlink(`${manifestDirPath}/package.json`); + await fs.unlink(executedFile); + } + } else { + const directory = commandArgs.directory; + const files = await getYamlFiles(directory!); + + for await (const file of files) { + const fileName = path.basename(file); + console.log(fileName); + + try { + await executeCommands(file, true); + } catch (error: any) { + const fileName = path.basename(file); + const executedFile = file.replace(fileName, `re-${fileName}`); + + logStdoutFailMessage(error); + await fs.unlink(executedFile); + } + } + } +}; + +IfCheck().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 850ea050c2b61d2098815aed1455251184832e8b Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 13:06:32 +0400 Subject: [PATCH 236/863] feat(package): add if-check script and update if-core version --- package-lock.json | 9 +++++---- package.json | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e66c802a..9d64c6b7b 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.9", + "@grnsft/if-core": "^0.0.10", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -24,6 +24,7 @@ "zod": "^3.22.4" }, "bin": { + "if-check": "build/check.js", "if-diff": "build/diff.js", "if-env": "build/env.js", "if-run": "build/index.js" @@ -1183,9 +1184,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.9.tgz", - "integrity": "sha512-F0niYe1j+NfhH+okz5sjP/CD7w/9BeXXe13bHkCsdOnk0WfXrq0DGKwpqh9TiLbKc9f1P3/XuojeFANMQu5nig==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.10.tgz", + "integrity": "sha512-WHCdr7H/dFO9gT5fbjrthjOU+4RoLZ5P1F84pbGwJiKLmcU7dvYRuNQKDVIQQ7YJfZl76KSaS7sYgqA+QG8Wpw==", "dependencies": { "typescript": "^5.1.6" }, diff --git a/package.json b/package.json index e9f2f2777..0d965de37 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "bin": { "if-diff": "./build/diff.js", "if-run": "./build/index.js", - "if-env": "./build/env.js" + "if-env": "./build/env.js", + "if-check": "./build/check.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -17,7 +18,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.9", + "@grnsft/if-core": "^0.0.10", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -75,6 +76,7 @@ "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/unit", "fix": "gts fix", "fix:package": "fixpack", + "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/check.ts", "if-diff": "npx ts-node src/diff.ts", "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", "if-run": "npx ts-node src/index.ts", From d51b9a077e70bce59dfe55e02021677bbd11c250 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 16:26:27 +0400 Subject: [PATCH 237/863] fix(src): fix issue realted to remove created temp re-manifest file during if-check execution --- src/check.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/check.ts b/src/check.ts index 56e659efb..887ff13f6 100644 --- a/src/check.ts +++ b/src/check.ts @@ -25,7 +25,9 @@ const IfCheck = async () => { await executeCommands(manifest, false); } catch (error: any) { const fileName = path.basename(manifest); - const executedFile = manifest.replace(fileName, `re-${fileName}`); + const executedFile = manifest + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); const manifestDirPath = path.dirname(manifest); logStdoutFailMessage(error); @@ -45,7 +47,9 @@ const IfCheck = async () => { await executeCommands(file, true); } catch (error: any) { const fileName = path.basename(file); - const executedFile = file.replace(fileName, `re-${fileName}`); + const executedFile = file + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); logStdoutFailMessage(error); await fs.unlink(executedFile); From f2a371ac44d70abaa4c792925bf915245c8fab06 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 18:43:51 +0400 Subject: [PATCH 238/863] feat(config): add messages for if-check fail and verify --- src/config/strings.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index 3a2fc84fe..e55eb1b9c 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -136,4 +136,8 @@ ${error}`, IF_CHECK_FLAGS_MISSING: 'Either the `--manifest` or `--directory` command should be provided with a path', DIRECTORY_NOT_FOUND: 'Directory not found.', + IF_CHECK_FAILED: (filename: string) => + `if-check could not verify <${filename}>. The re-executed file does not match the original.\n`, + IF_CHECK_VERIFIED: (filename: string) => + `if-check successfully verified <${filename}>\n`, }; From 9f1c32ecdb432ec6e3aa00659daa0f1836a57ae9 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 18:45:45 +0400 Subject: [PATCH 239/863] feat(util): remove logStdoutFailMessage function --- src/__tests__/unit/util/helpers.test.ts | 13 ------------- src/util/helpers.ts | 11 ----------- 2 files changed, 24 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 42ff9450b..4e0422403 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -146,7 +146,6 @@ import { getOptionsFromArgs, addTemplateManifest, initializeAndInstallLibs, - logStdoutFailMessage, } from '../../../util/helpers'; import {CONFIG} from '../../../config'; import {Difference} from '../../../types/lib/compare'; @@ -667,16 +666,4 @@ description: mock-description process.exit = originalProcessExit; }); }); - - describe('logStdoutFailMessage(): ', () => { - it('successfully logs the failed message.', () => { - const errorMessage = {stdout: '\n\nmock error message'}; - const logSpy = jest.spyOn(global.console, 'log'); - logStdoutFailMessage(errorMessage); - - expect.assertions(1); - - expect(logSpy).toHaveBeenCalledWith('mock error message'); - }); - }); }); diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 3273fa8bc..e69b9e0e9 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -268,14 +268,3 @@ export const addTemplateManifest = async (destinationDir: string) => { process.exit(1); } }; - -/** - * Logs the failure message from the stdout of an error. - */ -export const logStdoutFailMessage = (error: any) => { - const stdout = error.stdout; - const logs = stdout.split('\n\n'); - const failMessage = logs[logs.length - 1]; - - console.log(failMessage); -}; From 03ce50b7fec0f9529a0dbae592828c43f7493518 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 18:48:32 +0400 Subject: [PATCH 240/863] test(util): update log message --- src/__tests__/unit/util/npm.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 0cf801583..d73095d93 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -266,7 +266,9 @@ describe('util/npm: ', () => { expect(spyExecPromise).toHaveBeenCalledWith(command, { cwd: process.cwd(), }); - expect(logSpy).toHaveBeenCalledWith('Files match!\n'); + expect(logSpy).toHaveBeenCalledWith( + 'if-check successfully verified \n' + ); const packageJsonPath = 'src/__mocks__/package.json'; fsSync.unlink(path.resolve(process.cwd(), reManifest), () => {}); From f894878f23c787c60d9eac581d343e7f461299fa Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 18:50:41 +0400 Subject: [PATCH 241/863] feat(util): update if-check verify log --- src/util/npm.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/util/npm.ts b/src/util/npm.ts index 8c66d37b5..16c2cb4d2 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -12,7 +12,8 @@ import {ManifestPlugin, PathWithVersion} from '../types/npm'; const packageJson = require('../../package.json'); -const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES, IF_CHECK_VERIFIED} = + STRINGS; /** * Checks if the package.json is exists, if not, initializes it. @@ -164,7 +165,7 @@ export const executeCommands = async (manifest: string, cwd: boolean) => { } -s ${executedManifest}.yaml -t ${manifest}`; const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; - const result = await execPromise( + await execPromise( `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, { cwd: process.env.CURRENT_DIR || process.cwd(), @@ -177,10 +178,5 @@ export const executeCommands = async (manifest: string, cwd: boolean) => { await fs.unlink(`${executedManifest}.yaml`); - if (result.stdout) { - const logs = result.stdout.split('\n\n'); - const successMessage = logs[logs.length - 1]; - - console.log(successMessage); - } + console.log(IF_CHECK_VERIFIED(path.basename(manifest))); }; From eca2d2ff41d7cd28b6e76325158381e49d89d9f4 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 18:52:28 +0400 Subject: [PATCH 242/863] feat(src): update fail log --- src/check.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/check.ts b/src/check.ts index 887ff13f6..530072b04 100644 --- a/src/check.ts +++ b/src/check.ts @@ -5,13 +5,12 @@ import * as path from 'path'; import {logger} from './util/logger'; import {parseIfCheckArgs} from './util/args'; -import {logStdoutFailMessage} from './util/helpers'; import {getYamlFiles} from './util/fs'; import {STRINGS} from './config'; import {executeCommands} from './util/npm'; -const {CHECKING} = STRINGS; +const {CHECKING, IF_CHECK_FAILED} = STRINGS; const IfCheck = async () => { const commandArgs = await parseIfCheckArgs(); @@ -30,7 +29,7 @@ const IfCheck = async () => { .replace('yml', 'yaml'); const manifestDirPath = path.dirname(manifest); - logStdoutFailMessage(error); + console.log(IF_CHECK_FAILED(fileName)); await fs.unlink(`${manifestDirPath}/package.json`); await fs.unlink(executedFile); @@ -51,7 +50,7 @@ const IfCheck = async () => { .replace(fileName, `re-${fileName}`) .replace('yml', 'yaml'); - logStdoutFailMessage(error); + console.log(IF_CHECK_FAILED(fileName)); await fs.unlink(executedFile); } } From 68cbf5b8c1529db489a8e66309557e259f3d8ded Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 19:51:10 +0400 Subject: [PATCH 243/863] fix(config): update srtings of if-check logs --- src/__tests__/unit/util/npm.test.ts | 2 +- src/config/strings.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index d73095d93..3fd4fac18 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -267,7 +267,7 @@ describe('util/npm: ', () => { cwd: process.cwd(), }); expect(logSpy).toHaveBeenCalledWith( - 'if-check successfully verified \n' + 'if-check successfully verified mock-manifest.yaml\n' ); const packageJsonPath = 'src/__mocks__/package.json'; diff --git a/src/config/strings.ts b/src/config/strings.ts index e55eb1b9c..b1d58a7b4 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -137,7 +137,7 @@ ${error}`, 'Either the `--manifest` or `--directory` command should be provided with a path', DIRECTORY_NOT_FOUND: 'Directory not found.', IF_CHECK_FAILED: (filename: string) => - `if-check could not verify <${filename}>. The re-executed file does not match the original.\n`, + `if-check could not verify ${filename}. The re-executed file does not match the original.\n`, IF_CHECK_VERIFIED: (filename: string) => - `if-check successfully verified <${filename}>\n`, + `if-check successfully verified ${filename}\n`, }; From 2c0e2fcb45d198f693824ebc2f85836e2f039ed8 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 20:14:03 +0400 Subject: [PATCH 244/863] fix(util): bring back logStdoutFailMessage function --- src/__tests__/unit/util/helpers.test.ts | 18 ++++++++++++++++++ src/util/helpers.ts | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 4e0422403..7b6bc2eec 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -146,6 +146,7 @@ import { getOptionsFromArgs, addTemplateManifest, initializeAndInstallLibs, + logStdoutFailMessage, } from '../../../util/helpers'; import {CONFIG} from '../../../config'; import {Difference} from '../../../types/lib/compare'; @@ -666,4 +667,21 @@ description: mock-description process.exit = originalProcessExit; }); }); + + describe('logStdoutFailMessage(): ', () => { + it('successfully logs the failed message.', () => { + const errorMessage = {stdout: '\n\nmock error message'}; + const mockFilename = 'mock-filename.yaml'; + const logSpy = jest.spyOn(global.console, 'log'); + logStdoutFailMessage(errorMessage, mockFilename); + + expect.assertions(2); + + expect(logSpy).toHaveBeenCalledWith( + `if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` + ); + + expect(logSpy).toHaveBeenCalledWith('mock error message'); + }); + }); }); diff --git a/src/util/helpers.ts b/src/util/helpers.ts index e69b9e0e9..0fcdda963 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -33,7 +33,7 @@ const { FAILURE_MESSAGE_DEPENDENCIES, } = IF_ENV; -const {UNSUPPORTED_ERROR} = STRINGS; +const {UNSUPPORTED_ERROR, IF_CHECK_FAILED} = STRINGS; const {MissingPluginDependenciesError} = ERRORS; /** @@ -268,3 +268,16 @@ export const addTemplateManifest = async (destinationDir: string) => { process.exit(1); } }; + +/** + * Logs the failure message from the stdout of an error. + */ +export const logStdoutFailMessage = (error: any, fileName: string) => { + console.log(IF_CHECK_FAILED(fileName)); + + const stdout = error.stdout; + const logs = stdout.split('\n\n'); + const failMessage = logs[logs.length - 1]; + + console.log(failMessage); +}; From 0cc011bc9c7cc0425f57793135b29854446d4a2b Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 27 Jun 2024 20:15:12 +0400 Subject: [PATCH 245/863] fix(src): move fail logs into logStdoutFailMessage function --- src/check.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/check.ts b/src/check.ts index 530072b04..a7e561b04 100644 --- a/src/check.ts +++ b/src/check.ts @@ -4,13 +4,14 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import {logger} from './util/logger'; +import {logStdoutFailMessage} from './util/helpers'; import {parseIfCheckArgs} from './util/args'; import {getYamlFiles} from './util/fs'; import {STRINGS} from './config'; import {executeCommands} from './util/npm'; -const {CHECKING, IF_CHECK_FAILED} = STRINGS; +const {CHECKING} = STRINGS; const IfCheck = async () => { const commandArgs = await parseIfCheckArgs(); @@ -29,7 +30,7 @@ const IfCheck = async () => { .replace('yml', 'yaml'); const manifestDirPath = path.dirname(manifest); - console.log(IF_CHECK_FAILED(fileName)); + logStdoutFailMessage(error, fileName); await fs.unlink(`${manifestDirPath}/package.json`); await fs.unlink(executedFile); @@ -50,7 +51,8 @@ const IfCheck = async () => { .replace(fileName, `re-${fileName}`) .replace('yml', 'yaml'); - console.log(IF_CHECK_FAILED(fileName)); + logStdoutFailMessage(error, fileName); + await fs.unlink(executedFile); } } From ae7e4c89958052f1b33921f20dcceda49b621052 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 22:48:25 +0400 Subject: [PATCH 246/863] fix(manifests): uncomment sci from aggregation error wrong metric --- manifests/bugs/aggregation-error-wrong-metric.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml index 60a8dd8dd..2c3141c13 100644 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ b/manifests/bugs/aggregation-error-wrong-metric.yml @@ -57,7 +57,7 @@ initialize: path: builtin global-config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon-operational" + output-parameter: "carbon" "sci": path: "builtin" method: Sci @@ -87,7 +87,7 @@ tree: - sci-embodied - operational-carbon - time-sync - # - sci + - sci config: group-by: group: @@ -107,21 +107,25 @@ tree: cloud/region: uk-west duration: 1 cpu/utilization: 10 + requests: 100 - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 + requests: 100 child-2: pipeline: - interpolate @@ -133,7 +137,7 @@ tree: - sci-embodied - operational-carbon - time-sync - # - sci + - sci config: group-by: group: @@ -153,18 +157,22 @@ tree: cpu/utilization: 30 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 28 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 40 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west + requests: 100 From 084da9dd1753690c30e1b50288194a44a11812de Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 22:53:22 +0400 Subject: [PATCH 247/863] fix(manifests): uncomment sci from nesting example --- manifests/examples/nesting.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/manifests/examples/nesting.yml b/manifests/examples/nesting.yml index b274ae7f0..978510f48 100644 --- a/manifests/examples/nesting.yml +++ b/manifests/examples/nesting.yml @@ -106,7 +106,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -156,7 +156,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -208,7 +208,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -258,7 +258,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 From 5e1b13ff032007234c9eec9896fd11e7e5bd5310 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 22:57:04 +0400 Subject: [PATCH 248/863] fix(manifests): uncomment sci from pipeline with aggregate, fix second child --- .../examples/pipeline-with-aggregate.yml | 105 +++++++++--------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/manifests/examples/pipeline-with-aggregate.yml b/manifests/examples/pipeline-with-aggregate.yml index 65d6c9d26..73203676b 100644 --- a/manifests/examples/pipeline-with-aggregate.yml +++ b/manifests/examples/pipeline-with-aggregate.yml @@ -93,7 +93,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci config: group-by: group: @@ -132,55 +132,54 @@ tree: cloud/region: uk-west cpu/utilization: 15 requests: 30 - # child-2: - # pipeline: - # - interpolate - # - cpu-factor-to-wattage - # - wattage-times-duration - # - wattage-to-energy-kwh - # - calculate-vcpu-ratio - # - correct-cpu-energy-for-vcpu-ratio - # - sci-e - # - sci-embodied - # - sci-o - # - sum-carbon - # - time-sync - # - sci - # config: - # group-by: - # group: - # - cloud/region - # - cloud/instance-type - # defaults: - # cpu/thermal-design-power: 100 - # grid/carbon-intensity: 800 - # device/emissions-embodied: 1533.120 # gCO2eq - # time-reserved: 3600 # 1hr in seconds - # device/expected-lifespan: 94608000 # 3 years in seconds - # resources-reserved: 1 - # resources-total: 8 - # inputs: - # - timestamp: "2023-12-12T00:00:00.000Z" - # duration: 1 - # cpu/utilization: 30 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 100 - # - timestamp: "2023-12-12T00:00:01.000Z" - # duration: 5 - # cpu/utilization: 28 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 150 - # - timestamp: "2023-12-12T00:00:06.000Z" - # duration: 7 - # cpu/utilization: 40 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 110 - # - timestamp: "2023-12-12T00:00:13.000Z" - # duration: 30 - # cpu/utilization: 33 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 180 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.120 # gCO2eq + time-reserved: 3600 # 1hr in seconds + device/expected-lifespan: 94608000 # 3 years in seconds + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: "2023-12-12T00:00:01.000Z" + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 150 + - timestamp: "2023-12-12T00:00:06.000Z" + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 110 + - timestamp: "2023-12-12T00:00:13.000Z" + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 180 From a4e2757890bb8295975db72ccabc09ba51387700 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 22:58:23 +0400 Subject: [PATCH 249/863] fix(manifests): uncomment sci from pipeline with mocks, fix second child --- manifests/examples/pipeline-with-mocks.yml | 100 +++++++++++---------- 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/manifests/examples/pipeline-with-mocks.yml b/manifests/examples/pipeline-with-mocks.yml index 801b7bfd9..168ebd7fe 100644 --- a/manifests/examples/pipeline-with-mocks.yml +++ b/manifests/examples/pipeline-with-mocks.yml @@ -115,7 +115,7 @@ tree: - operational-carbon - sum-carbon - time-sync - # - sci + - sci config: group-by: group: @@ -154,50 +154,54 @@ tree: cloud/region: uk-west cpu/utilization: 15 requests: 50 - # child-2: - # pipeline: - # - teads-curve - # - sci-e - # - sci-embodied - # - sci-o - # - sum-carbon - # - time-sync - # - sci - # config: - # group-by: - # group: - # - cloud/region - # - cloud/instance-type - # defaults: - # cpu/thermal-design-power: 100 - # grid/carbon-intensity: 800 - # device/emissions-embodied: 1533.120 # gCO2eq - # time-reserved: 3600 # 1hr in seconds - # device/expected-lifespan: 94608000 # 3 years in seconds - # resources-reserved: 1 - # resources-total: 8 - # inputs: - # - timestamp: "2023-12-12T00:00:00.000Z" - # duration: 1 - # cpu/utilization: 30 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 30 - # - timestamp: "2023-12-12T00:00:01.000Z" - # duration: 5 - # cpu/utilization: 28 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 40 - # - timestamp: "2023-12-12T00:00:06.000Z" - # duration: 7 - # cpu/utilization: 40 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 50 - # - timestamp: "2023-12-12T00:00:13.000Z" - # duration: 30 - # cpu/utilization: 33 - # cloud/instance-type: A1 - # cloud/region: uk-west - # requests: 60 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.120 # gCO2eq + time-reserved: 3600 # 1hr in seconds + device/expected-lifespan: 94608000 # 3 years in seconds + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + - timestamp: "2023-12-12T00:00:01.000Z" + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 40 + - timestamp: "2023-12-12T00:00:06.000Z" + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 50 + - timestamp: "2023-12-12T00:00:13.000Z" + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 60 From 5313ff19495a85beabd983b8bbacb4ffa8546163 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 23:19:07 +0400 Subject: [PATCH 250/863] feat(manifests): init zeros example --- manifests/examples/zeros.yaml | 130 ++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 manifests/examples/zeros.yaml diff --git a/manifests/examples/zeros.yaml b/manifests/examples/zeros.yaml new file mode 100644 index 000000000..da5541789 --- /dev/null +++ b/manifests/examples/zeros.yaml @@ -0,0 +1,130 @@ +name: generics +description: a pipeline that does arbitrary calculations using our generic arithmetic builtins +tags: +initialize: + plugins: + "sum-zero-and-one": + path: "builtin" + method: Sum + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-plus-zero + "sum-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-plus-zero + "subtract-one-and-zero": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-minus-zero + "subtract-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-minus-zero + "subtract-zero-and-one": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - zero-value + - some-value + output-parameter: zero-minus-one + "coefficient-one-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 1 + output-parameter: zero-times-one-coefficient + "coefficient-zero-times-one": + path: "builtin" + method: Coefficient + global-config: + input-parameter: some-value + coefficient: 0 + output-parameter: one-times-zero-coefficient + "coefficient-zero-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 0 + output-parameter: zero-times-zero-coefficient + "multiply-one-times-zero": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["some-value", "zero-value"] + output-parameter: "one-times-zero" + "multiply-zero-times-one": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["zero-value", "zero-value"] + output-parameter: "zero-times-one" + exponent-one-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'some-value' + exponent: 0 + output-parameter: 'one-raised-to-zero-power' + exponent-zero-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 0 + output-parameter: 'zero-raised-to-zero-power' + exponent-zero-to-one: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 1 + output-parameter: 'zero-raised-to-first-power' + "sci": + path: "builtin" + method: Sci + global-config: + functional-unit: "zero-value" +tree: + children: + child-1: + pipeline: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci + config: + defaults: + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + duration: 1 + some-value: 1 + zero-value: 0 + carbon: 10 From 629c488d05caaf67e272be34b762c36de303b8c1 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 23:36:47 +0400 Subject: [PATCH 251/863] fix(manifests): drop boavizta from pipeline --- ...adata-divide-boavizta.yml => cloud-metadata-divide.yml} | 7 ------- 1 file changed, 7 deletions(-) rename manifests/integrations/{cloud-metadata-divide-boavizta.yml => cloud-metadata-divide.yml} (83%) diff --git a/manifests/integrations/cloud-metadata-divide-boavizta.yml b/manifests/integrations/cloud-metadata-divide.yml similarity index 83% rename from manifests/integrations/cloud-metadata-divide-boavizta.yml rename to manifests/integrations/cloud-metadata-divide.yml index efb48f0ab..032206474 100644 --- a/manifests/integrations/cloud-metadata-divide-boavizta.yml +++ b/manifests/integrations/cloud-metadata-divide.yml @@ -19,19 +19,12 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: From a33ff08741b21fc9bdb28d01e9748fb678942971 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 27 Jun 2024 23:37:13 +0400 Subject: [PATCH 252/863] fix(manifests): drop boavizta from divide --- .../plugins/divide/failure-denominator-equal-zero.yml | 7 ------- .../divide/failure-invalid-config-denominator.yml | 7 ------- manifests/plugins/divide/failure-missing-numerator.yml | 7 ------- manifests/plugins/divide/success.yml | 9 +-------- 4 files changed, 1 insertion(+), 29 deletions(-) diff --git a/manifests/plugins/divide/failure-denominator-equal-zero.yml b/manifests/plugins/divide/failure-denominator-equal-zero.yml index 8c48e42b9..4022d4797 100644 --- a/manifests/plugins/divide/failure-denominator-equal-zero.yml +++ b/manifests/plugins/divide/failure-denominator-equal-zero.yml @@ -20,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-invalid-config-denominator.yml b/manifests/plugins/divide/failure-invalid-config-denominator.yml index bc93f4f5f..91129714a 100644 --- a/manifests/plugins/divide/failure-invalid-config-denominator.yml +++ b/manifests/plugins/divide/failure-invalid-config-denominator.yml @@ -20,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 'vcpus' output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-missing-numerator.yml b/manifests/plugins/divide/failure-missing-numerator.yml index ebf250961..7cf123976 100644 --- a/manifests/plugins/divide/failure-missing-numerator.yml +++ b/manifests/plugins/divide/failure-missing-numerator.yml @@ -20,19 +20,12 @@ initialize: #numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/success.yml b/manifests/plugins/divide/success.yml index 4d35e5fc1..6a32d7e2c 100644 --- a/manifests/plugins/divide/success.yml +++ b/manifests/plugins/divide/success.yml @@ -2,7 +2,7 @@ name: divide description: success path tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -20,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: From d1bc0377607ade0eb48575fffed2215fc957de9f Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 28 Jun 2024 00:19:56 +0400 Subject: [PATCH 253/863] fix(doc): update divide readme --- src/builtins/divide/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index 35f7d867c..9a4d04f36 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -4,8 +4,6 @@ You provide the names of the values you want to divide, and a name to use to add the divide to the output array. -For example, `boavizta-cpu` need `cpu/number-cores` to work, however `cloud-metadata` returns `vcpus-allocated`, to get number of cores you divide `vcpus-allocated` by 2. - ## Parameters ### Plugin config From 4eed69cd14e493a147a4195a0023f46f2dba44a9 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 28 Jun 2024 00:20:09 +0400 Subject: [PATCH 254/863] fix(doc): update regex readme --- src/builtins/regex/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index f079b0461..a0fa5d624 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -4,8 +4,6 @@ You provide the name of the value you want to match, and a name to use to add the regex to the output array. -For example, `boavizta-cpu` need `cpu/name` to work, however `cloud-metadata` returns `physical-processor` which usually contains a long string of processors that the instance could be separated by `,`, like so: - ``` 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 ``` From f8ca3b4219df585814fbe3e39c67a696c9c451b3 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 28 Jun 2024 12:47:48 +0400 Subject: [PATCH 255/863] feat(config): add string for if-check --- src/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index b6aaf1de5..6a8a586f3 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -138,6 +138,8 @@ ${error}`, IF_CHECK_FLAGS_MISSING: 'Either the `--manifest` or `--directory` command should be provided with a path', DIRECTORY_NOT_FOUND: 'Directory not found.', + DIRECTORY_YAML_FILES_NOT_FOUND: + 'The directory does not contain any YAML/YML files.\n', IF_CHECK_FAILED: (filename: string) => `if-check could not verify ${filename}. The re-executed file does not match the original.\n`, IF_CHECK_VERIFIED: (filename: string) => From 9606c446a50bc8c181c4a4de8da82a7a3578080d Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 28 Jun 2024 14:46:07 +0400 Subject: [PATCH 256/863] feat(util): add removeFileIfExists function to fs.ts --- src/__tests__/unit/util/fs.test.ts | 19 +++++++++++++++++++ src/util/fs.ts | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/src/__tests__/unit/util/fs.test.ts b/src/__tests__/unit/util/fs.test.ts index 15cb0103d..77b3c0370 100644 --- a/src/__tests__/unit/util/fs.test.ts +++ b/src/__tests__/unit/util/fs.test.ts @@ -5,6 +5,7 @@ import { isDirectoryExists, isFileExists, getYamlFiles, + removeFileIfExists, } from '../../../util/fs'; jest.mock('fs/promises', () => require('../../../__mocks__/fs')); @@ -122,4 +123,22 @@ describe('util/fs: ', () => { expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); }); }); + + describe('removeFileIfExists(): ', () => { + it('successfully delete file if exists.', async () => { + await isFileExists('true'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + + it('does not throw an error if the file not exists.', async () => { + await isFileExists('false'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + }); }); diff --git a/src/util/fs.ts b/src/util/fs.ts index 7438ced61..bf10af9ba 100644 --- a/src/util/fs.ts +++ b/src/util/fs.ts @@ -57,3 +57,12 @@ export const getFileName = (filePath: string) => { const extension = path.extname(filePath); return baseName.replace(extension, ''); }; + +/** + * Removes the given file if exists. + */ +export const removeFileIfExists = async (filePath: string) => { + if (await isFileExists(filePath)) { + await fs.unlink(filePath); + } +}; From c8d8879823a8ac76b319d4bdabb1dad23c7b99a7 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 28 Jun 2024 15:09:27 +0400 Subject: [PATCH 257/863] fix(util): fix to take account the --prefix flag --- src/__tests__/unit/util/npm.test.ts | 11 ++--------- src/util/npm.ts | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 3fd4fac18..b7f028fa4 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -252,20 +252,13 @@ describe('util/npm: ', () => { it('successfully executes with correct commands.', async () => { const manifest = './src/__mocks__/mock-manifest.yaml'; const reManifest = 'src/__mocks__/re-mock-manifest.yaml'; - const command = `npm run if-env -- -m ${manifest} && npm run if-run -- -m ${manifest} -o ${reManifest.replace( - '.yaml', - '' - )} && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s ${reManifest} -t ${manifest}`; const logSpy = jest.spyOn(global.console, 'log'); - const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + jest.spyOn(fs, 'unlink').mockResolvedValue(); await executeCommands(manifest, false); - expect.assertions(2); - expect(spyExecPromise).toHaveBeenCalledWith(command, { - cwd: process.cwd(), - }); + expect.assertions(1); expect(logSpy).toHaveBeenCalledWith( 'if-check successfully verified mock-manifest.yaml\n' ); diff --git a/src/util/npm.ts b/src/util/npm.ts index 16c2cb4d2..de27ae4de 100644 --- a/src/util/npm.ts +++ b/src/util/npm.ts @@ -4,7 +4,12 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import {execPromise} from './helpers'; -import {isDirectoryExists, getFileName, isFileExists} from './fs'; +import { + isDirectoryExists, + getFileName, + isFileExists, + removeFileIfExists, +} from './fs'; import {logger} from './logger'; import {STRINGS} from '../config'; @@ -155,13 +160,19 @@ export const executeCommands = async (manifest: string, cwd: boolean) => { const manifestDirPath = path.dirname(manifest); const manifestFileName = getFileName(manifest); const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); - const ifEnv = `${isGlobal ? 'if-env' : 'npm run if-env --'} -m ${manifest}`; + const prefixFlag = + process.env.CURRENT_DIR && process.env.CURRENT_DIR !== process.cwd() + ? `--prefix=${path.relative(process.env.CURRENT_DIR!, process.cwd())}` + : ''; + const ifEnv = `${ + isGlobal ? `if-env ${prefixFlag}` : `npm run if-env ${prefixFlag} --` + } -m ${manifest}`; const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; const ifRunCommand = `${ - isGlobal ? 'if-run' : 'npm run if-run --' + isGlobal ? `if-run ${prefixFlag}` : `npm run if-run ${prefixFlag} --` } -m ${manifest} -o ${executedManifest}`; const ifDiffCommand = `${ - isGlobal ? 'if-diff' : 'npm run if-diff --' + isGlobal ? `if-diff ${prefixFlag}` : `npm run if-diff ${prefixFlag} --` } -s ${executedManifest}.yaml -t ${manifest}`; const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; @@ -173,10 +184,10 @@ export const executeCommands = async (manifest: string, cwd: boolean) => { ); if (!cwd) { - await fs.unlink(`${manifestDirPath}/package.json`); + await removeFileIfExists(`${manifestDirPath}/package.json`); } - await fs.unlink(`${executedManifest}.yaml`); + await removeFileIfExists(`${executedManifest}.yaml`); console.log(IF_CHECK_VERIFIED(path.basename(manifest))); }; From 86da2e60b8f5b9c896c9f063f5156e534f16967f Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 28 Jun 2024 15:11:31 +0400 Subject: [PATCH 258/863] fix(util): add log when in the directory no any yaml files --- src/check.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/check.ts b/src/check.ts index a7e561b04..3d53bc516 100644 --- a/src/check.ts +++ b/src/check.ts @@ -1,17 +1,16 @@ #!/usr/bin/env node /* eslint-disable no-process-exit */ -import * as fs from 'fs/promises'; import * as path from 'path'; import {logger} from './util/logger'; import {logStdoutFailMessage} from './util/helpers'; import {parseIfCheckArgs} from './util/args'; -import {getYamlFiles} from './util/fs'; +import {getYamlFiles, removeFileIfExists} from './util/fs'; import {STRINGS} from './config'; import {executeCommands} from './util/npm'; -const {CHECKING} = STRINGS; +const {CHECKING, DIRECTORY_YAML_FILES_NOT_FOUND} = STRINGS; const IfCheck = async () => { const commandArgs = await parseIfCheckArgs(); @@ -32,13 +31,18 @@ const IfCheck = async () => { logStdoutFailMessage(error, fileName); - await fs.unlink(`${manifestDirPath}/package.json`); - await fs.unlink(executedFile); + await removeFileIfExists(`${manifestDirPath}/package.json`); + await removeFileIfExists(executedFile); } } else { const directory = commandArgs.directory; const files = await getYamlFiles(directory!); + if (files.length === 0) { + console.log(DIRECTORY_YAML_FILES_NOT_FOUND); + process.exit(1); + } + for await (const file of files) { const fileName = path.basename(file); console.log(fileName); @@ -53,7 +57,7 @@ const IfCheck = async () => { logStdoutFailMessage(error, fileName); - await fs.unlink(executedFile); + await removeFileIfExists(executedFile); } } } From 8e969fdebc067966cfa56f78eb95e6364e37ccc7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 30 Jun 2024 11:58:22 +0400 Subject: [PATCH 259/863] chore(manifests): init outputs folder --- outputs/examples/copy.yaml | 69 +++++++ outputs/examples/generics.yaml | 240 ++++++++++++++++++++++++ outputs/examples/instance-metadata.yaml | 99 ++++++++++ 3 files changed, 408 insertions(+) create mode 100644 outputs/examples/copy.yaml create mode 100644 outputs/examples/generics.yaml create mode 100644 outputs/examples/instance-metadata.yaml diff --git a/outputs/examples/copy.yaml b/outputs/examples/copy.yaml new file mode 100644 index 000000000..6b088ab99 --- /dev/null +++ b/outputs/examples/copy.yaml @@ -0,0 +1,69 @@ +name: copy-param +description: null +tags: null +initialize: + plugins: + copy-param: + path: builtin + method: Copy + global-config: + keep-existing: true + from: original + to: copy + outputs: + - yaml +execution: + command: >- + /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node + /Users/admin/Projects/uk/if/src/index.ts --manifest + manifests/examples/copy.yaml --output outputs/examples/copy + environment: + if-version: 0.4.0 + os: macOS + os-version: 14.3.1 + node-version: 18.19.0 + date-time: 2024-06-30T07:53:07.361Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - copy-param + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + original: hello + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + original: hello + copy: hello diff --git a/outputs/examples/generics.yaml b/outputs/examples/generics.yaml new file mode 100644 index 000000000..2408d6b3d --- /dev/null +++ b/outputs/examples/generics.yaml @@ -0,0 +1,240 @@ +name: generics +description: >- + a pipeline that does arbitrary calculations using our generic arithmetic + builtins +tags: null +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + coefficient: + path: builtin + method: Coefficient + global-config: + input-parameter: cpu-energy-kwh + coefficient: 2 + output-parameter: energy-doubled + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/utilization + - duration + output-parameter: cpu-times-duration + outputs: + - yaml +execution: + command: >- + /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node + /Users/admin/Projects/uk/if/src/index.ts --manifest + manifests/examples/generics.yml --output outputs/examples/generics + environment: + if-version: 0.4.0 + os: macOS + os-version: 14.3.1 + node-version: 18.19.0 + date-time: 2024-06-30T07:53:53.523Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - coefficient + - multiply + config: null + defaults: + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 10 + energy: 5 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.75 + cpu-wattage: 75 + cpu-wattage-times-duration: 75 + cpu-energy-raw: 0.000020833333333333333 + vcpu-ratio: 8 + cpu-energy-kwh: 0.0000026041666666666666 + energy-doubled: 0.000005208333333333333 + cpu-times-duration: 50 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4275 + cpu-wattage: 42.75 + cpu-wattage-times-duration: 213.75 + cpu-energy-raw: 0.000059375 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000007421875 + energy-doubled: 0.00001484375 + cpu-times-duration: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 261.625 + cpu-energy-raw: 0.00007267361111111111 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009084201388888889 + energy-doubled: 0.000018168402777777778 + cpu-times-duration: 105 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 1121.25 + cpu-energy-raw: 0.00031145833333333335 + vcpu-ratio: 8 + cpu-energy-kwh: 0.00003893229166666667 + energy-doubled: 0.00007786458333333334 + cpu-times-duration: 450 diff --git a/outputs/examples/instance-metadata.yaml b/outputs/examples/instance-metadata.yaml new file mode 100644 index 000000000..41baa0b58 --- /dev/null +++ b/outputs/examples/instance-metadata.yaml @@ -0,0 +1,99 @@ +name: csv-demo +description: null +tags: null +initialize: + plugins: + cloud-instance-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: '*' + extract-processor-name: + path: builtin + method: Regex + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name + outputs: + - yaml +execution: + command: >- + /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node + /Users/admin/Projects/uk/if/src/index.ts --manifest + manifests/examples/instance-metadata.yml --output + outputs/examples/instance-metadata + environment: + if-version: 0.4.0 + os: macOS + os-version: 14.3.1 + node-version: 18.19.0 + date-time: 2024-06-30T07:54:34.384Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 + cpu-cores-available: 52 + cpu-cores-utilized: 1 + cpu-manufacturer: Intel + cpu-model-name: >- + 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 + cpu-tdp: 205 + gpu-count: nan + gpu-model-name: nan + gpu-tdp: nan + memory-available: 2 + cpu/name: Intel® Xeon® Platinum 8272CL From 9060fdb54a125597a65d77d86e38a83eddc0e6a8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 30 Jun 2024 11:59:22 +0400 Subject: [PATCH 260/863] feat(.github): add integration test to workflows --- .github/workflows/nodejs-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index e8aac6e88..306833939 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -19,5 +19,8 @@ jobs: - name: Run lint run: npm run lint - - name: Run tests + - name: Run unit tests run: npm run test --silent + + - name: Run integration tests + run: npm run if-check -- -d outputs From dad16522787d54f5e8a0cf5b8b3ef8615dc2177b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 30 Jun 2024 23:47:30 +0400 Subject: [PATCH 261/863] feat(builtins): add mock field to output --- src/__tests__/unit/builtins/copy-param.test.ts | 2 +- src/builtins/copy-param/index.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts index 64809e44a..2d0475988 100644 --- a/src/__tests__/unit/builtins/copy-param.test.ts +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../config'; const {GlobalConfigError, InputValidationError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -describe('builtins/copy: ', () => { +describe.skip('builtins/copy: ', () => { describe('Copy: ', () => { const globalConfig = { 'keep-existing': true, diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts index 6301bbf25..9730c1b07 100644 --- a/src/builtins/copy-param/index.ts +++ b/src/builtins/copy-param/index.ts @@ -75,8 +75,10 @@ export const Copy = (globalConfig: Record): ExecutePlugin => { delete safeInput[from]; } } + return { ...safeInput, // need to return or what you provide won't be outputted, don't be evil! + mock: '100', [to]: outputValue, }; }); From e917dd93a6c7a8931ac0f53a6c4503a552771c0d Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 08:39:27 +0400 Subject: [PATCH 262/863] feat(config): add string for if-check error summary log --- src/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/strings.ts b/src/config/strings.ts index 6a8a586f3..6c63fbb05 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -144,6 +144,8 @@ ${error}`, `if-check could not verify ${filename}. The re-executed file does not match the original.\n`, IF_CHECK_VERIFIED: (filename: string) => `if-check successfully verified ${filename}\n`, + IF_CHECK_SUMMARY_LOG: (passedCount: number, totalCount: number) => + `\nSummary of all failing files:\n${passedCount} of ${totalCount} files are passed.\n`, ZERO_DIVISION: (moduleName: string, index: number) => `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, }; From 4cc8134b3b88ed56cb2d952c6d2c5bbb2d20b62a Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 08:43:38 +0400 Subject: [PATCH 263/863] feat(util): update the logStdoutFailMessage function to return error message --- src/util/helpers.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 0fcdda963..067084548 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -280,4 +280,5 @@ export const logStdoutFailMessage = (error: any, fileName: string) => { const failMessage = logs[logs.length - 1]; console.log(failMessage); + return `${fileName}\n${failMessage}`; }; From fcca86925cc5cf62a760dcd2c23d589ce7bb7055 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 08:49:31 +0400 Subject: [PATCH 264/863] feat(src): add summary error log and exit with 1 code --- src/check.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/check.ts b/src/check.ts index 3d53bc516..aacfdc9e6 100644 --- a/src/check.ts +++ b/src/check.ts @@ -10,7 +10,8 @@ import {getYamlFiles, removeFileIfExists} from './util/fs'; import {STRINGS} from './config'; import {executeCommands} from './util/npm'; -const {CHECKING, DIRECTORY_YAML_FILES_NOT_FOUND} = STRINGS; +const {CHECKING, DIRECTORY_YAML_FILES_NOT_FOUND, IF_CHECK_SUMMARY_LOG} = + STRINGS; const IfCheck = async () => { const commandArgs = await parseIfCheckArgs(); @@ -35,6 +36,7 @@ const IfCheck = async () => { await removeFileIfExists(executedFile); } } else { + const failedLogs = {count: 0, message: ''}; const directory = commandArgs.directory; const files = await getYamlFiles(directory!); @@ -55,11 +57,21 @@ const IfCheck = async () => { .replace(fileName, `re-${fileName}`) .replace('yml', 'yaml'); - logStdoutFailMessage(error, fileName); + const failedFilesLog = logStdoutFailMessage(error, fileName); + failedLogs.message = failedLogs.message.concat(`${failedFilesLog}\n`); + failedLogs.count++; await removeFileIfExists(executedFile); } } + + if (failedLogs.count > 0) { + const passedFilesCount = files.length - failedLogs.count; + + console.log(IF_CHECK_SUMMARY_LOG(passedFilesCount, files.length)); + console.error(failedLogs.message); + process.exit(1); + } } }; From 3e1d8ecb4e71f06158248309c6612f1270a22c18 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 2 Jul 2024 12:36:50 +0400 Subject: [PATCH 265/863] fix(util): add check for debug log --- src/util/debug-logger.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/util/debug-logger.ts b/src/util/debug-logger.ts index 1a2481b16..f1f34ae0e 100644 --- a/src/util/debug-logger.ts +++ b/src/util/debug-logger.ts @@ -81,14 +81,16 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { return; } - const isDebugLog = logMessagesKeys.some(key => { - const message = - typeof STRINGS[key] === 'function' - ? (STRINGS[key] as Function).call(null, '') - : (STRINGS[key] as string); - - return args[0].includes(message); - }); + const isDebugLog = + typeof args[0] === 'string' && + logMessagesKeys.some(key => { + const message = + typeof STRINGS[key] === 'function' + ? (STRINGS[key] as Function).call(null, '') + : (STRINGS[key] as string); + + return args[0].includes(message); + }); if (!isDebugLog) { originalConsole.log(...args); From ef688799f555587801c676cfb0fa85fdb7093d1a Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 14:50:09 +0400 Subject: [PATCH 266/863] fix(config): add and update strings for If-check --- src/config/strings.ts | 11 ++++++++--- src/util/helpers.ts | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index 6c63fbb05..b6f3410b4 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -140,12 +140,17 @@ ${error}`, DIRECTORY_NOT_FOUND: 'Directory not found.', DIRECTORY_YAML_FILES_NOT_FOUND: 'The directory does not contain any YAML/YML files.\n', + IF_CHECK_EXECUTING: (filename: string) => `Executing \`${filename}\``, + IF_CHECK_VERIFICATION_FAILURES: + '---------\nif-check verification failures:\n', IF_CHECK_FAILED: (filename: string) => - `if-check could not verify ${filename}. The re-executed file does not match the original.\n`, + `✖ if-check could not verify ${filename}. The re-executed file does not match the original.\n`, IF_CHECK_VERIFIED: (filename: string) => - `if-check successfully verified ${filename}\n`, + `✔ if-check successfully verified ${filename}\n`, + IF_CHECK_SUMMARY_ERROR_MESSAGE: (filename: string, message: string) => + `Executing \`${filename}\`\n✖ ${message}`, IF_CHECK_SUMMARY_LOG: (passedCount: number, totalCount: number) => - `\nSummary of all failing files:\n${passedCount} of ${totalCount} files are passed.\n`, + `---------\nCheck summary:\n${passedCount} of ${totalCount} files are passed.\n`, ZERO_DIVISION: (moduleName: string, index: number) => `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, }; diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 067084548..c55b43724 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -33,7 +33,8 @@ const { FAILURE_MESSAGE_DEPENDENCIES, } = IF_ENV; -const {UNSUPPORTED_ERROR, IF_CHECK_FAILED} = STRINGS; +const {UNSUPPORTED_ERROR, IF_CHECK_FAILED, IF_CHECK_SUMMARY_ERROR_MESSAGE} = + STRINGS; const {MissingPluginDependenciesError} = ERRORS; /** @@ -280,5 +281,5 @@ export const logStdoutFailMessage = (error: any, fileName: string) => { const failMessage = logs[logs.length - 1]; console.log(failMessage); - return `${fileName}\n${failMessage}`; + return IF_CHECK_SUMMARY_ERROR_MESSAGE(fileName, failMessage); }; From f7f0a91494a00a15f6bf3b5bb1da83714654ad63 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 14:59:46 +0400 Subject: [PATCH 267/863] test(util): update tests according to changes --- src/__tests__/unit/util/helpers.test.ts | 2 +- src/__tests__/unit/util/npm.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index 7b6bc2eec..ed46dc0d9 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -678,7 +678,7 @@ description: mock-description expect.assertions(2); expect(logSpy).toHaveBeenCalledWith( - `if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` + `✖ if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` ); expect(logSpy).toHaveBeenCalledWith('mock error message'); diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index b7f028fa4..77133ffec 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -260,7 +260,7 @@ describe('util/npm: ', () => { expect.assertions(1); expect(logSpy).toHaveBeenCalledWith( - 'if-check successfully verified mock-manifest.yaml\n' + '✔ if-check successfully verified mock-manifest.yaml\n' ); const packageJsonPath = 'src/__mocks__/package.json'; From de29e4467b55072affda24712ff5e95741b10e7d Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 15:00:51 +0400 Subject: [PATCH 268/863] fix(src): update error logs --- src/check.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/check.ts b/src/check.ts index aacfdc9e6..54b6b1492 100644 --- a/src/check.ts +++ b/src/check.ts @@ -10,8 +10,13 @@ import {getYamlFiles, removeFileIfExists} from './util/fs'; import {STRINGS} from './config'; import {executeCommands} from './util/npm'; -const {CHECKING, DIRECTORY_YAML_FILES_NOT_FOUND, IF_CHECK_SUMMARY_LOG} = - STRINGS; +const { + CHECKING, + DIRECTORY_YAML_FILES_NOT_FOUND, + IF_CHECK_VERIFICATION_FAILURES, + IF_CHECK_SUMMARY_LOG, + IF_CHECK_EXECUTING, +} = STRINGS; const IfCheck = async () => { const commandArgs = await parseIfCheckArgs(); @@ -47,7 +52,7 @@ const IfCheck = async () => { for await (const file of files) { const fileName = path.basename(file); - console.log(fileName); + console.log(IF_CHECK_EXECUTING(fileName)); try { await executeCommands(file, true); @@ -68,8 +73,9 @@ const IfCheck = async () => { if (failedLogs.count > 0) { const passedFilesCount = files.length - failedLogs.count; + console.log(IF_CHECK_VERIFICATION_FAILURES); + console.log(failedLogs.message); console.log(IF_CHECK_SUMMARY_LOG(passedFilesCount, files.length)); - console.error(failedLogs.message); process.exit(1); } } From b5ace20daa33aa78a065a8f83d6ae3eec6bf98ef Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 15:49:38 +0400 Subject: [PATCH 269/863] test(util): improve npm.ts tests to run fast with mocks --- src/__tests__/unit/util/npm.test.ts | 68 +++++++++++++---------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts index 77133ffec..6d1476b42 100644 --- a/src/__tests__/unit/util/npm.test.ts +++ b/src/__tests__/unit/util/npm.test.ts @@ -1,5 +1,4 @@ import * as fs from 'fs/promises'; -import * as fsSync from 'fs'; import * as path from 'path'; jest.mock('fs/promises', () => require('../../../__mocks__/fs')); @@ -15,6 +14,29 @@ jest.mock('../../../util/logger', () => ({ }, })); +jest.mock('../../../util/helpers', () => { + const originalModule = jest.requireActual('../../../util/helpers'); + return { + ...originalModule, + execPromise: async (param: any) => { + switch (process.env.NPM_INSTALL) { + case 'true': + expect(param).toEqual('npm install @grnsft/if@0.3.3-beta.0'); + break; + case 'npm init -y': + expect(param).toEqual('npm init -y'); + break; + case 'if-check': + expect(param).toEqual( + "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" + ); + break; + } + return; + }, + }; +}); + import { installDependencies, initPackageJsonIfNotExists, @@ -31,33 +53,17 @@ import {ManifestPlugin} from '../../../types/npm'; const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; describe('util/npm: ', () => { - const helpers = require('../../../util/helpers'); const folderPath = path.resolve(__dirname, 'npm-test'); - beforeAll(() => { - if (!fsSync.existsSync(folderPath)) { - fsSync.mkdirSync(folderPath, {recursive: true}); - } - }); - - afterAll(() => { - if (fsSync.existsSync(folderPath)) { - fsSync.rmSync(folderPath, {recursive: true, force: true}); - } - }); - describe('initPackageJsonIfNotExists(): ', () => { it('initializes package.json if it does not exist.', async () => { - const spyExecPromise = jest.spyOn(helpers, 'execPromise'); + process.env.NPM_INSTALL = 'npm init -y'; isFileExists('true'); await initPackageJsonIfNotExists(folderPath); expect.assertions(2); expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); - expect(spyExecPromise).toHaveBeenCalledWith('npm init -y', { - cwd: folderPath, - }); }); it('returns the package.json path if it exists.', async () => { @@ -66,7 +72,7 @@ describe('util/npm: ', () => { const result = await initPackageJsonIfNotExists(folderPath); - expect.assertions(1); + expect.assertions(2); expect(result).toBe(packageJsonPath); }); }); @@ -77,17 +83,11 @@ describe('util/npm: ', () => { }; it('calls execPromise with the correct arguments.', async () => { - const spyExecPromise = jest.spyOn(helpers, 'execPromise'); - const formattedDependencies = ['@grnsft/if@0.3.3-beta.0']; + process.env.NPM_INSTALL = 'true'; expect.assertions(1); await installDependencies(folderPath, dependencies); - - expect(spyExecPromise).toHaveBeenCalledWith( - `npm install ${formattedDependencies.join(' ')}`, - {cwd: folderPath} - ); - }, 30000); + }); it('logs the installation message.', async () => { const dependencies = { @@ -96,7 +96,7 @@ describe('util/npm: ', () => { await installDependencies(folderPath, dependencies); - expect.assertions(1); + expect.assertions(2); expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); }); }); @@ -250,22 +250,16 @@ describe('util/npm: ', () => { describe('executeCommands(): ', () => { it('successfully executes with correct commands.', async () => { + process.env.NPM_INSTALL = 'if-check'; const manifest = './src/__mocks__/mock-manifest.yaml'; - const reManifest = 'src/__mocks__/re-mock-manifest.yaml'; const logSpy = jest.spyOn(global.console, 'log'); - jest.spyOn(fs, 'unlink').mockResolvedValue(); - await executeCommands(manifest, false); - expect.assertions(1); + expect.assertions(2); expect(logSpy).toHaveBeenCalledWith( '✔ if-check successfully verified mock-manifest.yaml\n' ); - - const packageJsonPath = 'src/__mocks__/package.json'; - fsSync.unlink(path.resolve(process.cwd(), reManifest), () => {}); - fsSync.unlink(path.resolve(process.cwd(), packageJsonPath), () => {}); - }, 70000); + }); }); }); From bddf47ef2b581e59dae4d007b5c14f58dd81704a Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 2 Jul 2024 16:08:44 +0400 Subject: [PATCH 270/863] fix(src): remove unnecessary new line --- src/check.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check.ts b/src/check.ts index 54b6b1492..f1e8f0cdd 100644 --- a/src/check.ts +++ b/src/check.ts @@ -63,7 +63,7 @@ const IfCheck = async () => { .replace('yml', 'yaml'); const failedFilesLog = logStdoutFailMessage(error, fileName); - failedLogs.message = failedLogs.message.concat(`${failedFilesLog}\n`); + failedLogs.message = failedLogs.message.concat(failedFilesLog); failedLogs.count++; await removeFileIfExists(executedFile); From 87a9978b7a462a93982b69587ff4efccc76da597 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 2 Jul 2024 20:00:41 +0400 Subject: [PATCH 271/863] revert(builtins): remove mock field --- src/builtins/copy-param/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts index 9730c1b07..0602f6f75 100644 --- a/src/builtins/copy-param/index.ts +++ b/src/builtins/copy-param/index.ts @@ -78,7 +78,6 @@ export const Copy = (globalConfig: Record): ExecutePlugin => { return { ...safeInput, // need to return or what you provide won't be outputted, don't be evil! - mock: '100', [to]: outputValue, }; }); From 7ea8fded0e2b1c42a5596632d15d2aca5b509084 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 2 Jul 2024 20:01:18 +0400 Subject: [PATCH 272/863] test(builtins): unskip copy-params tests --- src/__tests__/unit/builtins/copy-param.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts index 2d0475988..64809e44a 100644 --- a/src/__tests__/unit/builtins/copy-param.test.ts +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../config'; const {GlobalConfigError, InputValidationError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -describe.skip('builtins/copy: ', () => { +describe('builtins/copy: ', () => { describe('Copy: ', () => { const globalConfig = { 'keep-existing': true, From a5c9ad2acc69d8b7f32a02e8cca33e7a265b7fbc Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 3 Jul 2024 01:39:49 +0400 Subject: [PATCH 273/863] feat(manifests): replaced input manifests with output manifests --- .../bugs/aggregation-error-wrong-metric.yml | 178 ----- .../bugs/azure-importer-ignoring-defaults.yml | 64 -- .../azure-importer-incorrect-calculation.yml | 59 -- manifests/bugs/initialize-error-no-config.yml | 26 - manifests/bugs/initialize-error-no-path.yml | 32 - .../bugs/input-error-missing-duration.yml | 25 - ...-observations-failure-duration-is-zero.yml | 34 - .../bugs/pipeline-error-naming-mismatch.yml | 32 - .../pipeline-error-uninitialized-plugin.yml | 33 - manifests/bugs/pipeline-ordering-error.yml | 91 --- .../sci-embodied-missing-resources-total.yml | 23 - .../failure-invalid-config-input-param.yml | 0 .../failure-output-param-is-null.yaml | 0 .../builtins}/coefficient/success.yml | 0 .../csv-lookup}/failure-missing-column.yml | 0 .../csv-lookup}/failure-missing-output.yml | 0 .../builtins/csv-lookup/success-renaming.yaml | 83 +++ .../examples/builtins/csv-lookup/success.yaml | 95 +++ .../divide/failure-denominator-equal-zero.yml | 17 +- .../failure-invalid-config-denominator.yml | 17 +- .../divide/failure-missing-numerator.yml | 17 +- .../builtins}/divide/success.yml | 19 +- .../groupby/failure-invalid-config-group.yml | 0 .../failure-missing-cloud-instance-type.yml | 0 .../builtins}/groupby/success.yml | 2 +- .../builtins}/interpolation/interpolation.yml | 0 .../failure-invalid-config-cpu-range.yml | 0 ...ilure-invalid-memory-utilization-range.yml | 0 .../failure-missing-timestamp-from-param.yml | 0 .../builtins}/mock-observations/success.yml | 2 +- .../failure-input-parameter-is-missing.yml | 0 .../multiply/success-with-multiple-inputs.yml | 0 .../builtins}/multiply/success.yml | 0 .../regex/failure-missing-input-param.yml | 0 .../regex/failure-not-matching-with-regex.yml | 0 .../builtins}/regex/success.yml | 0 ...failure-invalid-default-emission-value.yml | 0 .../failure-missing-expected-lifespan.yml | 0 .../builtins}/sci-embodied/success.yml | 0 .../sci/failure-invalid-config-value.yml | 0 .../sci/failure-missing-input-param.yml | 8 +- .../builtins}/sci/success.yml | 3 + .../shell/failure-invalid-command.yml | 0 .../builtins}/shell/success.yml | 0 .../sum/failure-missing-input-param.yml | 0 .../sum/failure-missing-output-param.yml | 0 .../builtins}/sum/success.yml | 2 +- .../failure-config-start-later-end.yml | 0 .../failure-missing-global-config.yml | 0 .../builtins}/time-sync/success.yml | 0 manifests/examples/copy.yaml | 20 - manifests/examples/generics.yml | 106 --- .../pipelines/basic.yml} | 10 +- manifests/examples/pipelines/generics.yml | 45 ++ .../{ => pipelines}/instance-metadata.yml | 8 +- .../mock-cpu-util-to-carbon.yml | 10 +- .../examples/{ => pipelines}/nesting.yml | 117 +--- .../{ => pipelines}/pipeline-teads-sci.yml | 72 +- .../pipeline-with-aggregate.yml | 90 +-- .../{ => pipelines}/pipeline-with-mocks.yml | 87 +-- manifests/examples/{ => pipelines}/sci.yml | 0 .../examples/{ => pipelines}/teads-curve.yml | 0 manifests/examples/region-metadata.yml | 26 - manifests/examples/tdp-finder.yml | 23 - manifests/examples/zeros.yaml | 130 ---- .../aggregate-failure-invalid-metrics.yml | 49 -- ...egate-failure-missing-metric-in-inputs.yml | 49 -- manifests/features/aggregate-horizontal.yml | 50 -- manifests/features/aggregate-vertical.yml | 50 -- manifests/features/aggregate.yml | 50 -- .../integrations/cloud-metadata-divide.yml | 37 - .../failure-invalid-instance-type.yaml | 33 - .../failure-invalid-provider.yaml | 33 - .../failure-missing-queried-input.yml | 33 - .../instance-metadata/success.yml | 33 - .../mock-obs-group-by-cloud-meta.yml | 57 -- manifests/integrations/mock-obs-groupby.yml | 39 -- manifests/integrations/mock-obs-time-sync.yml | 110 --- .../bugs/aggregation-error-wrong-metric.yaml | 243 +++++++ .../bugs/initialize-error-no-config.yaml | 81 +++ .../bugs/initialize-error-no-path.yaml | 94 +++ .../bugs/initialize-error-no-plugins.yaml | 77 +++ .../bugs/input-error-missing-duration.yaml | 87 +++ ...observations-failure-duration-is-zero.yaml | 84 +++ .../bugs/pipeline-error-naming-mismatch.yaml | 94 +++ .../pipeline-error-uninitialized-plugin.yaml | 95 +++ .../outputs/bugs/pipeline-ordering-error.yaml | 158 +++++ .../sci-embodied-missing-resources-total.yaml | 76 ++ .../aggregate-failure-invalid-metrics.yaml | 104 +++ ...gate-failure-missing-metric-in-inputs.yaml | 103 +++ .../features/aggregate-horizontal.yaml | 131 ++++ .../outputs/features/aggregate-vertical.yaml | 154 +++++ manifests/outputs/features/aggregate.yaml | 158 +++++ .../pipelines/cloud-metadata-divide.yaml | 98 +++ .../mock-obs-group-by-cloud-meta.yaml | 648 ++++++++++++++++++ .../outputs/pipelines/mock-obs-groupby.yaml | 181 +++++ .../outputs/pipelines/mock-obs-time-sync.yaml | 353 ++++++++++ .../failure-invalid-config-input-param.yaml | 76 ++ .../failure-output-param-is-null.yaml | 76 ++ .../outputs/plugins/coefficient/success.yaml | 78 +++ .../failure-invalid-instance-type.yaml | 0 .../failure-invalid-vendor.yaml | 0 .../failure-missing-cloud-vendor.yaml | 80 +++ .../csv-lookup/cloud-metadata/success.yaml | 85 +++ .../failure-missing-column.yaml | 79 +++ .../failure-missing-output.yaml | 78 +++ .../region-metadata/success-renaming.yaml | 83 +++ .../csv-lookup/region-metadata/success.yaml | 95 +++ .../failure-missing-input-param.yaml | 77 +++ ...ailure-unsupported-physical-processor.yaml | 78 +++ .../csv-lookup/tdp-finder/success.yaml | 79 +++ .../failure-invalid-config-denominator.yaml | 76 ++ .../divide/failure-missing-numerator.yaml | 80 +++ .../success-denominator-equal-zero.yaml | 98 +++ manifests/outputs/plugins/divide/success.yaml | 98 +++ .../outputs/plugins/exponent/success.yaml | 80 +++ .../groupby/failure-invalid-config-group.yaml | 99 +++ .../failure-missing-cloud-instance-type.yaml | 98 +++ .../outputs/plugins/groupby/success.yaml | 104 +++ .../plugins/interpolation/interpolation.yaml | 86 +++ .../plugins/interpolation/success.yaml | 86 +++ .../failure-invalid-config-cpu-range.yaml | 89 +++ ...lure-invalid-memory-utilization-range.yaml | 87 +++ .../failure-missing-timestamp-from-param.yaml | 86 +++ .../plugins/mock-observations/success.yaml | 223 ++++++ .../failure-input-parameter-is-missing.yaml | 78 +++ .../success-with-multiple-inputs.yaml | 99 +++ .../outputs/plugins/multiply/success.yaml | 81 +++ .../regex/failure-missing-input-param.yaml | 78 +++ .../failure-not-matching-with-regex.yaml | 79 +++ manifests/outputs/plugins/regex/success.yaml | 84 +++ ...ailure-invalid-default-emission-value.yaml | 78 +++ .../failure-missing-expected-lifespan.yaml | 74 ++ .../outputs/plugins/sci-embodied/success.yaml | 81 +++ .../sci/failure-invalid-config-value.yaml | 75 ++ .../sci/failure-missing-input-param.yaml | 75 ++ .../outputs/plugins/sci/success.yml.yaml | 83 +++ .../shell/failure-invalid-command.yaml | 73 ++ manifests/outputs/plugins/shell/success.yaml | 71 ++ .../outputs/plugins/subtract/success.yaml | 81 +++ .../sum/failure-missing-input-param.yaml | 78 +++ .../sum/failure-missing-output-param.yaml | 81 +++ manifests/outputs/plugins/sum/success.yaml | 81 +++ .../failure-config-start-later-end.yaml | 85 +++ .../failure-missing-global-config.yaml | 81 +++ .../outputs/plugins/time-sync/success.yaml | 122 ++++ .../failure-missing-cloud-vendor.yml | 27 - .../csv-lookup/cloud-metadata/success.yml | 27 - .../region-metadata/success-renaming.yml | 26 - .../csv-lookup/region-metadata/success.yml | 26 - .../failure-missing-input-param.yml | 23 - ...failure-unsupported-physical-processor.yml | 24 - .../plugins/csv-lookup/tdp-finder/success.yml | 24 - manifests/plugins/exponent/success.yml | 26 - manifests/plugins/interpolation/success.yml | 24 - manifests/plugins/subtract/success.yml | 25 - 156 files changed, 7475 insertions(+), 2097 deletions(-) delete mode 100644 manifests/bugs/aggregation-error-wrong-metric.yml delete mode 100644 manifests/bugs/azure-importer-ignoring-defaults.yml delete mode 100644 manifests/bugs/azure-importer-incorrect-calculation.yml delete mode 100644 manifests/bugs/initialize-error-no-config.yml delete mode 100644 manifests/bugs/initialize-error-no-path.yml delete mode 100644 manifests/bugs/input-error-missing-duration.yml delete mode 100644 manifests/bugs/mock-observations-failure-duration-is-zero.yml delete mode 100644 manifests/bugs/pipeline-error-naming-mismatch.yml delete mode 100644 manifests/bugs/pipeline-error-uninitialized-plugin.yml delete mode 100644 manifests/bugs/pipeline-ordering-error.yml delete mode 100644 manifests/bugs/sci-embodied-missing-resources-total.yml rename manifests/{plugins => examples/builtins}/coefficient/failure-invalid-config-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/coefficient/failure-output-param-is-null.yaml (100%) rename manifests/{plugins => examples/builtins}/coefficient/success.yml (100%) rename manifests/{plugins/csv-lookup/region-metadata => examples/builtins/csv-lookup}/failure-missing-column.yml (100%) rename manifests/{plugins/csv-lookup/region-metadata => examples/builtins/csv-lookup}/failure-missing-output.yml (100%) create mode 100644 manifests/examples/builtins/csv-lookup/success-renaming.yaml create mode 100644 manifests/examples/builtins/csv-lookup/success.yaml rename manifests/{plugins => examples/builtins}/divide/failure-denominator-equal-zero.yml (69%) rename manifests/{plugins => examples/builtins}/divide/failure-invalid-config-denominator.yml (69%) rename manifests/{plugins => examples/builtins}/divide/failure-missing-numerator.yml (68%) rename manifests/{plugins => examples/builtins}/divide/success.yml (66%) rename manifests/{plugins => examples/builtins}/groupby/failure-invalid-config-group.yml (100%) rename manifests/{plugins => examples/builtins}/groupby/failure-missing-cloud-instance-type.yml (100%) rename manifests/{plugins => examples/builtins}/groupby/success.yml (98%) rename manifests/{plugins => examples/builtins}/interpolation/interpolation.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/failure-invalid-config-cpu-range.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/failure-invalid-memory-utilization-range.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/failure-missing-timestamp-from-param.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/success.yml (95%) rename manifests/{plugins => examples/builtins}/multiply/failure-input-parameter-is-missing.yml (100%) rename manifests/{plugins => examples/builtins}/multiply/success-with-multiple-inputs.yml (100%) rename manifests/{plugins => examples/builtins}/multiply/success.yml (100%) rename manifests/{plugins => examples/builtins}/regex/failure-missing-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/regex/failure-not-matching-with-regex.yml (100%) rename manifests/{plugins => examples/builtins}/regex/success.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/failure-invalid-default-emission-value.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/failure-missing-expected-lifespan.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/success.yml (100%) rename manifests/{plugins => examples/builtins}/sci/failure-invalid-config-value.yml (100%) rename manifests/{plugins => examples/builtins}/sci/failure-missing-input-param.yml (65%) rename manifests/{plugins => examples/builtins}/sci/success.yml (79%) rename manifests/{plugins => examples/builtins}/shell/failure-invalid-command.yml (100%) rename manifests/{plugins => examples/builtins}/shell/success.yml (100%) rename manifests/{plugins => examples/builtins}/sum/failure-missing-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/sum/failure-missing-output-param.yml (100%) rename manifests/{plugins => examples/builtins}/sum/success.yml (95%) rename manifests/{plugins => examples/builtins}/time-sync/failure-config-start-later-end.yml (100%) rename manifests/{plugins => examples/builtins}/time-sync/failure-missing-global-config.yml (100%) rename manifests/{plugins => examples/builtins}/time-sync/success.yml (100%) delete mode 100644 manifests/examples/copy.yaml delete mode 100644 manifests/examples/generics.yml rename manifests/{bugs/initialize-error-no-plugins.yml => examples/pipelines/basic.yml} (63%) create mode 100644 manifests/examples/pipelines/generics.yml rename manifests/examples/{ => pipelines}/instance-metadata.yml (94%) rename manifests/examples/{ => pipelines}/mock-cpu-util-to-carbon.yml (85%) rename manifests/examples/{ => pipelines}/nesting.yml (71%) rename manifests/examples/{ => pipelines}/pipeline-teads-sci.yml (54%) rename manifests/examples/{ => pipelines}/pipeline-with-aggregate.yml (61%) rename manifests/examples/{ => pipelines}/pipeline-with-mocks.yml (65%) rename manifests/examples/{ => pipelines}/sci.yml (100%) rename manifests/examples/{ => pipelines}/teads-curve.yml (100%) delete mode 100644 manifests/examples/region-metadata.yml delete mode 100644 manifests/examples/tdp-finder.yml delete mode 100644 manifests/examples/zeros.yaml delete mode 100644 manifests/features/aggregate-failure-invalid-metrics.yml delete mode 100644 manifests/features/aggregate-failure-missing-metric-in-inputs.yml delete mode 100644 manifests/features/aggregate-horizontal.yml delete mode 100644 manifests/features/aggregate-vertical.yml delete mode 100644 manifests/features/aggregate.yml delete mode 100644 manifests/integrations/cloud-metadata-divide.yml delete mode 100644 manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml delete mode 100644 manifests/integrations/instance-metadata/failure-invalid-provider.yaml delete mode 100644 manifests/integrations/instance-metadata/failure-missing-queried-input.yml delete mode 100644 manifests/integrations/instance-metadata/success.yml delete mode 100644 manifests/integrations/mock-obs-group-by-cloud-meta.yml delete mode 100644 manifests/integrations/mock-obs-groupby.yml delete mode 100644 manifests/integrations/mock-obs-time-sync.yml create mode 100644 manifests/outputs/bugs/aggregation-error-wrong-metric.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-config.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-path.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-plugins.yaml create mode 100644 manifests/outputs/bugs/input-error-missing-duration.yaml create mode 100644 manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml create mode 100644 manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml create mode 100644 manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml create mode 100644 manifests/outputs/bugs/pipeline-ordering-error.yaml create mode 100644 manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml create mode 100644 manifests/outputs/features/aggregate-failure-invalid-metrics.yaml create mode 100644 manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml create mode 100644 manifests/outputs/features/aggregate-horizontal.yaml create mode 100644 manifests/outputs/features/aggregate-vertical.yaml create mode 100644 manifests/outputs/features/aggregate.yaml create mode 100644 manifests/outputs/pipelines/cloud-metadata-divide.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-groupby.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-time-sync.yaml create mode 100644 manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml create mode 100644 manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml create mode 100644 manifests/outputs/plugins/coefficient/success.yaml rename manifests/{ => outputs}/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml (100%) rename manifests/{ => outputs}/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml (100%) create mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml create mode 100644 manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml create mode 100644 manifests/outputs/plugins/divide/failure-missing-numerator.yaml create mode 100644 manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml create mode 100644 manifests/outputs/plugins/divide/success.yaml create mode 100644 manifests/outputs/plugins/exponent/success.yaml create mode 100644 manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml create mode 100644 manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml create mode 100644 manifests/outputs/plugins/groupby/success.yaml create mode 100644 manifests/outputs/plugins/interpolation/interpolation.yaml create mode 100644 manifests/outputs/plugins/interpolation/success.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml create mode 100644 manifests/outputs/plugins/mock-observations/success.yaml create mode 100644 manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml create mode 100644 manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml create mode 100644 manifests/outputs/plugins/multiply/success.yaml create mode 100644 manifests/outputs/plugins/regex/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml create mode 100644 manifests/outputs/plugins/regex/success.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/success.yaml create mode 100644 manifests/outputs/plugins/sci/failure-invalid-config-value.yaml create mode 100644 manifests/outputs/plugins/sci/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/sci/success.yml.yaml create mode 100644 manifests/outputs/plugins/shell/failure-invalid-command.yaml create mode 100644 manifests/outputs/plugins/shell/success.yaml create mode 100644 manifests/outputs/plugins/subtract/success.yaml create mode 100644 manifests/outputs/plugins/sum/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/sum/failure-missing-output-param.yaml create mode 100644 manifests/outputs/plugins/sum/success.yaml create mode 100644 manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml create mode 100644 manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml create mode 100644 manifests/outputs/plugins/time-sync/success.yaml delete mode 100644 manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml delete mode 100644 manifests/plugins/csv-lookup/cloud-metadata/success.yml delete mode 100644 manifests/plugins/csv-lookup/region-metadata/success-renaming.yml delete mode 100644 manifests/plugins/csv-lookup/region-metadata/success.yml delete mode 100644 manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml delete mode 100644 manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml delete mode 100644 manifests/plugins/csv-lookup/tdp-finder/success.yml delete mode 100644 manifests/plugins/exponent/success.yml delete mode 100644 manifests/plugins/interpolation/success.yml delete mode 100644 manifests/plugins/subtract/success.yml diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml deleted file mode 100644 index 2c3141c13..000000000 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ /dev/null @@ -1,178 +0,0 @@ -name: aggregation-error-wrong-metric -description: a negative test case that fails due to the aggregation feature being passed an incorrect metric -tags: -aggregation: - metrics: - - "dummy-param" - type: "both" -initialize: - plugins: - "interpolate": - 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: 'cpu-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - "sci-embodied": - path: "builtin" - method: SciEmbodied - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon" - "sci": - path: "builtin" - method: Sci - global-config: - functional-unit: "requests" - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true - "group-by": - path: builtin - method: GroupBy -tree: - children: - child-1: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 100 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 100 - child-2: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 diff --git a/manifests/bugs/azure-importer-ignoring-defaults.yml b/manifests/bugs/azure-importer-ignoring-defaults.yml deleted file mode 100644 index b6749ee70..000000000 --- a/manifests/bugs/azure-importer-ignoring-defaults.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: pipeline-demo -description: https://github.com/Green-Software-Foundation/if-unofficial-plugins/issues/81 -tags: -# aggregation: -# metrics: -# - "carbon" -# - "energy" -#type: "both" -initialize: - outputs: - - yaml - # - csv - plugins: - "azure-importer": - method: AzureImporter - path: "@grnsft/if-unofficial-plugins" - "try-defaults-1": - path: "builtin" - method: Coefficient - global-config: - input-parameter: grid/carbon-intensity - coefficient: 0.1 - output-parameter: grid/carbon-intensity - "try-defaults-2": - path: "builtin" - method: Coefficient - global-config: - input-parameter: network/energy - coefficient: 1000 - output-parameter: network/energy - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["energy", "grid/carbon-intensity"] - output-parameter: "carbon-operational" - "group-by": - path: "builtin" - method: GroupBy -tree: - children: - web-front: # name this according to the sub-system, e.g. portal, APIs/backend, DB - pipeline: - - azure-importer - #- try-defaults-1 - #- try-defaults-2 - - sci-o - config: - group-by: - group: - - instance-type - azure-importer: - azure-observation-window: 60 min - azure-observation-aggregation: "average" - azure-subscription-id: 30b6e171-af2c-4fe6-b00d-d4c70f6291fe - azure-resource-group: gcf-app_group - azure-vm-name: gcf-app - defaults: - grid/carbon-intensity: 800 # adjust for SG grid - network/energy: 0.001 # review for naming accuracy - inputs: - - timestamp: "2024-04-04T08:00:00.001Z" - duration: 3600 - energy: 100 diff --git a/manifests/bugs/azure-importer-incorrect-calculation.yml b/manifests/bugs/azure-importer-incorrect-calculation.yml deleted file mode 100644 index bbac70ae2..000000000 --- a/manifests/bugs/azure-importer-incorrect-calculation.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: pipeline-demo -description: https://github.com/Green-Software-Foundation/if-unofficial-plugins/issues/81 -tags: null -initialize: - plugins: - azure-importer: - path: '@grnsft/if-unofficial-plugins' - method: AzureImporter - try-defaults-1: - path: 'builtin' - method: Coefficient - global-config: - input-parameter: grid/carbon-intensity - coefficient: 0.1 - output-parameter: grid/carbon-intensity - try-defaults-2: - path: 'builtin' - method: Coefficient - global-config: - input-parameter: network/energy - coefficient: 1000 - output-parameter: network/energy - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["energy", "grid/carbon-intensity"] - output-parameter: "carbon-operational" - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -if-version: v0.3.2 -tree: - children: - web-front: - pipeline: - - azure-importer - - try-defaults-1 - - try-defaults-2 - config: - group-by: - group: - - instance-type - azure-importer: - azure-observation-window: 60 min - azure-observation-aggregation: average - azure-subscription-id: 30b6e171-af2c-4fe6-b00d-d4c70f6291fe - azure-resource-group: gcf-app_group - azure-vm-name: gcf-app - defaults: - grid/carbon-intensity: 800 - network/energy: 0.001 - inputs: - - timestamp: '2024-04-04T08:00:00.001Z' - duration: 3600 - energy: 100 - \ No newline at end of file diff --git a/manifests/bugs/initialize-error-no-config.yml b/manifests/bugs/initialize-error-no-config.yml deleted file mode 100644 index 466c7f5f9..000000000 --- a/manifests/bugs/initialize-error-no-config.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: initialize-error-no-config -description: a negative test case that fails due to plugin initialization missing some required config -tags: -initialize: - plugins: - "interpolate": - method: Interpolation - path: 'builtin' - global-config: -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/initialize-error-no-path.yml b/manifests/bugs/initialize-error-no-path.yml deleted file mode 100644 index 279f304e6..000000000 --- a/manifests/bugs/initialize-error-no-path.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: initialize-error-no-path -description: a negative test case that fails because the path is mising in a plugin initialization -tags: -initialize: - plugins: - "interpolate": - method: Interpolation - path: - 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-factor' - # outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/input-error-missing-duration.yml b/manifests/bugs/input-error-missing-duration.yml deleted file mode 100644 index a2e7f3ca4..000000000 --- a/manifests/bugs/input-error-missing-duration.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: input-error-missing-duration -description: a negative test case that fails due to the required `duration` field being omitted from input data -tags: -initialize: - plugins: - "interpolate": - 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: 'cpu-factor' - # outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - cpu/utilization: 20 diff --git a/manifests/bugs/mock-observations-failure-duration-is-zero.yml b/manifests/bugs/mock-observations-failure-duration-is-zero.yml deleted file mode 100644 index e3d0d4cb8..000000000 --- a/manifests/bugs/mock-observations-failure-duration-is-zero.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: mock-observation-demo -description: a manifest demonstrating how to use the mock observations feature -tags: -initialize: - outputs: ['yaml'] - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: "builtin" - global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 0 - components: - - cloud/instance-type: A1 - - cloud/instance-type: B1 - generators: - common: - region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - memory/utilization: - min: 1 - max: 99 -tree: - children: - child: - pipeline: - - mock-observations - inputs: diff --git a/manifests/bugs/pipeline-error-naming-mismatch.yml b/manifests/bugs/pipeline-error-naming-mismatch.yml deleted file mode 100644 index 982e89088..000000000 --- a/manifests/bugs/pipeline-error-naming-mismatch.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: pipeline-error-naming-mismatch -description: a negative test case that fails due to the plugin name in the pipeline not matching the name given in initialize -tags: -initialize: - plugins: - "interpolate": - 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: 'cpu-factor' - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - wrong-name - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/pipeline-error-uninitialized-plugin.yml b/manifests/bugs/pipeline-error-uninitialized-plugin.yml deleted file mode 100644 index 7bead556b..000000000 --- a/manifests/bugs/pipeline-error-uninitialized-plugin.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: pipeline-uninitialized-plugin-error -description: a negative test case that fails due to an uninitialized plugin being invoked in a pipeline -tags: -initialize: - # outputs: ['yaml'] - plugins: - "interpolate": - 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: 'cpu-factor' -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - - multiply - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/pipeline-ordering-error.yml b/manifests/bugs/pipeline-ordering-error.yml deleted file mode 100644 index 7fa8836c1..000000000 --- a/manifests/bugs/pipeline-ordering-error.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: pipeline-ordering-error -description: a negative test case that fails because sci-o is invoked too early in the pipeline (before its inputs are generated) -tags: -initialize: - plugins: - "interpolate": - 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: 'cpu-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh -tree: - children: - child-1: - pipeline: - - interpolate - - correct-cpu-energy-for-vcpu-ratio - - calculate-vcpu-ratio - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - config: - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 50 - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - network/energy: 0.000001 diff --git a/manifests/bugs/sci-embodied-missing-resources-total.yml b/manifests/bugs/sci-embodied-missing-resources-total.yml deleted file mode 100644 index 952859c56..000000000 --- a/manifests/bugs/sci-embodied-missing-resources-total.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: sci-embodied -description: receiving incorrect error message when running sci-embodied without `resources-total` issue #716 -tags: -initialize: - #outputs: ['yaml'] - plugins: - "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor - method: SciEmbodied - path: "builtin" -tree: - children: - child: - pipeline: - - sci-embodied # duration & config -> embodied - defaults: - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - # resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/plugins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml similarity index 100% rename from manifests/plugins/coefficient/failure-invalid-config-input-param.yml rename to manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml diff --git a/manifests/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml similarity index 100% rename from manifests/plugins/coefficient/failure-output-param-is-null.yaml rename to manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml diff --git a/manifests/plugins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml similarity index 100% rename from manifests/plugins/coefficient/success.yml rename to manifests/examples/builtins/coefficient/success.yml diff --git a/manifests/plugins/csv-lookup/region-metadata/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/failure-missing-column.yml similarity index 100% rename from manifests/plugins/csv-lookup/region-metadata/failure-missing-column.yml rename to manifests/examples/builtins/csv-lookup/failure-missing-column.yml diff --git a/manifests/plugins/csv-lookup/region-metadata/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/failure-missing-output.yml similarity index 100% rename from manifests/plugins/csv-lookup/region-metadata/failure-missing-output.yml rename to manifests/examples/builtins/csv-lookup/failure-missing-output.yml diff --git a/manifests/examples/builtins/csv-lookup/success-renaming.yaml b/manifests/examples/builtins/csv-lookup/success-renaming.yaml new file mode 100644 index 000000000..80d12e8a8 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/success-renaming.yaml @@ -0,0 +1,83 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: + - em-zone-id + - renamed-em-zone-data + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/examples/builtins/csv-lookup/success-renaming.yml -o + manifests/examples/builtins/csv-lookup/success-renaming + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:16:40.781Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + renamed-em-zone-data: TW diff --git a/manifests/examples/builtins/csv-lookup/success.yaml b/manifests/examples/builtins/csv-lookup/success.yaml new file mode 100644 index 000000000..0f616f376 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/success.yaml @@ -0,0 +1,95 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: '*' + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/examples/builtins/csv-lookup/success.yml -o + manifests/examples/builtins/csv-lookup/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:09:37.066Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + year: 2022 + cfe-region: Taiwan + em-zone-id: TW + wt-region-id: TW + location: Taiwan + geolocation: 25.0375,121.5625 + cfe-hourly: 0.18 + cfe-annual: nan + power-usage-efficiency: nan + net-carbon: 0 + grid-carbon-intensity-24x7: 453 + grid-carbon-intensity-consumption: nan + grid-carbon-intensity-marginal: nan + grid-carbon-intensity-production: nan + grid-carbon-intensity: 453 diff --git a/manifests/plugins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml similarity index 69% rename from manifests/plugins/divide/failure-denominator-equal-zero.yml rename to manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index 4022d4797..af5ed2ae0 100644 --- a/manifests/plugins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -5,14 +5,8 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + method: CloudMetadata + path: "@grnsft/if-plugins" divide: method: Divide path: "builtin" @@ -20,12 +14,19 @@ initialize: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores + boavizta-cpu: + method: BoaviztaCpuOutput + path: "@grnsft/if-unofficial-plugins" + global-config: + allocation: LINEAR + verbose: true tree: children: child: pipeline: - cloud-metadata - divide + - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml similarity index 69% rename from manifests/plugins/divide/failure-invalid-config-denominator.yml rename to manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 91129714a..063274bc0 100644 --- a/manifests/plugins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -5,14 +5,8 @@ initialize: outputs: ['yaml'] plugins: cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + method: CloudMetadata + path: "@grnsft/if-plugins" divide: method: Divide path: "builtin" @@ -20,12 +14,19 @@ initialize: numerator: vcpus-allocated denominator: 'vcpus' output: cpu/number-cores + boavizta-cpu: + method: BoaviztaCpuOutput + path: "@grnsft/if-unofficial-plugins" + global-config: + allocation: LINEAR + verbose: true tree: children: child: pipeline: - cloud-metadata - divide + - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml similarity index 68% rename from manifests/plugins/divide/failure-missing-numerator.yml rename to manifests/examples/builtins/divide/failure-missing-numerator.yml index 7cf123976..7f03d5eba 100644 --- a/manifests/plugins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -5,14 +5,8 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + method: CloudMetadata + path: "@grnsft/if-plugins" divide: method: Divide path: "builtin" @@ -20,12 +14,19 @@ initialize: #numerator: vcpus-allocated denominator: 2 output: cpu/number-cores + boavizta-cpu: + method: BoaviztaCpuOutput + path: "@grnsft/if-unofficial-plugins" + global-config: + allocation: LINEAR + verbose: true tree: children: child: pipeline: - cloud-metadata - divide + - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/success.yml b/manifests/examples/builtins/divide/success.yml similarity index 66% rename from manifests/plugins/divide/success.yml rename to manifests/examples/builtins/divide/success.yml index 6a32d7e2c..ed75a7c5c 100644 --- a/manifests/plugins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -2,17 +2,11 @@ name: divide description: success path tags: initialize: - # outputs: ['yaml'] +# outputs: ['yaml'] plugins: cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + method: CloudMetadata + path: "@grnsft/if-plugins" divide: method: Divide path: "builtin" @@ -20,12 +14,19 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores + boavizta-cpu: + method: BoaviztaCpuOutput + path: "@grnsft/if-unofficial-plugins" + global-config: + allocation: LINEAR + verbose: true tree: children: child: pipeline: - cloud-metadata - divide + - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/groupby/failure-invalid-config-group.yml b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml similarity index 100% rename from manifests/plugins/groupby/failure-invalid-config-group.yml rename to manifests/examples/builtins/groupby/failure-invalid-config-group.yml diff --git a/manifests/plugins/groupby/failure-missing-cloud-instance-type.yml b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml similarity index 100% rename from manifests/plugins/groupby/failure-missing-cloud-instance-type.yml rename to manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml diff --git a/manifests/plugins/groupby/success.yml b/manifests/examples/builtins/groupby/success.yml similarity index 98% rename from manifests/plugins/groupby/success.yml rename to manifests/examples/builtins/groupby/success.yml index 0105799b1..b81e7d53e 100644 --- a/manifests/plugins/groupby/success.yml +++ b/manifests/examples/builtins/groupby/success.yml @@ -1,7 +1,7 @@ name: groupby description: successful path initialize: - outputs: ['yaml'] + plugins: group-by: path: "builtin" diff --git a/manifests/plugins/interpolation/interpolation.yml b/manifests/examples/builtins/interpolation/interpolation.yml similarity index 100% rename from manifests/plugins/interpolation/interpolation.yml rename to manifests/examples/builtins/interpolation/interpolation.yml diff --git a/manifests/plugins/mock-observations/failure-invalid-config-cpu-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-invalid-config-cpu-range.yml rename to manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml diff --git a/manifests/plugins/mock-observations/failure-invalid-memory-utilization-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-invalid-memory-utilization-range.yml rename to manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml diff --git a/manifests/plugins/mock-observations/failure-missing-timestamp-from-param.yml b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-missing-timestamp-from-param.yml rename to manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml diff --git a/manifests/plugins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml similarity index 95% rename from manifests/plugins/mock-observations/success.yml rename to manifests/examples/builtins/mock-observations/success.yml index ac1464322..941344fe4 100644 --- a/manifests/plugins/mock-observations/success.yml +++ b/manifests/examples/builtins/mock-observations/success.yml @@ -10,7 +10,7 @@ initialize: path: "builtin" global-config: timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 + timestamp-to: 2023-07-06T00:01 duration: 60 components: - cloud/instance-type: A1 diff --git a/manifests/plugins/multiply/failure-input-parameter-is-missing.yml b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml similarity index 100% rename from manifests/plugins/multiply/failure-input-parameter-is-missing.yml rename to manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml diff --git a/manifests/plugins/multiply/success-with-multiple-inputs.yml b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml similarity index 100% rename from manifests/plugins/multiply/success-with-multiple-inputs.yml rename to manifests/examples/builtins/multiply/success-with-multiple-inputs.yml diff --git a/manifests/plugins/multiply/success.yml b/manifests/examples/builtins/multiply/success.yml similarity index 100% rename from manifests/plugins/multiply/success.yml rename to manifests/examples/builtins/multiply/success.yml diff --git a/manifests/plugins/regex/failure-missing-input-param.yml b/manifests/examples/builtins/regex/failure-missing-input-param.yml similarity index 100% rename from manifests/plugins/regex/failure-missing-input-param.yml rename to manifests/examples/builtins/regex/failure-missing-input-param.yml diff --git a/manifests/plugins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml similarity index 100% rename from manifests/plugins/regex/failure-not-matching-with-regex.yml rename to manifests/examples/builtins/regex/failure-not-matching-with-regex.yml diff --git a/manifests/plugins/regex/success.yml b/manifests/examples/builtins/regex/success.yml similarity index 100% rename from manifests/plugins/regex/success.yml rename to manifests/examples/builtins/regex/success.yml diff --git a/manifests/plugins/sci-embodied/failure-invalid-default-emission-value.yml b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml similarity index 100% rename from manifests/plugins/sci-embodied/failure-invalid-default-emission-value.yml rename to manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml diff --git a/manifests/plugins/sci-embodied/failure-missing-expected-lifespan.yml b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml similarity index 100% rename from manifests/plugins/sci-embodied/failure-missing-expected-lifespan.yml rename to manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml diff --git a/manifests/plugins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml similarity index 100% rename from manifests/plugins/sci-embodied/success.yml rename to manifests/examples/builtins/sci-embodied/success.yml diff --git a/manifests/plugins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml similarity index 100% rename from manifests/plugins/sci/failure-invalid-config-value.yml rename to manifests/examples/builtins/sci/failure-invalid-config-value.yml diff --git a/manifests/plugins/sci/failure-missing-input-param.yml b/manifests/examples/builtins/sci/failure-missing-input-param.yml similarity index 65% rename from manifests/plugins/sci/failure-missing-input-param.yml rename to manifests/examples/builtins/sci/failure-missing-input-param.yml index 54514a8e5..44ced7374 100644 --- a/manifests/plugins/sci/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sci/failure-missing-input-param.yml @@ -8,13 +8,17 @@ initialize: kind: plugin method: Sci path: "builtin" - global-config: - functional-unit: requests + # global-config: + # functional-unit: requests tree: children: child: pipeline: - sci + config: + sci: + functional-unit-time: 1 sec + functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/plugins/sci/success.yml b/manifests/examples/builtins/sci/success.yml similarity index 79% rename from manifests/plugins/sci/success.yml rename to manifests/examples/builtins/sci/success.yml index cddfe5755..c7e6dbde6 100644 --- a/manifests/plugins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -16,6 +16,9 @@ tree: pipeline: - sci config: + sci: + functional-unit-time: 1 sec + functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/plugins/shell/failure-invalid-command.yml b/manifests/examples/builtins/shell/failure-invalid-command.yml similarity index 100% rename from manifests/plugins/shell/failure-invalid-command.yml rename to manifests/examples/builtins/shell/failure-invalid-command.yml diff --git a/manifests/plugins/shell/success.yml b/manifests/examples/builtins/shell/success.yml similarity index 100% rename from manifests/plugins/shell/success.yml rename to manifests/examples/builtins/shell/success.yml diff --git a/manifests/plugins/sum/failure-missing-input-param.yml b/manifests/examples/builtins/sum/failure-missing-input-param.yml similarity index 100% rename from manifests/plugins/sum/failure-missing-input-param.yml rename to manifests/examples/builtins/sum/failure-missing-input-param.yml diff --git a/manifests/plugins/sum/failure-missing-output-param.yml b/manifests/examples/builtins/sum/failure-missing-output-param.yml similarity index 100% rename from manifests/plugins/sum/failure-missing-output-param.yml rename to manifests/examples/builtins/sum/failure-missing-output-param.yml diff --git a/manifests/plugins/sum/success.yml b/manifests/examples/builtins/sum/success.yml similarity index 95% rename from manifests/plugins/sum/success.yml rename to manifests/examples/builtins/sum/success.yml index 454efc9e0..fc0661bf5 100644 --- a/manifests/plugins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -2,7 +2,7 @@ name: sum description: successful path tags: initialize: - # outputs: ['yaml'] + outputs: ['yaml'] plugins: sum: method: Sum diff --git a/manifests/plugins/time-sync/failure-config-start-later-end.yml b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml similarity index 100% rename from manifests/plugins/time-sync/failure-config-start-later-end.yml rename to manifests/examples/builtins/time-sync/failure-config-start-later-end.yml diff --git a/manifests/plugins/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml similarity index 100% rename from manifests/plugins/time-sync/failure-missing-global-config.yml rename to manifests/examples/builtins/time-sync/failure-missing-global-config.yml diff --git a/manifests/plugins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml similarity index 100% rename from manifests/plugins/time-sync/success.yml rename to manifests/examples/builtins/time-sync/success.yml diff --git a/manifests/examples/copy.yaml b/manifests/examples/copy.yaml deleted file mode 100644 index f2ee816e4..000000000 --- a/manifests/examples/copy.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: copy-param -description: -tags: -initialize: - plugins: - copy-param: - path: builtin - method: Copy - global-config: - keep-existing: true - from: original - to: copy -tree: - children: - child-1: - pipeline: - - copy-param - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - original: 'hello' diff --git a/manifests/examples/generics.yml b/manifests/examples/generics.yml deleted file mode 100644 index c319967f0..000000000 --- a/manifests/examples/generics.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: generics -description: a pipeline that does arbitrary calculations using our generic arithmetic builtins -tags: -initialize: - plugins: - "interpolate": - 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: 'cpu-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - "coefficient": - path: "builtin" - method: Coefficient - global-config: - input-parameter: cpu-energy-kwh - coefficient: 2 - output-parameter: energy-doubled - "multiply": - path: "builtin" - method: Multiply - global-config: - input-parameters: ["cpu/utilization", "duration"] - output-parameter: "cpu-times-duration" -tree: - children: - child-1: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - coefficient - - multiply - config: - defaults: - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 50 - network/energy: 10 - energy: 5 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - network/energy: 10 - energy: 5 diff --git a/manifests/bugs/initialize-error-no-plugins.yml b/manifests/examples/pipelines/basic.yml similarity index 63% rename from manifests/bugs/initialize-error-no-plugins.yml rename to manifests/examples/pipelines/basic.yml index 7c6bfad53..0f3dc7735 100644 --- a/manifests/bugs/initialize-error-no-plugins.yml +++ b/manifests/examples/pipelines/basic.yml @@ -1,9 +1,13 @@ -name: initialize-error-no-path -description: a negative test case that fails becuase no plugins are included in the initialize block +name: basic +description: a minimal manifest executing a single plugin on a single component for a single timestep tags: initialize: plugins: - outputs: ['yaml'] + teads-curve: + path: '@grnsft/if-unofficial-plugins' + method: TeadsCurve + global-config: + interpolation: spline tree: children: child-0: diff --git a/manifests/examples/pipelines/generics.yml b/manifests/examples/pipelines/generics.yml new file mode 100644 index 000000000..6492c9a3d --- /dev/null +++ b/manifests/examples/pipelines/generics.yml @@ -0,0 +1,45 @@ +name: generics +description: a pipeline that does arbitrary calculations using our generic arithmetic builtins +tags: +initialize: + plugins: + "sum": + path: "builtin" + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-sum + "coefficient": + path: "builtin" + method: Coefficient + global-config: + input-parameter: energy + coefficient: 2 + output-parameter: energy-doubled + "multiply": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["cpu/utilization", "duration"] + output-parameter: "cpu-times-duration" +tree: + children: + child-1: + pipeline: + - sum + - coefficient + - multiply + config: + defaults: + cpu/thermal-design-power: 100 + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + cpu/energy: 20 + network/energy: 10 + energy: 5 diff --git a/manifests/examples/instance-metadata.yml b/manifests/examples/pipelines/instance-metadata.yml similarity index 94% rename from manifests/examples/instance-metadata.yml rename to manifests/examples/pipelines/instance-metadata.yml index ea0998241..4ed443985 100644 --- a/manifests/examples/instance-metadata.yml +++ b/manifests/examples/pipelines/instance-metadata.yml @@ -1,6 +1,6 @@ name: csv-demo -description: -tags: +description: null +tags: null initialize: plugins: cloud-instance-metadata: @@ -19,8 +19,8 @@ initialize: parameter: cpu-model-name match: /^([^,])+/g output: cpu/name - # outputs: - # - yaml + outputs: + - yaml tree: children: child: diff --git a/manifests/examples/mock-cpu-util-to-carbon.yml b/manifests/examples/pipelines/mock-cpu-util-to-carbon.yml similarity index 85% rename from manifests/examples/mock-cpu-util-to-carbon.yml rename to manifests/examples/pipelines/mock-cpu-util-to-carbon.yml index 64e6d6719..35f7cea26 100644 --- a/manifests/examples/mock-cpu-util-to-carbon.yml +++ b/manifests/examples/pipelines/mock-cpu-util-to-carbon.yml @@ -21,14 +21,8 @@ initialize: global-config: interpolation: spline cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + method: CloudMetadata + path: "@grnsft/if-plugins" mock-observations: path: 'builtin' method: MockObservations diff --git a/manifests/examples/nesting.yml b/manifests/examples/pipelines/nesting.yml similarity index 71% rename from manifests/examples/nesting.yml rename to manifests/examples/pipelines/nesting.yml index 978510f48..e56e8bb18 100644 --- a/manifests/examples/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -7,62 +7,31 @@ tags: aggregation: metrics: - "carbon" + - "energy" type: "both" params: initialize: - # outputs: ['yaml'] + outputs: ['yaml'] plugins: - "interpolate": - method: Interpolation - path: 'builtin' + teads-curve: + path: "@grnsft/if-unofficial-plugins" + method: TeadsCurve 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-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide + interpolation: spline + sum: path: "builtin" + method: Sum global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy sci-embodied: path: "builtin" method: SciEmbodied - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon-operational" + sci-o: + path: "@grnsft/if-plugins" + method: SciO sci: path: "builtin" method: Sci @@ -93,17 +62,13 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 + resources-reserved: 1 + resources-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sum - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -143,17 +108,13 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 + resources-reserved: 1 + resources-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sum - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -195,17 +156,13 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 + resources-reserved: 1 + resources-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sum - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -245,17 +202,13 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-allocated: 1 - vcpus-total: 8 + resources-reserved: 1 + resources-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sum - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci diff --git a/manifests/examples/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml similarity index 54% rename from manifests/examples/pipeline-teads-sci.yml rename to manifests/examples/pipelines/pipeline-teads-sci.yml index c07b093bd..01c491cdc 100644 --- a/manifests/examples/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -3,57 +3,25 @@ description: a full pipeline seeded with some hardcoded input data and yielding tags: initialize: plugins: - "interpolate": - method: Interpolation - path: 'builtin' + "teads-curve": + path: "@grnsft/if-unofficial-plugins" + method: TeadsCurve 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-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide + interpolation: spline + "sum": path: "builtin" + method: Sum global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy "sci-embodied": path: "builtin" method: SciEmbodied - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon-operational" + "sci-o": + path: "@grnsft/if-plugins" + method: SciO "sci": path: "builtin" method: Sci @@ -79,14 +47,10 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sum - sci-embodied - - operational-carbon + - sci-o - sum-carbon - sci config: @@ -96,8 +60,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-total: 8 - vcpus-allocated: 1 + resources-reserved: 1 + resources-total: 8 component: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" diff --git a/manifests/examples/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml similarity index 61% rename from manifests/examples/pipeline-with-aggregate.yml rename to manifests/examples/pipelines/pipeline-with-aggregate.yml index 73203676b..bd3e637ac 100644 --- a/manifests/examples/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -7,62 +7,25 @@ aggregation: type: "both" initialize: plugins: - "interpolate": - method: Interpolation - path: 'builtin' + "teads-curve": + path: "@grnsft/if-unofficial-plugins" + method: TeadsCurve 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-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh + interpolation: spline + "sci-e": + path: "@grnsft/if-plugins" + method: SciE "sci-embodied": path: "builtin" method: SciEmbodied - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon-operational" + "sci-o": + path: "@grnsft/if-plugins" + method: SciO "sci": path: "builtin" method: Sci global-config: - functional-unit: requests # factor to convert per time to per f.unit + functional-unit: "requests" "sum-carbon": path: "builtin" method: Sum @@ -79,18 +42,17 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true + "group-by": + path: builtin + method: GroupBy tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sci-e - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -105,8 +67,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-total: 8 - vcpus-allocated: 1 + resources-reserved: 1 + resources-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -134,14 +96,10 @@ tree: requests: 30 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sci-e - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -156,8 +114,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-total: 8 - vcpus-allocated: 1 + resources-reserved: 1 + resources-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/examples/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml similarity index 65% rename from manifests/examples/pipeline-with-mocks.yml rename to manifests/examples/pipelines/pipeline-with-mocks.yml index 168ebd7fe..008e319b1 100644 --- a/manifests/examples/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -25,57 +25,20 @@ initialize: cpu/utilization: min: 1 max: 99 - "interpolate": - method: Interpolation - path: 'builtin' + "teads-curve": + path: "@grnsft/if-unofficial-plugins" + method: TeadsCurve 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-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh + interpolation: spline + "sci-e": + path: "@grnsft/if-plugins" + method: SciE "sci-embodied": path: "builtin" method: SciEmbodied - "operational-carbon": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] - output-parameter: "carbon-operational" + "sci-o": + path: "@grnsft/if-plugins" + method: SciO "sum-carbon": path: "builtin" method: Sum @@ -105,14 +68,10 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sci-e - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -127,8 +86,9 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-total: 8 - vcpus-allocated: 1 + resources-reserved: 1 + resources-total: 8 + functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -156,14 +116,10 @@ tree: requests: 50 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + - teads-curve + - sci-e - sci-embodied - - operational-carbon + - sci-o - sum-carbon - time-sync - sci @@ -178,8 +134,9 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - vcpus-total: 8 - vcpus-allocated: 1 + resources-reserved: 1 + resources-total: 8 + functional-unit-time: "1 min" inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/examples/sci.yml b/manifests/examples/pipelines/sci.yml similarity index 100% rename from manifests/examples/sci.yml rename to manifests/examples/pipelines/sci.yml diff --git a/manifests/examples/teads-curve.yml b/manifests/examples/pipelines/teads-curve.yml similarity index 100% rename from manifests/examples/teads-curve.yml rename to manifests/examples/pipelines/teads-curve.yml diff --git a/manifests/examples/region-metadata.yml b/manifests/examples/region-metadata.yml deleted file mode 100644 index d43b5bc65..000000000 --- a/manifests/examples/region-metadata.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: csv-demo -description: -tags: -initialize: - plugins: - cloud-region-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: cloud-provider - cloud-region: cloud-region - output: "*" -tree: - children: - child: - pipeline: - - cloud-region-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - instance-id: AMD A10-9700 - cloud-provider: "Google Cloud" - cloud-region: "asia-east1" diff --git a/manifests/examples/tdp-finder.yml b/manifests/examples/tdp-finder.yml deleted file mode 100644 index 5ce1b5903..000000000 --- a/manifests/examples/tdp-finder.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: csv-demo -description: -tags: -initialize: - plugins: - tdp-finder: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv - query: - name: instance-id - output: "tdp" -tree: - children: - child: - pipeline: - - tdp-finder - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - instance-id: "AMD A10-9700" diff --git a/manifests/examples/zeros.yaml b/manifests/examples/zeros.yaml deleted file mode 100644 index da5541789..000000000 --- a/manifests/examples/zeros.yaml +++ /dev/null @@ -1,130 +0,0 @@ -name: generics -description: a pipeline that does arbitrary calculations using our generic arithmetic builtins -tags: -initialize: - plugins: - "sum-zero-and-one": - path: "builtin" - method: Sum - global-config: - input-parameters: - - some-value - - zero-value - output-parameter: one-plus-zero - "sum-zero-and-zero": - path: "builtin" - method: Sum - global-config: - input-parameters: - - zero-value - - zero-value - output-parameter: zero-plus-zero - "subtract-one-and-zero": - path: "builtin" - method: Subtract - global-config: - input-parameters: - - some-value - - zero-value - output-parameter: one-minus-zero - "subtract-zero-and-zero": - path: "builtin" - method: Sum - global-config: - input-parameters: - - zero-value - - zero-value - output-parameter: zero-minus-zero - "subtract-zero-and-one": - path: "builtin" - method: Subtract - global-config: - input-parameters: - - zero-value - - some-value - output-parameter: zero-minus-one - "coefficient-one-times-zero": - path: "builtin" - method: Coefficient - global-config: - input-parameter: zero-value - coefficient: 1 - output-parameter: zero-times-one-coefficient - "coefficient-zero-times-one": - path: "builtin" - method: Coefficient - global-config: - input-parameter: some-value - coefficient: 0 - output-parameter: one-times-zero-coefficient - "coefficient-zero-times-zero": - path: "builtin" - method: Coefficient - global-config: - input-parameter: zero-value - coefficient: 0 - output-parameter: zero-times-zero-coefficient - "multiply-one-times-zero": - path: "builtin" - method: Multiply - global-config: - input-parameters: ["some-value", "zero-value"] - output-parameter: "one-times-zero" - "multiply-zero-times-one": - path: "builtin" - method: Multiply - global-config: - input-parameters: ["zero-value", "zero-value"] - output-parameter: "zero-times-one" - exponent-one-to-zero: - method: Exponent - path: 'builtin' - global-config: - input-parameter: 'some-value' - exponent: 0 - output-parameter: 'one-raised-to-zero-power' - exponent-zero-to-zero: - method: Exponent - path: 'builtin' - global-config: - input-parameter: 'zero-value' - exponent: 0 - output-parameter: 'zero-raised-to-zero-power' - exponent-zero-to-one: - method: Exponent - path: 'builtin' - global-config: - input-parameter: 'zero-value' - exponent: 1 - output-parameter: 'zero-raised-to-first-power' - "sci": - path: "builtin" - method: Sci - global-config: - functional-unit: "zero-value" -tree: - children: - child-1: - pipeline: - - sum-zero-and-one - - sum-zero-and-zero - - subtract-one-and-zero - - subtract-zero-and-zero - - subtract-zero-and-one - - coefficient-one-times-zero - - coefficient-zero-times-one - - coefficient-zero-times-zero - - multiply-one-times-zero - - multiply-zero-times-one - - exponent-one-to-zero - - exponent-zero-to-one - - exponent-zero-to-zero - - sci - config: - defaults: - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - some-value: 1 - zero-value: 0 - carbon: 10 diff --git a/manifests/features/aggregate-failure-invalid-metrics.yml b/manifests/features/aggregate-failure-invalid-metrics.yml deleted file mode 100644 index 7e4692509..000000000 --- a/manifests/features/aggregate-failure-invalid-metrics.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Aggregation -description: Fails with invalid metric. -aggregation: - metrics: - - 'test' - type: 'both' -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 diff --git a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml b/manifests/features/aggregate-failure-missing-metric-in-inputs.yml deleted file mode 100644 index eeff85290..000000000 --- a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Aggregation -description: Fails with missing metric in inputs. -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-01-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - # cpu/utilization: 110 - - timestamp: '2024-02-26 00:15:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 diff --git a/manifests/features/aggregate-horizontal.yml b/manifests/features/aggregate-horizontal.yml deleted file mode 100644 index 8003c4214..000000000 --- a/manifests/features/aggregate-horizontal.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Aggregation -description: Apply `horizontal` aggregation -aggregation: - metrics: - - 'cpu/utilization' - type: 'horizontal' -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/features/aggregate-vertical.yml b/manifests/features/aggregate-vertical.yml deleted file mode 100644 index 6308a01d0..000000000 --- a/manifests/features/aggregate-vertical.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Aggregation -description: Apply `vertical` aggregation -aggregation: - metrics: - - 'cpu/utilization' - type: 'vertical' -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/features/aggregate.yml b/manifests/features/aggregate.yml deleted file mode 100644 index 04672cf38..000000000 --- a/manifests/features/aggregate.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/integrations/cloud-metadata-divide.yml b/manifests/integrations/cloud-metadata-divide.yml deleted file mode 100644 index 032206474..000000000 --- a/manifests/integrations/cloud-metadata-divide.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: divide-demo -description: -tags: -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] - divide: - method: Divide - path: "builtin" - global-config: - numerator: vcpus-allocated - denominator: 2 - output: cpu/number-cores -tree: - children: - child: - pipeline: - - cloud-metadata - - divide - config: - divide: - defaults: - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 diff --git a/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml b/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml deleted file mode 100644 index 810dee072..000000000 --- a/manifests/integrations/instance-metadata/failure-invalid-instance-type.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: instance-metadata -description: -tags: -initialize: - plugins: - cloud-instance-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: "cloud/instance-type" - output: "*" - extract-processor-name: - method: Regex - path: "builtin" - global-config: - parameter: cpu-model-name - match: /^([^,])+/g - output: cpu/name -tree: - children: - child: - pipeline: - - cloud-instance-metadata - - extract-processor-name - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - cloud/provider: gcp - cloud/region: asia-east - cloud/instance-type: m6 \ No newline at end of file diff --git a/manifests/integrations/instance-metadata/failure-invalid-provider.yaml b/manifests/integrations/instance-metadata/failure-invalid-provider.yaml deleted file mode 100644 index a362132e7..000000000 --- a/manifests/integrations/instance-metadata/failure-invalid-provider.yaml +++ /dev/null @@ -1,33 +0,0 @@ -name: instance-metadata -description: -tags: -initialize: - plugins: - cloud-instance-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: "cloud/provider" - output: "*" - extract-processor-name: - method: Regex - path: "builtin" - global-config: - parameter: cpu-model-name - match: /^([^,])+/g - output: cpu/name -tree: - children: - child: - pipeline: - - cloud-instance-metadata - - extract-processor-name - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - cloud/provider: 6568 - cloud/region: asia-east - cloud/instance-type: Standard_A1_v2 diff --git a/manifests/integrations/instance-metadata/failure-missing-queried-input.yml b/manifests/integrations/instance-metadata/failure-missing-queried-input.yml deleted file mode 100644 index 37f4001ae..000000000 --- a/manifests/integrations/instance-metadata/failure-missing-queried-input.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: instance-metadata -description: -tags: -initialize: - plugins: - cloud-instance-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: "cloud/provider" - output: "*" - extract-processor-name: - method: Regex - path: "builtin" - global-config: - parameter: cpu-model-name - match: /^([^,])+/g - output: cpu/name -tree: - children: - child: - pipeline: - - cloud-instance-metadata - - extract-processor-name - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - # cloud/provider: gcp - cloud/region: asia-east - cloud/instance-type: Standard_A1_v2 \ No newline at end of file diff --git a/manifests/integrations/instance-metadata/success.yml b/manifests/integrations/instance-metadata/success.yml deleted file mode 100644 index d95115896..000000000 --- a/manifests/integrations/instance-metadata/success.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: instance-metadata -description: -tags: -initialize: - plugins: - cloud-instance-metadata: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: "cloud/instance-type" - output: "*" - extract-processor-name: - method: Regex - path: "builtin" - global-config: - parameter: cpu-model-name - match: /^([^,])+/g - output: cpu/name -tree: - children: - child: - pipeline: - - cloud-instance-metadata - - extract-processor-name - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - cloud/provider: gcp - cloud/region: asia-east - cloud/instance-type: Standard_A1_v2 \ No newline at end of file diff --git a/manifests/integrations/mock-obs-group-by-cloud-meta.yml b/manifests/integrations/mock-obs-group-by-cloud-meta.yml deleted file mode 100644 index 6b6196cab..000000000 --- a/manifests/integrations/mock-obs-group-by-cloud-meta.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: My Manifest File -description: integration of mock observations, group by and cloud metadata -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - # outputs: ['yaml'] - plugins: - group-by: - path: 'builtin' - method: GroupBy - global-config: - input-parameters: ['cpu/energy', 'grid/carbon-intensity'] - output-parameter: 'carbon' - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-tdp'] - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: 2024-03-05T00:00 - timestamp-to: 2024-03-05T01:00 - duration: 300 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 -tree: - pipeline: - - mock-observations - - group-by - - cloud-metadata - config: - group-by: - group: - - name - - cloud/instance-type - inputs: null diff --git a/manifests/integrations/mock-obs-groupby.yml b/manifests/integrations/mock-obs-groupby.yml deleted file mode 100644 index 39c37e2c8..000000000 --- a/manifests/integrations/mock-obs-groupby.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Mock observations + Group by -description: Integration of `mock observations` + `groupby plugins` -initialize: - plugins: - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - group-by: - path: 'builtin' - method: GroupBy -tree: - pipeline: - - mock-observations - - group-by - defaults: - config: - group-by: - group: - - cloud/region - - name - inputs: null diff --git a/manifests/integrations/mock-obs-time-sync.yml b/manifests/integrations/mock-obs-time-sync.yml deleted file mode 100644 index f1f176eb3..000000000 --- a/manifests/integrations/mock-obs-time-sync.yml +++ /dev/null @@ -1,110 +0,0 @@ -name: Mock observation and time sync integration -description: Integration of `mock observation` + `time sync` -tags: -initialize: - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: "builtin" - global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 60 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - "interpolate": - 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: 'cpu-factor' - "cpu-factor-to-wattage": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-factor", "cpu/thermal-design-power"] - output-parameter: "cpu-wattage" - "wattage-times-duration": - method: Multiply - path: builtin - global-config: - input-parameters: ["cpu-wattage", "duration"] - output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": - method: Divide - path: "builtin" - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - "calculate-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - "correct-cpu-energy-for-vcpu-ratio": - method: Divide - path: "builtin" - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true -tree: - children: - child-1: - pipeline: - # - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - time-sync - defaults: - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml new file mode 100644 index 000000000..fc0ac48b0 --- /dev/null +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -0,0 +1,243 @@ +name: aggregation-error-wrong-metric +description: >- + a negative test case that fails due to the aggregation feature being passed an + incorrect metric +tags: null +aggregation: + metrics: + - dummy-param + type: both +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor + cpu-factor-to-wattage: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + method: Divide + path: builtin + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + time-sync: + method: TimeSync + path: builtin + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/aggregation-error-wrong-metric.yml -o + manifests/outputs/bugs/aggregation-error-wrong-metric + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:25:34.759Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric dummy-param is not found in + inputs[0]. +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 100 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml new file mode 100644 index 000000000..9d3c21a68 --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-config.yaml @@ -0,0 +1,81 @@ +name: initialize-error-no-config +description: >- + a negative test case that fails due to plugin initialization missing some + required config +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + method: Interpolation + path: builtin + global-config: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-config.yml -o + manifests/outputs/bugs/initialize-error-no-config + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:45:41.936Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.interpolate.global-config" + parameter is expected object, received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml new file mode 100644 index 000000000..77483ac27 --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-path.yaml @@ -0,0 +1,94 @@ +name: initialize-error-no-path +description: >- + a negative test case that fails because the path is mising in a plugin + initialization +tags: null +initialize: + plugins: + interpolate: + method: Interpolation + path: null + 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-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-path.yml -o + manifests/outputs/bugs/initialize-error-no-path + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:57:11.499Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.interpolate.path" parameter is + expected string, received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml new file mode 100644 index 000000000..0324550ee --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-plugins.yaml @@ -0,0 +1,77 @@ +name: initialize-error-no-path +description: >- + a negative test case that fails becuase no plugins are included in the + initialize block +tags: null +initialize: + plugins: null + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-plugins.yml -o + manifests/outputs/bugs/initialize-error-no-plugins + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:52:35.214Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins" parameter is expected object, + received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - teads-curve + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml new file mode 100644 index 000000000..7a9a53b8e --- /dev/null +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -0,0 +1,87 @@ +name: input-error-missing-duration +description: >- + a negative test case that fails due to the required `duration` field being + omitted from input data +tags: null +initialize: + plugins: + interpolate: + 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: cpu-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/input-error-missing-duration.yml -o + manifests/outputs/bugs/input-error-missing-duration + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:59:58.987Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "duration" parameter is required at index 0. Error + code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml new file mode 100644 index 000000000..6af109ec0 --- /dev/null +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -0,0 +1,84 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 0 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yml -o + manifests/outputs/bugs/mock-observations-failure-duration-is-zero + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:02:22.596Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'RangeError: Maximum call stack size exceeded' +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml new file mode 100644 index 000000000..b7885a361 --- /dev/null +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -0,0 +1,94 @@ +name: pipeline-error-naming-mismatch +description: >- + a negative test case that fails due to the plugin name in the pipeline not + matching the name given in initialize +tags: null +initialize: + plugins: + interpolate: + 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: cpu-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-error-naming-mismatch.yml -o + manifests/outputs/bugs/pipeline-error-naming-mismatch + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:06:51.254Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + PluginInitializationError: Not initalized plugin: wrong-name. Check if + wrong-name is in 'manifest.initalize.plugins'. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - wrong-name + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml new file mode 100644 index 000000000..75d87e3be --- /dev/null +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -0,0 +1,95 @@ +name: pipeline-uninitialized-plugin-error +description: >- + a negative test case that fails due to an uninitialized plugin being invoked + in a pipeline +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yml -o + manifests/outputs/bugs/pipeline-error-uninitialized-plugin + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:08:51.260Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + PluginInitializationError: Not initalized plugin: multiply. Check if + multiply is in 'manifest.initalize.plugins'. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + - multiply + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml new file mode 100644 index 000000000..c167f5e39 --- /dev/null +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -0,0 +1,158 @@ +name: pipeline-ordering-error +description: >- + a negative test case that fails because sci-o is invoked too early in the + pipeline (before its inputs are generated) +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor + cpu-factor-to-wattage: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + method: Divide + path: builtin + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-ordering-error.yml -o + manifests/outputs/bugs/pipeline-ordering-error + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:14:29.109Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu-energy-raw" parameter is required. Error code: + invalid_type. +tree: + children: + child-1: + pipeline: + - interpolate + - correct-cpu-energy-for-vcpu-ratio + - calculate-vcpu-ratio + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + config: null + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml new file mode 100644 index 000000000..add3499be --- /dev/null +++ b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml @@ -0,0 +1,76 @@ +name: sci-embodied +description: >- + receiving incorrect error message when running sci-embodied without + `resources-total` issue +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/sci-embodied-missing-resources-total.yml -o + manifests/outputs/bugs/sci-embodied-missing-resources-total + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:17:30.390Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "vcpus-allocated" parameter is required. Error code: + invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml new file mode 100644 index 000000000..a332f8476 --- /dev/null +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -0,0 +1,104 @@ +name: Aggregation +description: Fails with invalid metric. +aggregation: + metrics: + - test + type: both +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-failure-invalid-metrics.yml -o + manifests/outputs/features/aggregate-failure-invalid-metrics + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:25:17.348Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric test is not found in + inputs[0]. +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml new file mode 100644 index 000000000..2aeb03fab --- /dev/null +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -0,0 +1,103 @@ +name: Aggregation +description: Fails with missing metric in inputs. +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yml -o + manifests/outputs/features/aggregate-failure-missing-metric-in-inputs + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:26:58.250Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric cpu/utilization is not + found in inputs[0]. +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-01-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + - timestamp: '2024-02-26 00:15:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml new file mode 100644 index 000000000..b0ee17210 --- /dev/null +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -0,0 +1,131 @@ +name: Aggregation +description: Apply `horizontal` aggregation +aggregation: + metrics: + - cpu/utilization + type: horizontal +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-horizontal.yml -o + manifests/outputs/features/aggregate-horizontal + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:28:27.168Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 74 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 25.5 diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml new file mode 100644 index 000000000..5a7695520 --- /dev/null +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -0,0 +1,154 @@ +name: Aggregation +description: Apply `vertical` aggregation +aggregation: + metrics: + - cpu/utilization + type: vertical +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-vertical.yml -o + manifests/outputs/features/aggregate-vertical + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:32:47.459Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml new file mode 100644 index 000000000..91ef6a671 --- /dev/null +++ b/manifests/outputs/features/aggregate.yaml @@ -0,0 +1,158 @@ +name: Aggregation +description: Apply both `horizontal` and `vertical` aggregations +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate.yml -o + manifests/outputs/features/aggregate + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:34:35.981Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 74 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 25.5 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml new file mode 100644 index 000000000..4b1f0ebba --- /dev/null +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -0,0 +1,98 @@ +name: divide-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/cloud-metadata-divide.yml -o + manifests/outputs/pipelines/cloud-metadata-divide + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:13:05.868Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml new file mode 100644 index 000000000..81f4ee71b --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml @@ -0,0 +1,648 @@ +name: My Manifest File +description: integration of mock observations, group by and cloud metadata +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + plugins: + group-by: + path: builtin + method: GroupBy + global-config: + input-parameters: + - cpu/energy + - grid/carbon-intensity + output-parameter: carbon + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-tdp + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2024-03-05T00:00 + timestamp-to: 2024-03-05T01:00 + duration: 300 + components: + - name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + - name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + generators: + common: + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + randint: + cpu/utilization: + min: 1 + max: 99 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yml -o + manifests/outputs/pipelines/mock-obs-group-by-cloud-meta + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:21:45.561Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + pipeline: + - mock-observations + - group-by + - cloud-metadata + config: + group-by: + group: + - name + - cloud/instance-type + children: + server-1: + children: + Standard_E64_v3: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 93 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 3 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 83 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 8 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 59 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 55 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 52 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 54 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 93 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 3 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 83 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 8 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 59 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 55 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 52 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 54 + cpu-tdp: 270 + aggregated: + cpu/utilization: 49.083333333333336 + outputs: + - cpu/utilization: 93 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 6 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 6 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 3 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 83 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 85 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 8 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 59 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 55 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 85 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 52 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 54 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 49.083333333333336 + server-2: + children: + Standard_E64_v3: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 4 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 38 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 10 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 88 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 17 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 11 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 76 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 74 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 4 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 38 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 10 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 88 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 17 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 11 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 76 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 74 + cpu-tdp: 270 + aggregated: + cpu/utilization: 50.5 + outputs: + - cpu/utilization: 4 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 63 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 38 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 10 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 88 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 81 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 17 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 11 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 76 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 63 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 81 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 74 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 50.5 + outputs: + - cpu/utilization: 48.5 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 34.5 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 22 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 6.5 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 85.5 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 83 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 12.5 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 35 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 65.5 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 74 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 66.5 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 64 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 49.791666666666664 diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml new file mode 100644 index 000000000..29b5aff0a --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-groupby.yaml @@ -0,0 +1,181 @@ +name: Mock observations + Group by +description: Integration of `mock observations` + `groupby plugins` +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: '2024-03-05T00:00:00.000Z' + timestamp-to: '2024-03-05T00:01:00.000Z' + duration: 10 + components: + - name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + - name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + generators: + common: + cloud/vendor: azure + randint: + cpu/utilization: + min: 1 + max: 99 + group-by: + path: builtin + method: GroupBy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-groupby.yml -o + manifests/outputs/pipelines/mock-obs-groupby + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:27:34.757Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + pipeline: + - mock-observations + - group-by + defaults: null + config: + group-by: + group: + - cloud/region + - name + children: + westus3: + children: + server-1: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 12 + - timestamp: '2024-03-05T00:00:10.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 71 + - timestamp: '2024-03-05T00:00:20.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 75 + - timestamp: '2024-03-05T00:00:30.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 39 + - timestamp: '2024-03-05T00:00:40.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 42 + - timestamp: '2024-03-05T00:00:50.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 98 + france: + children: + server-2: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 14 + - timestamp: '2024-03-05T00:00:10.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 80 + - timestamp: '2024-03-05T00:00:20.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 53 + - timestamp: '2024-03-05T00:00:30.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 10 + - timestamp: '2024-03-05T00:00:40.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 40 + - timestamp: '2024-03-05T00:00:50.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 92 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml new file mode 100644 index 000000000..54c411b96 --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -0,0 +1,353 @@ +name: Mock observation and time sync integration +description: Integration of `mock observation` + `time sync` +tags: null +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-time-sync.yml -o + manifests/outputs/pipelines/mock-obs-time-sync + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:29:47.787Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - time-sync + defaults: + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: 14 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.662 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000007048611111111113 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 + cpu/thermal-design-power: 60 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 diff --git a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml new file mode 100644 index 000000000..6f3e5cb23 --- /dev/null +++ b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml @@ -0,0 +1,76 @@ +name: coefficient-demo +description: failure with ivalid `global-config.input-parameter` +tags: null +initialize: + outputs: + - yaml + plugins: + coefficient: + method: Coefficient + path: builtin + global-config: + input-parameter: 4 + coefficient: 3 + output-parameter: carbon-product +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yml + -o manifests/outputs/plugins/coefficient/failure-invalid-config-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:41:49.144Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "input-parameter" parameter is expected string, + received number. Error code: invalid_type. +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 diff --git a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml new file mode 100644 index 000000000..67ac62cff --- /dev/null +++ b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml @@ -0,0 +1,76 @@ +name: coefficient-demo +description: value of output-param is missing +tags: null +initialize: + outputs: + - yaml + plugins: + coefficient: + method: Coefficient + path: builtin + global-config: + input-parameter: carbon + coefficient: 3 + output-parameter: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/failure-output-param-is-null.yml -o + manifests/outputs/plugins/coefficient/failure-output-param-is-null + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:38:48.831Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output-parameter" parameter is expected string, + received null. Error code: invalid_type. +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 diff --git a/manifests/outputs/plugins/coefficient/success.yaml b/manifests/outputs/plugins/coefficient/success.yaml new file mode 100644 index 000000000..edf264092 --- /dev/null +++ b/manifests/outputs/plugins/coefficient/success.yaml @@ -0,0 +1,78 @@ +name: coefficient-demo +description: successful path +tags: null +initialize: + plugins: + coefficient: + path: builtin + method: Coefficient + global-config: + input-parameter: carbon + coefficient: 3 + output-parameter: carbon-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/success.yml -o + manifests/outputs/plugins/coefficient/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:37:08.297Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 + carbon-product: 90 diff --git a/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml similarity index 100% rename from manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml rename to manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml diff --git a/manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml similarity index 100% rename from manifests/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml rename to manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml new file mode 100644 index 000000000..5cbc23dec --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -0,0 +1,80 @@ +name: cloud-metadata +description: failing because cloud/vendor is not provided +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml + -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:20:08.333Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - cloud-metadata + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 100 + cpu/utilization: 10 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml new file mode 100644 index 000000000..4b02a939b --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -0,0 +1,85 @@ +name: cloud-metadata +description: successful path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yml -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:21:45.504Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + config: null + inputs: + - timestamp: 2023-07-06T00:00 + cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 + outputs: + - timestamp: 2023-07-06T00:00 + cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 + vcpus-allocated: 2 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml new file mode 100644 index 000000000..0826f4fa2 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -0,0 +1,79 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: nonexistant + cloud-region: cloud/region + output: '*' +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yml + -o + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:26:59.352Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml new file mode 100644 index 000000000..57cfb9358 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -0,0 +1,78 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yml + -o + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:26:09.874Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output" parameter is invalid input. Error code: + invalid_union. +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml new file mode 100644 index 000000000..408a9d3dc --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml @@ -0,0 +1,83 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: + - em-zone-id + - renamed-em-zone-data + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yml -o + manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:24:10.894Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + renamed-em-zone-data: TW diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml new file mode 100644 index 000000000..aa1f3de32 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml @@ -0,0 +1,95 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: '*' + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/success.yml -o + manifests/outputs/plugins/csv-lookup/region-metadata/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:23:15.965Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + year: 2022 + cfe-region: Taiwan + em-zone-id: TW + wt-region-id: TW + location: Taiwan + geolocation: 25.0375,121.5625 + cfe-hourly: 0.18 + cfe-annual: nan + power-usage-efficiency: nan + net-carbon: 0 + grid-carbon-intensity-24x7: 453 + grid-carbon-intensity-consumption: nan + grid-carbon-intensity-marginal: nan + grid-carbon-intensity-production: nan + grid-carbon-intensity: 453 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml new file mode 100644 index 000000000..7406ac879 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -0,0 +1,77 @@ +name: tdp-finder +description: failure with `inputs` missing `physical-processor` param +tags: null +initialize: + outputs: + - yaml + plugins: + tdp-finder: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml + -o + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:30:11.973Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml new file mode 100644 index 000000000..0d4bff834 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -0,0 +1,78 @@ +name: tdp-finder +description: successful path +tags: null +initialize: + outputs: + - yaml + plugins: + tdp-finder: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml + -o + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:29:16.211Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 302 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml new file mode 100644 index 000000000..e3dd6e9eb --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml @@ -0,0 +1,79 @@ +name: tdp-finder +description: successful path +tags: null +initialize: + plugins: + tdp-finder: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/success.yml -o + manifests/outputs/plugins/csv-lookup/tdp-finder/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:28:19.790Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e + outputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e + tdp: 6 diff --git a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml new file mode 100644 index 000000000..1f70d83c8 --- /dev/null +++ b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml @@ -0,0 +1,76 @@ +name: divide +description: failure when `global-config.denominator` is string +tags: null +initialize: + outputs: + - yaml + plugins: + divide: + method: Divide + path: builtin + global-config: + numerator: cpu/utilization + denominator: test + output: cpu/divided-two +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml -o + manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T06:02:25.409Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingInputDataError: test is missing from the input array, or has nullish + value. +tree: + children: + child: + pipeline: + - divide + config: + divide: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 diff --git a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml new file mode 100644 index 000000000..065bc9a55 --- /dev/null +++ b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml @@ -0,0 +1,80 @@ +name: divide +description: success path +tags: null +initialize: + outputs: + - yaml + plugins: + divide: + method: Divide + path: builtin + global-config: + denominator: 2 + output: cpu/number-cores +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-missing-numerator.yml -o + manifests/outputs/plugins/divide/failure-missing-numerator + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:49:51.802Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "numerator" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + vcpus-allocated: 8 diff --git a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml new file mode 100644 index 000000000..9c333a41e --- /dev/null +++ b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml @@ -0,0 +1,98 @@ +name: divide +description: denominator is invalid, denominator is +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 0 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-denominator-equal-zero.yml -o + manifests/outputs/plugins/divide/failure-denominator-equal-zero + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T06:05:58.040Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 2 diff --git a/manifests/outputs/plugins/divide/success.yaml b/manifests/outputs/plugins/divide/success.yaml new file mode 100644 index 000000000..42e60482c --- /dev/null +++ b/manifests/outputs/plugins/divide/success.yaml @@ -0,0 +1,98 @@ +name: divide +description: success path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/success.yml -o + manifests/outputs/plugins/divide/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:43:34.055Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/plugins/exponent/success.yaml b/manifests/outputs/plugins/exponent/success.yaml new file mode 100644 index 000000000..1afa27f5a --- /dev/null +++ b/manifests/outputs/plugins/exponent/success.yaml @@ -0,0 +1,80 @@ +name: exponent demo +description: null +tags: null +initialize: + plugins: + exponent: + path: builtin + method: Exponent + global-config: + input-parameter: cpu/energy + exponent: 2 + output-parameter: energy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/exponent/success.yml -o + manifests/outputs/plugins/exponent/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:07:19.737Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - exponent + config: + exponent: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + energy: 0.000001 diff --git a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml new file mode 100644 index 000000000..e211b0d51 --- /dev/null +++ b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml @@ -0,0 +1,99 @@ +name: groupby +description: failure when `config->group-by->group` is not an array +initialize: + outputs: + - yaml + plugins: + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-invalid-config-group.yml -o + manifests/outputs/plugins/groupby/failure-invalid-config-group + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:11:23.166Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "group" parameter is expected array, received string. + Error code: invalid_type. +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: cloud/region + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml new file mode 100644 index 000000000..38cebb9bb --- /dev/null +++ b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml @@ -0,0 +1,98 @@ +name: groupby +description: null +initialize: + outputs: + - yaml + plugins: + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yml -o + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:10:00.820Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InvalidGroupingError: Invalid group cloud/instance-type.' +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: + - cloud/region + - cloud/instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml new file mode 100644 index 000000000..cf1c7f734 --- /dev/null +++ b/manifests/outputs/plugins/groupby/success.yaml @@ -0,0 +1,104 @@ +name: groupby +description: successful path +initialize: + plugins: + group-by: + path: builtin + method: GroupBy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/success.yml -o + manifests/outputs/plugins/groupby/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:08:31.858Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: + - cloud/region + - cloud/instance-type + children: + uk-west: + children: + A1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + B1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/interpolation/interpolation.yaml b/manifests/outputs/plugins/interpolation/interpolation.yaml new file mode 100644 index 000000000..08036cf0b --- /dev/null +++ b/manifests/outputs/plugins/interpolation/interpolation.yaml @@ -0,0 +1,86 @@ +name: interpolation-demo +description: simple demo of interpolation plugin +tags: null +initialize: + plugins: + interpolation: + path: builtin + method: Interpolation + 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 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/interpolation/interpolation.yml -o + manifests/outputs/plugins/interpolation/interpolation + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:14:18.033Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + result: 0.69625 diff --git a/manifests/outputs/plugins/interpolation/success.yaml b/manifests/outputs/plugins/interpolation/success.yaml new file mode 100644 index 000000000..5c81f15fa --- /dev/null +++ b/manifests/outputs/plugins/interpolation/success.yaml @@ -0,0 +1,86 @@ +name: interpolation-demo +description: simple demo of interpolation plugin +tags: null +initialize: + plugins: + interpolation: + path: builtin + method: Interpolation + 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 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/interpolation/success.yml -o + manifests/outputs/plugins/interpolation/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:13:22.946Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + result: 0.69625 diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml new file mode 100644 index 000000000..ebf62b776 --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -0,0 +1,89 @@ +name: mock-observation-demo +description: >- + failure with `global-config->generators->randint->cpu/utilization->min` is + greater than `max` +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 99 + max: 10 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yml + -o + manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:19:22.233Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + GlobalConfigError: Min value should not be greater than or equal to max + value of cpu/utilization +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml new file mode 100644 index 000000000..72d1cf9d0 --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -0,0 +1,87 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 99 + max: 10 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yml + -o + manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:18:11.486Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + GlobalConfigError: Min value should not be greater than or equal to max + value of memory/utilization +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml new file mode 100644 index 000000000..ab340d36c --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -0,0 +1,86 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yml + -o + manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:17:01.277Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "timestamp-from" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/plugins/mock-observations/success.yaml new file mode 100644 index 000000000..1a89eea75 --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/success.yaml @@ -0,0 +1,223 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/success.yml -o + manifests/outputs/plugins/mock-observations/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:15:43.108Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - mock-observations + inputs: null + outputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 81 + memory/utilization: 63 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 92 + memory/utilization: 63 + - timestamp: '2023-07-06T00:02:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 63 + memory/utilization: 95 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 37 + memory/utilization: 13 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 28 + memory/utilization: 50 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 98 + memory/utilization: 29 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 10 + memory/utilization: 93 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 84 + memory/utilization: 37 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 10 + memory/utilization: 30 + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 50 + memory/utilization: 10 + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 97 + memory/utilization: 89 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 61 + memory/utilization: 83 + - timestamp: '2023-07-06T00:02:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 86 + memory/utilization: 52 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 17 + memory/utilization: 60 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 53 + memory/utilization: 84 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 38 + memory/utilization: 58 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 4 + memory/utilization: 39 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 89 + memory/utilization: 52 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 38 + memory/utilization: 16 + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 25 + memory/utilization: 78 diff --git a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml new file mode 100644 index 000000000..23594fbf9 --- /dev/null +++ b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml @@ -0,0 +1,78 @@ +name: multiply +description: failure `inputs` is missing `cpu/energy` parameter +tags: null +initialize: + outputs: + - yaml + plugins: + multiply: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yml -o + manifests/outputs/plugins/multiply/failure-input-parameter-is-missing + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:23:15.185Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu/energy" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu: 0.001 + network/energy: 0.002 diff --git a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml new file mode 100644 index 000000000..22d23b8ed --- /dev/null +++ b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml @@ -0,0 +1,99 @@ +name: multiply +description: a manifest demonstrating how to use the multiply feature +tags: null +initialize: + plugins: + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/success-with-multiple-inputs.yml -o + manifests/outputs/plugins/multiply/success-with-multiple-inputs + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:22:04.324Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: -0.002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: 0 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + energy-product: 0.000002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: -0.002 + energy-product: -0.00001 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: 0 + energy-product: 0 diff --git a/manifests/outputs/plugins/multiply/success.yaml b/manifests/outputs/plugins/multiply/success.yaml new file mode 100644 index 000000000..19183c43c --- /dev/null +++ b/manifests/outputs/plugins/multiply/success.yaml @@ -0,0 +1,81 @@ +name: multiply +description: a manifest demonstrating how to use the multiply feature +tags: null +initialize: + plugins: + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/success.yml -o + manifests/outputs/plugins/multiply/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:20:34.016Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + energy-product: 0.000002 diff --git a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml new file mode 100644 index 000000000..8ffe1bd24 --- /dev/null +++ b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml @@ -0,0 +1,78 @@ +name: regex +description: failure with missing `physical-processor` field from `inputs` +tags: null +initialize: + outputs: + - yaml + plugins: + regex: + method: Regex + path: builtin + global-config: + parameter: physical-processor + match: ^(.*), + output: cpu/name +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/failure-missing-input-param.yml -o + manifests/outputs/plugins/regex/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:26:07.477Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingInputDataError: physical-processor is missing from the input array, + or has nullish value. +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical: >- + 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 diff --git a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml new file mode 100644 index 000000000..da1e88503 --- /dev/null +++ b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml @@ -0,0 +1,79 @@ +name: regex +description: physical processor doesn't match the regex expression +tags: null +initialize: + outputs: + - yaml + plugins: + regex: + method: Regex + path: builtin + global-config: + parameter: physical-processor + match: ^ + output: cpu/name +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/failure-not-matching-with-regex.yml -o + manifests/outputs/plugins/regex/failure-not-matching-with-regex + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:24:39.241Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + RegexMismatchError: `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` does + not match the /^/ regex expression +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 diff --git a/manifests/outputs/plugins/regex/success.yaml b/manifests/outputs/plugins/regex/success.yaml new file mode 100644 index 000000000..e63d81e75 --- /dev/null +++ b/manifests/outputs/plugins/regex/success.yaml @@ -0,0 +1,84 @@ +name: regex +description: successful path +tags: null +initialize: + plugins: + regex: + path: builtin + method: Regex + global-config: + parameter: physical-processor + match: ^(.*), + output: cpu/name + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/success.yml -o + manifests/outputs/plugins/regex/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:23:25.744Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 + cpu/name: >- + Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® + E5-2673 v4 2.3 GHz, diff --git a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml new file mode 100644 index 000000000..12978e16e --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -0,0 +1,78 @@ +name: sci-embodied +description: >- + failure with `defaults.device/emissions-embodied` being string instead of + number +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yml + -o + manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:49:08.280Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "device/emissions-embodied" parameter is invalid + number. please provide it as `gco2e` to input. Error code: invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: fail + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml new file mode 100644 index 000000000..4288c8a7a --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml @@ -0,0 +1,74 @@ +name: sci-embodied +description: missing device/expected-lifespan +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yml + -o manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:42:51.951Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "device/expected-lifespan" parameter is required. + Error code: invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/plugins/sci-embodied/success.yaml b/manifests/outputs/plugins/sci-embodied/success.yaml new file mode 100644 index 000000000..1a8099221 --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/success.yaml @@ -0,0 +1,81 @@ +name: sci-embodied +description: successful path +tags: null +initialize: + plugins: + sci-embodied: + path: builtin + method: SciEmbodied + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/success.yml -o + manifests/outputs/plugins/sci-embodied/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:42:03.186Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + carbon-embodied: 0.007292237442922374 diff --git a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml new file mode 100644 index 000000000..babc11c32 --- /dev/null +++ b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml @@ -0,0 +1,75 @@ +name: sci +description: failure with `config.sci.functional-unit` value being number +tags: null +initialize: + outputs: + - yaml + plugins: + sci: + kind: plugin + method: Sci + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/failure-invalid-config-value.yml -o + manifests/outputs/plugins/sci/failure-invalid-config-value + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:38:15.858Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InputValidationError: Required' +tree: + children: + child: + pipeline: + - sci + config: + sci: + functional-unit: 999 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + requests: 100 diff --git a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml new file mode 100644 index 000000000..5ce6ba144 --- /dev/null +++ b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml @@ -0,0 +1,75 @@ +name: sci +description: missing input value (carbon-embodied) +tags: null +initialize: + outputs: + - yaml + plugins: + sci: + kind: plugin + method: Sci + path: builtin + global-config: + functional-unit: requests +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/failure-missing-input-param.yml -o + manifests/outputs/plugins/sci/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:36:10.588Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "carbon" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sci + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + requests: 100 diff --git a/manifests/outputs/plugins/sci/success.yml.yaml b/manifests/outputs/plugins/sci/success.yml.yaml new file mode 100644 index 000000000..c9fc1e7f8 --- /dev/null +++ b/manifests/outputs/plugins/sci/success.yml.yaml @@ -0,0 +1,83 @@ +name: sci +description: successful path +tags: null +initialize: + plugins: + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/success.yml -o + manifests/outputs/plugins/sci/success.yml + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:35:12.024Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sci + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + carbon: 5.02 + requests: 100 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + carbon: 5.02 + requests: 100 + sci: 0.050199999999999995 diff --git a/manifests/outputs/plugins/shell/failure-invalid-command.yaml b/manifests/outputs/plugins/shell/failure-invalid-command.yaml new file mode 100644 index 000000000..308dd47ea --- /dev/null +++ b/manifests/outputs/plugins/shell/failure-invalid-command.yaml @@ -0,0 +1,73 @@ +name: shell +description: falure with `global-config.command` being number instead od string +tags: null +initialize: + outputs: + - yaml + plugins: + shell: + method: Shell + path: builtin + global-config: + command: 1000 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/shell/failure-invalid-command.yml -o + manifests/outputs/plugins/shell/failure-invalid-command + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:51:36.186Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "command" parameter is expected string, received + number. Error code: invalid_type. +tree: + children: + child: + pipeline: + - shell + inputs: + - timestamp: '2023-11-02T10:35:31.820Z' + duration: 3600 + cpu/energy: 0.002 + memory/energy: 0.000005 diff --git a/manifests/outputs/plugins/shell/success.yaml b/manifests/outputs/plugins/shell/success.yaml new file mode 100644 index 000000000..573ee41ee --- /dev/null +++ b/manifests/outputs/plugins/shell/success.yaml @@ -0,0 +1,71 @@ +name: shell +description: successful path +tags: null +initialize: + plugins: + shell: + path: builtin + method: Shell + global-config: + command: python3 /usr/local/bin/sampler + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/shell/success.yml -o + manifests/outputs/plugins/shell/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:50:37.625Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - shell + inputs: + - timestamp: '2023-11-02T10:35:31.820Z' + duration: 3600 + cpu/energy: 0.002 + memory/energy: 0.000005 + outputs: [] diff --git a/manifests/outputs/plugins/subtract/success.yaml b/manifests/outputs/plugins/subtract/success.yaml new file mode 100644 index 000000000..feff487d4 --- /dev/null +++ b/manifests/outputs/plugins/subtract/success.yaml @@ -0,0 +1,81 @@ +name: subtract demo +description: null +tags: null +initialize: + plugins: + subtract: + path: builtin + method: Subtract + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy/diff + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/subtract/success.yml -o + manifests/outputs/plugins/subtract/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:52:42.932Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - subtract + config: + subtract: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 + energy/diff: 0.002 diff --git a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml new file mode 100644 index 000000000..c9f1171d7 --- /dev/null +++ b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml @@ -0,0 +1,78 @@ +name: sum +description: failure with `inputs[0]` misses one of `global-config.input-parameters` +tags: null +initialize: + outputs: + - yaml + plugins: + sum: + method: Sum + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/failure-missing-input-param.yml -o + manifests/outputs/plugins/sum/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:55:20.733Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu/energy" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu: 0.001 + network/energy: 0.001 diff --git a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml new file mode 100644 index 000000000..e38b08539 --- /dev/null +++ b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml @@ -0,0 +1,81 @@ +name: sum +description: missing `output-parameter` in global-config +tags: null +initialize: + outputs: + - yaml + plugins: + sum: + method: Sum + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/failure-missing-output-param.yml -o + manifests/outputs/plugins/sum/failure-missing-output-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:54:23.422Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output-parameter" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: e diff --git a/manifests/outputs/plugins/sum/success.yaml b/manifests/outputs/plugins/sum/success.yaml new file mode 100644 index 000000000..9b201185e --- /dev/null +++ b/manifests/outputs/plugins/sum/success.yaml @@ -0,0 +1,81 @@ +name: sum +description: successful path +tags: null +initialize: + plugins: + sum: + path: builtin + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/success.yml -o + manifests/outputs/plugins/sum/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:53:35.496Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + energy: 0.002 diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml new file mode 100644 index 000000000..001223fc5 --- /dev/null +++ b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml @@ -0,0 +1,85 @@ +name: time-sync +description: >- + failure with `global-config.start-time` being later than + `global-config.end-time` +tags: null +initialize: + outputs: + - yaml + plugins: + time-sync: + method: TimeSync + path: builtin + global-config: + start-time: '2023-12-12T00:01:00.000Z' + end-time: '2023-12-12T00:00:00.000Z' + interval: 5 + allow-padding: true +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/failure-config-start-later-end.yml -o + manifests/outputs/plugins/time-sync/failure-config-start-later-end + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:13:59.114Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InputValidationError: `start-time` should be lower than `end-time`' +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml new file mode 100644 index 000000000..98fec7aea --- /dev/null +++ b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml @@ -0,0 +1,81 @@ +name: time-sync +description: missing global config +tags: null +initialize: + outputs: + - yaml + plugins: + time-sync: + method: TimeSync + path: builtin + global-config: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/failure-missing-global-config.yml -o + manifests/outputs/plugins/time-sync/failure-missing-global-config + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:13:12.360Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.time-sync.global-config" + parameter is expected object, received null. Error code: invalid_type. +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 3 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/success.yaml b/manifests/outputs/plugins/time-sync/success.yaml new file mode 100644 index 000000000..01c5b695b --- /dev/null +++ b/manifests/outputs/plugins/time-sync/success.yaml @@ -0,0 +1,122 @@ +name: time-sync +description: successful path +tags: null +initialize: + plugins: + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/success.yml -o + manifests/outputs/plugins/time-sync/success -s + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:12:32.629Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + energy-cpu: 0.0018000000000000004 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + energy-cpu: 0.0007714285714285716 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + energy-cpu: 0.0004952380952380952 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + energy-cpu: 0.0001 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + energy-cpu: 0 diff --git a/manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml deleted file mode 100644 index 33c5cc4b1..000000000 --- a/manifests/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: cloud-metadata -description: failing because cloud/vendor is not provided -tags: -initialize: - # outputs: ['yaml'] - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - child: - pipeline: - - cloud-metadata - config: - inputs: - - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred - #cloud/vendor: aws - cloud/instance-type: m5n.large - duration: 100 - cpu/utilization: 10 diff --git a/manifests/plugins/csv-lookup/cloud-metadata/success.yml b/manifests/plugins/csv-lookup/cloud-metadata/success.yml deleted file mode 100644 index bd3cfdbb7..000000000 --- a/manifests/plugins/csv-lookup/cloud-metadata/success.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: cloud-metadata -description: successful path -tags: -initialize: - # outputs: ['yaml'] - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - child: - pipeline: - - cloud-metadata - config: - inputs: - - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred - cloud/vendor: aws - cloud/instance-type: m5n.large - duration: 100 - cpu/utilization: 10 diff --git a/manifests/plugins/csv-lookup/region-metadata/success-renaming.yml b/manifests/plugins/csv-lookup/region-metadata/success-renaming.yml deleted file mode 100644 index 7934e6234..000000000 --- a/manifests/plugins/csv-lookup/region-metadata/success-renaming.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: csv-lookup-demo -description: -tags: -initialize: - # outputs: - # - yaml - plugins: - cloud-metadata: - method: CSVLookup - path: 'builtin' - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" - output: ['em-zone-id','renamed-em-zone-data'] -tree: - children: - child: - pipeline: - - cloud-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 diff --git a/manifests/plugins/csv-lookup/region-metadata/success.yml b/manifests/plugins/csv-lookup/region-metadata/success.yml deleted file mode 100644 index c6fc07d7b..000000000 --- a/manifests/plugins/csv-lookup/region-metadata/success.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: csv-lookup-demo -description: -tags: -initialize: - # outputs: - # - yaml - plugins: - cloud-metadata: - method: CSVLookup - path: 'builtin' - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" - output: "*" -tree: - children: - child: - pipeline: - - cloud-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 diff --git a/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml deleted file mode 100644 index b14e57d1d..000000000 --- a/manifests/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: tdp-finder -description: failure with `inputs` missing `physical-processor` param -tags: -initialize: - # outputs: ['yaml'] - plugins: - tdp-finder: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv - query: - name: physical-processor - output: "tdp" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 diff --git a/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml deleted file mode 100644 index 47f392fcc..000000000 --- a/manifests/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - # outputs: ['yaml'] - plugins: - tdp-finder: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv - query: - name: physical-processor - output: "tdp" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 302 diff --git a/manifests/plugins/csv-lookup/tdp-finder/success.yml b/manifests/plugins/csv-lookup/tdp-finder/success.yml deleted file mode 100644 index 42545b0df..000000000 --- a/manifests/plugins/csv-lookup/tdp-finder/success.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - # outputs: ['yaml'] - plugins: - tdp-finder: - method: CSVLookup - path: "builtin" - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv - query: - name: physical-processor - output: "tdp" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 3020e diff --git a/manifests/plugins/exponent/success.yml b/manifests/plugins/exponent/success.yml deleted file mode 100644 index c123b3a24..000000000 --- a/manifests/plugins/exponent/success.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: exponent demo -description: -tags: -initialize: - # outputs: - # - yaml - plugins: - exponent: - method: Exponent - path: 'builtin' - global-config: - input-parameter: 'cpu/energy' - exponent: 2 - output-parameter: 'energy' -tree: - children: - child: - pipeline: - - exponent - config: - exponent: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - network/energy: 0.001 diff --git a/manifests/plugins/interpolation/success.yml b/manifests/plugins/interpolation/success.yml deleted file mode 100644 index 35d750e48..000000000 --- a/manifests/plugins/interpolation/success.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: - - interpolation - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 - cpu/utilization: 45 diff --git a/manifests/plugins/subtract/success.yml b/manifests/plugins/subtract/success.yml deleted file mode 100644 index 276128171..000000000 --- a/manifests/plugins/subtract/success.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: subtract demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - subtract: - method: Subtract - path: 'builtin' - global-config: - input-parameters: ['cpu/energy', 'network/energy'] - output-parameter: 'energy/diff' -tree: - children: - child: - pipeline: - - subtract - config: - subtract: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.003 - network/energy: 0.001 \ No newline at end of file From eb481ec0ea6631c4ce4a7e11a4ce5b3412df206b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:05:31 +0400 Subject: [PATCH 274/863] fix(config): update NO_OUTPUT string --- src/config/strings.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/config/strings.ts b/src/config/strings.ts index b6f3410b4..10d9b472c 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -43,9 +43,8 @@ You are using plugin ${path} which is not part of the Impact Framework standard NOT_INITALIZED_PLUGIN: (name: string) => `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`, NO_OUTPUT: ` -You have not selected an output method. To see your output data, you can choose from: ---stdout: this will print your output data to the console ---output : this will save your output data to the given filepath (do not provide file extension) +You have not added an output command: +--output : will save your output data to the given filepath (do not provide file extension) Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`, SOURCE_IS_NOT_YAML: 'Given source file is not in yaml format.', TARGET_IS_NOT_YAML: 'Given target file is not in yaml format.', From 49f3661d3825e511c1636300da502529d5eb1786 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:08:43 +0400 Subject: [PATCH 275/863] feat(config): remove stdout from config and add 'no-output' --- src/config/config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index b8f676924..69584200f 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -32,11 +32,11 @@ export const CONFIG = { alias: 'p', description: '[path to a parameter file that overrides our defaults]', }, - stdout: { + 'no-output': { type: Boolean, optional: true, - alias: 's', - description: '[prints out to the console]', + alias: 'n', + description: '[privent output to the console]', }, help: { type: Boolean, From c6eec4aa1b1511ffd998f859024907866e1c7b66 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:10:24 +0400 Subject: [PATCH 276/863] fix(types): change stdout to noOutoup --- src/types/process-args.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 0f3799f5a..a5b44d423 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -2,7 +2,7 @@ export interface IEArgs { manifest?: string; output?: string; 'override-params'?: string; - stdout?: boolean; + 'no-output'?: boolean; debug?: boolean; } @@ -24,14 +24,14 @@ export interface IFCheckArgs { export interface Options { outputPath?: string; - stdout?: boolean; + noOutput?: boolean; } export interface ProcessArgsOutputs { inputPath: string; outputOptions: { outputPath?: string; - stdout?: boolean; + noOutput?: boolean; }; paramPath?: string; debug?: boolean; From ef5f1bdaa34a1b2bdd0c1b917ac426389b735343 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:13:24 +0400 Subject: [PATCH 277/863] feat(src): change stdout to noOutput --- src/lib/exhaust.ts | 2 +- src/util/args.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 1b65ca898..80a783047 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -52,7 +52,7 @@ export const exhaust = async ( const outputPlugins = context.initialize.outputs; - if (outputOptions.stdout) { + if (!outputOptions.noOutput) { ExportLog().execute(tree, context); } diff --git a/src/util/args.ts b/src/util/args.ts index 31da90461..927cf3ded 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -82,11 +82,11 @@ export const parseIEProcessArgs = (): ProcessArgsOutputs => { manifest, output, 'override-params': overrideParams, - stdout, + 'no-output': noOutput, debug, } = validateAndParseProcessArgs(); - if (!output && !stdout) { + if (!output && noOutput) { logger.warn(NO_OUTPUT); } @@ -96,7 +96,7 @@ export const parseIEProcessArgs = (): ProcessArgsOutputs => { inputPath: prependFullFilePath(manifest), outputOptions: { ...(output && {outputPath: prependFullFilePath(output)}), - ...(stdout && {stdout}), + ...(noOutput && {noOutput}), }, ...(overrideParams && {paramPath: overrideParams}), debug, From 00fb94e1507504eb1bbf0380f0618f1545aa08a8 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:15:26 +0400 Subject: [PATCH 278/863] test(src): update tests according to changes --- src/__tests__/unit/lib/exhaust.test.ts | 2 +- src/__tests__/unit/util/args.test.ts | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index 49db14370..66a797ebb 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -39,7 +39,7 @@ describe('lib/exhaust: ', () => { }; // @ts-ignore - await exhaust(tree, context, {stdout: true}); + await exhaust(tree, context, {'no-outout': false}); expect(spy).toHaveBeenCalledTimes(1); }); diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index f4238cbce..0c8d47efa 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -47,10 +47,10 @@ jest.mock('ts-command-line-args', () => ({ return { manifest: 'mock.notyaml', }; - case 'stdout': + case 'no-output': return { manifest: 'manifest-mock.yaml', - stdout: true, + 'no-output': false, }; /** If-diff mocks */ case 'only-target': @@ -178,7 +178,7 @@ describe('util/args: ', () => { const expectedResult = { inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), outputOptions: { - stdout: undefined, + 'no-output': undefined, }, }; @@ -228,7 +228,6 @@ describe('util/args: ', () => { inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), outputOptions: { outputPath: path.normalize(`${processRunningPath}/${outputPath}`), - stdout: undefined, }, }; @@ -248,18 +247,16 @@ describe('util/args: ', () => { } }); - it('returns stdout and manifest.', () => { + it('returns no-output and manifest.', () => { expect.assertions(1); - process.env.result = 'stdout'; + process.env.result = 'no-output'; const manifestPath = 'manifest-mock.yaml'; const response = parseIEProcessArgs(); const expectedResult = { inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - outputOptions: { - stdout: true, - }, + outputOptions: {}, }; expect(response).toEqual(expectedResult); From 5970ea46a81769c2a4d4edf58364bcd102b232fd Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 09:38:18 +0400 Subject: [PATCH 279/863] docs(src): update the description --- README.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6fe0f67a4..029a97c06 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Read the [specification and design docs](https://if.greensoftware.foundation) to ## Get started -IF is a framework for running pipelines of plugins that operate on a set of observations. This is all configured using a manifest file. We provide a standard library of plugins that come bundled with IF - we refer to these as `builtins`. We also have an [Explorer](https://explorer.if.greensoftware.foundation) where anyone can list third party plugins you can install. +IF is a framework for running pipelines of plugins that operate on a set of observations. This is all configured using a manifest file. We provide a standard library of plugins that come bundled with IF - we refer to these as `builtins`. We also have an [Explorer](https://explorer.if.greensoftware.foundation) where anyone can list third party plugins you can install. Start by installing the latest version of IF: @@ -32,13 +32,13 @@ Then create a `manifest` file that describes your application (see our docs for Then, run `if` using the following command: ```sh -if-run --manifest --stdout -## or you can use aliases -if-run -m -s +if-run --manifest +## or you can use alias +if-run -m ``` -Note that above command will print your outputs to the console. You can also provide the `--output` command to save your outputs to a yaml file: +Note that above command will print your outputs to the console. If you do not want to print the outputs to the console, you need to provide `--no-output` command. You can also provide the `--output` command to save your outputs to a yaml file: ```sh if-run -m -o @@ -72,19 +72,16 @@ if-run -h Please read our documentation at [if.greensoftware.foundation](https://if.greensoftware.foundation/) - ## Video walk-through Watch this video to learn how to create and run a `manifest`. [![Watch the walk-through video](https://i3.ytimg.com/vi/R-6eDM8AsvY/maxresdefault.jpg)](https://youtu.be/GW37Qd4AQbU) - ## Join our mailing list We have a public mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that explain what we've shipped, what we're working on and how you can get involved each week! - ## Contributing To contribute to IF, please fork this repository and raise a pull request from your fork. @@ -93,7 +90,6 @@ You can check our issue board for issues. We mark some issues `core-only` if the Please read the full contribution guidelines at [if.greensoftware.foundation](https://if.greensoftware.foundation/Contributing) - ## Bug reports To report bugs please use our bug report template. You can do this by opening a new issue and selecting `Bug Report` when you are prompted to pick a template. The more information you provide,.the quicker we will be able to reproduce, diagnose and triage your issue. From d928c511cc86cfe0557e350e02650209b27b54cd Mon Sep 17 00:00:00 2001 From: Manushak Keramyan Date: Wed, 3 Jul 2024 13:56:49 +0400 Subject: [PATCH 280/863] Update src/config/config.ts Co-authored-by: Narek Hovhannisyan Signed-off-by: Manushak Keramyan --- src/config/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index 69584200f..fda15f73d 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -36,7 +36,7 @@ export const CONFIG = { type: Boolean, optional: true, alias: 'n', - description: '[privent output to the console]', + description: '[prevent output to the console]', }, help: { type: Boolean, From 49e88c14182604a59f86bdf1c6449d65acba03b1 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 3 Jul 2024 15:07:52 +0400 Subject: [PATCH 281/863] fix(manifests): fetch latest manifests from main --- .../failure-invalid-instance-type.yaml | 27 ++++++ .../failure-invalid-vendor.yaml | 27 ++++++ .../failure-missing-cloud-vendor.yml | 27 ++++++ .../csv-lookup/cloud-metadata/success.yml | 27 ++++++ .../failure-missing-column.yml | 3 +- .../failure-missing-output.yml | 3 +- .../region-metadata/success-renaming.yml | 25 +++++ .../csv-lookup/region-metadata/success.yml | 25 +++++ .../builtins/csv-lookup/success-renaming.yaml | 83 ---------------- .../examples/builtins/csv-lookup/success.yaml | 95 ------------------- .../failure-missing-input-param.yml | 23 +++++ ...failure-unsupported-physical-processor.yml | 24 +++++ .../csv-lookup/tdp-finder/success.yml | 24 +++++ .../divide/failure-denominator-equal-zero.yml | 17 ++-- .../failure-invalid-config-denominator.yml | 17 ++-- .../divide/failure-missing-numerator.yml | 17 ++-- .../examples/builtins/divide/success.yml | 19 ++-- .../examples/builtins/exponent/success.yml | 25 +++++ .../examples/builtins/groupby/success.yml | 2 +- .../builtins/interpolation/success.yml | 23 +++++ .../builtins/mock-observations/success.yml | 2 +- .../sci/failure-missing-input-param.yml | 8 +- manifests/examples/builtins/sci/success.yml | 3 - .../examples/builtins/subtract/success.yml | 24 +++++ manifests/examples/builtins/sum/success.yml | 2 +- 25 files changed, 341 insertions(+), 231 deletions(-) create mode 100644 manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml create mode 100644 manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml create mode 100644 manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml create mode 100644 manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml rename manifests/examples/builtins/csv-lookup/{ => region-metadata}/failure-missing-column.yml (95%) rename manifests/examples/builtins/csv-lookup/{ => region-metadata}/failure-missing-output.yml (95%) create mode 100644 manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml create mode 100644 manifests/examples/builtins/csv-lookup/region-metadata/success.yml delete mode 100644 manifests/examples/builtins/csv-lookup/success-renaming.yaml delete mode 100644 manifests/examples/builtins/csv-lookup/success.yaml create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/success.yml create mode 100644 manifests/examples/builtins/exponent/success.yml create mode 100644 manifests/examples/builtins/interpolation/success.yml create mode 100644 manifests/examples/builtins/subtract/success.yml diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml new file mode 100644 index 000000000..fa55623c2 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: cloud/instance-type instance type is not supported in the cloud vendor +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + cloud/vendor: aws + cloud/instance-type: m6 + duration: 100 + cpu/utilization: 10 diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml new file mode 100644 index 000000000..6f247f6c4 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: failure with invalid `inputs.cloud/vendor` +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + cloud/vendor: gcp + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml new file mode 100644 index 000000000..33c5cc4b1 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: failing because cloud/vendor is not provided +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + #cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml new file mode 100644 index 000000000..bd3cfdbb7 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 diff --git a/manifests/examples/builtins/csv-lookup/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml similarity index 95% rename from manifests/examples/builtins/csv-lookup/failure-missing-column.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml index a0d54d0b5..85360f717 100644 --- a/manifests/examples/builtins/csv-lookup/failure-missing-column.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/examples/builtins/csv-lookup/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml similarity index 95% rename from manifests/examples/builtins/csv-lookup/failure-missing-output.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index c6fc07d7b..005961ee0 100644 --- a/manifests/examples/builtins/csv-lookup/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml new file mode 100644 index 000000000..66df39736 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml @@ -0,0 +1,25 @@ +name: csv-lookup-demo +description: +tags: +initialize: + # outputs: [yaml] + plugins: + cloud-metadata: + method: CSVLookup + path: 'builtin' + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: "cloud/provider" + cloud-region: "cloud/region" + output: ['em-zone-id','renamed-em-zone-data'] +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml new file mode 100644 index 000000000..005961ee0 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml @@ -0,0 +1,25 @@ +name: csv-lookup-demo +description: +tags: +initialize: + # outputs: [yaml] + plugins: + cloud-metadata: + method: CSVLookup + path: 'builtin' + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: "cloud/provider" + cloud-region: "cloud/region" + output: "*" +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/examples/builtins/csv-lookup/success-renaming.yaml b/manifests/examples/builtins/csv-lookup/success-renaming.yaml deleted file mode 100644 index 80d12e8a8..000000000 --- a/manifests/examples/builtins/csv-lookup/success-renaming.yaml +++ /dev/null @@ -1,83 +0,0 @@ -name: csv-lookup-demo -description: null -tags: null -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: cloud/provider - cloud-region: cloud/region - output: - - em-zone-id - - renamed-em-zone-data - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/examples/builtins/csv-lookup/success-renaming.yml -o - manifests/examples/builtins/csv-lookup/success-renaming - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T21:16:40.781Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child: - pipeline: - - cloud-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 - outputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 - renamed-em-zone-data: TW diff --git a/manifests/examples/builtins/csv-lookup/success.yaml b/manifests/examples/builtins/csv-lookup/success.yaml deleted file mode 100644 index 0f616f376..000000000 --- a/manifests/examples/builtins/csv-lookup/success.yaml +++ /dev/null @@ -1,95 +0,0 @@ -name: csv-lookup-demo -description: null -tags: null -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: cloud/provider - cloud-region: cloud/region - output: '*' - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/examples/builtins/csv-lookup/success.yml -o - manifests/examples/builtins/csv-lookup/success - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T21:09:37.066Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child: - pipeline: - - cloud-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 - outputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: asia-east1 - year: 2022 - cfe-region: Taiwan - em-zone-id: TW - wt-region-id: TW - location: Taiwan - geolocation: 25.0375,121.5625 - cfe-hourly: 0.18 - cfe-annual: nan - power-usage-efficiency: nan - net-carbon: 0 - grid-carbon-intensity-24x7: 453 - grid-carbon-intensity-consumption: nan - grid-carbon-intensity-marginal: nan - grid-carbon-intensity-production: nan - grid-carbon-intensity: 453 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml new file mode 100644 index 000000000..b14e57d1d --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -0,0 +1,23 @@ +name: tdp-finder +description: failure with `inputs` missing `physical-processor` param +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml new file mode 100644 index 000000000..47f392fcc --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 302 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml new file mode 100644 index 000000000..42545b0df --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index af5ed2ae0..4022d4797 100644 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 063274bc0..91129714a 100644 --- a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -5,8 +5,14 @@ initialize: outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 'vcpus' output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/examples/builtins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml index 7f03d5eba..7cf123976 100644 --- a/manifests/examples/builtins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: #numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/examples/builtins/divide/success.yml b/manifests/examples/builtins/divide/success.yml index ed75a7c5c..6a32d7e2c 100644 --- a/manifests/examples/builtins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -2,11 +2,17 @@ name: divide description: success path tags: initialize: -# outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/examples/builtins/exponent/success.yml b/manifests/examples/builtins/exponent/success.yml new file mode 100644 index 000000000..c8b59b78c --- /dev/null +++ b/manifests/examples/builtins/exponent/success.yml @@ -0,0 +1,25 @@ +name: exponent demo +description: +tags: +initialize: + # outputs: [yaml] + plugins: + exponent: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'cpu/energy' + exponent: 2 + output-parameter: 'energy' +tree: + children: + child: + pipeline: + - exponent + config: + exponent: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 diff --git a/manifests/examples/builtins/groupby/success.yml b/manifests/examples/builtins/groupby/success.yml index b81e7d53e..e8e164e91 100644 --- a/manifests/examples/builtins/groupby/success.yml +++ b/manifests/examples/builtins/groupby/success.yml @@ -1,7 +1,7 @@ name: groupby description: successful path initialize: - + # outputs: ['yaml'] plugins: group-by: path: "builtin" diff --git a/manifests/examples/builtins/interpolation/success.yml b/manifests/examples/builtins/interpolation/success.yml new file mode 100644 index 000000000..cce024727 --- /dev/null +++ b/manifests/examples/builtins/interpolation/success.yml @@ -0,0 +1,23 @@ +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: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 diff --git a/manifests/examples/builtins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml index 941344fe4..ac1464322 100644 --- a/manifests/examples/builtins/mock-observations/success.yml +++ b/manifests/examples/builtins/mock-observations/success.yml @@ -10,7 +10,7 @@ initialize: path: "builtin" global-config: timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:01 + timestamp-to: 2023-07-06T00:10 duration: 60 components: - cloud/instance-type: A1 diff --git a/manifests/examples/builtins/sci/failure-missing-input-param.yml b/manifests/examples/builtins/sci/failure-missing-input-param.yml index 44ced7374..54514a8e5 100644 --- a/manifests/examples/builtins/sci/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sci/failure-missing-input-param.yml @@ -8,17 +8,13 @@ initialize: kind: plugin method: Sci path: "builtin" - # global-config: - # functional-unit: requests + global-config: + functional-unit: requests tree: children: child: pipeline: - sci - config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/sci/success.yml b/manifests/examples/builtins/sci/success.yml index c7e6dbde6..cddfe5755 100644 --- a/manifests/examples/builtins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -16,9 +16,6 @@ tree: pipeline: - sci config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/subtract/success.yml b/manifests/examples/builtins/subtract/success.yml new file mode 100644 index 000000000..bcc27294c --- /dev/null +++ b/manifests/examples/builtins/subtract/success.yml @@ -0,0 +1,24 @@ +name: subtract demo +description: +tags: +initialize: + # outputs: ['yaml'] + plugins: + subtract: + method: Subtract + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy/diff' +tree: + children: + child: + pipeline: + - subtract + config: + subtract: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 \ No newline at end of file diff --git a/manifests/examples/builtins/sum/success.yml b/manifests/examples/builtins/sum/success.yml index fc0661bf5..454efc9e0 100644 --- a/manifests/examples/builtins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -2,7 +2,7 @@ name: sum description: successful path tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: sum: method: Sum From f9b8a2e36aa2494c9dab20510edb3489bda7a500 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 3 Jul 2024 17:52:35 +0400 Subject: [PATCH 282/863] fix(lib): prevent output result to the console when is provided -o path --- src/lib/exhaust.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 80a783047..8f2c72fa3 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -52,7 +52,7 @@ export const exhaust = async ( const outputPlugins = context.initialize.outputs; - if (!outputOptions.noOutput) { + if (!outputOptions.noOutput && !outputOptions.outputPath) { ExportLog().execute(tree, context); } From baf4b0bb156f6dfc0e20ca9c92d7bb7d19bf8f23 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 3 Jul 2024 20:21:35 +0400 Subject: [PATCH 283/863] fix(manifests): fix pipelines --- manifests/examples/pipelines/generics.yml | 80 +++++++++-- .../pipelines/mock-cpu-util-to-carbon.yml | 70 ---------- manifests/examples/pipelines/nesting.yml | 117 +++++++++++----- .../examples/pipelines/pipeline-teads-sci.yml | 72 +++++++--- .../pipelines/pipeline-with-aggregate.yml | 92 +++++++++---- .../pipelines/pipeline-with-mocks.yml | 87 +++++++++--- manifests/examples/pipelines/zeros.yml | 130 ++++++++++++++++++ 7 files changed, 469 insertions(+), 179 deletions(-) delete mode 100644 manifests/examples/pipelines/mock-cpu-util-to-carbon.yml create mode 100644 manifests/examples/pipelines/zeros.yml diff --git a/manifests/examples/pipelines/generics.yml b/manifests/examples/pipelines/generics.yml index 6492c9a3d..641bedcb1 100644 --- a/manifests/examples/pipelines/generics.yml +++ b/manifests/examples/pipelines/generics.yml @@ -2,20 +2,55 @@ name: generics description: a pipeline that does arbitrary calculations using our generic arithmetic builtins tags: initialize: + # outputs: [yaml] plugins: - "sum": + "interpolate": + 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: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy-sum + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "coefficient": path: "builtin" method: Coefficient global-config: - input-parameter: energy + input-parameter: cpu-energy-kwh coefficient: 2 output-parameter: energy-doubled "multiply": @@ -28,18 +63,45 @@ tree: children: child-1: pipeline: - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - coefficient - multiply config: defaults: cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 - cpu/energy: 20 + network/energy: 10 + energy: 5 + - timestamp: "2023-12-12T00:00:01.000Z" + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: "2023-12-12T00:00:06.000Z" + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: "2023-12-12T00:00:13.000Z" + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 network/energy: 10 energy: 5 diff --git a/manifests/examples/pipelines/mock-cpu-util-to-carbon.yml b/manifests/examples/pipelines/mock-cpu-util-to-carbon.yml deleted file mode 100644 index 35f7cea26..000000000 --- a/manifests/examples/pipelines/mock-cpu-util-to-carbon.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: mock-cpu-util-to-carbon -description: a complete pipeline that starts with mocked CPU utilization data and outputs operational carbon in gCO2eq -initialize: - #outputs: ['yaml'] - plugins: - group-by: - path: 'builtin' - method: GroupBy - operational-carbon: - path: 'builtin' - method: Multiply - global-config: - input-parameters: ['cpu/energy', 'grid/carbon-intensity'] - output-parameter: 'carbon' - watttime: - path: '@grnsft/if-unofficial-plugins' - method: WattTimeGridEmissions - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - start-time: '2024-03-05T00:00:00.000Z' - end-time: '2024-03-05T00:01:00.000Z' - interval: 5 - allow-padding: true -tree: - pipeline: - - mock-observations - - group-by - - time-sync - - cloud-metadata - - watttime - - teads-curve - - operational-carbon - defaults: - config: - group-by: - group: - - cloud/region - - name - inputs: null diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index e56e8bb18..978510f48 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -7,31 +7,62 @@ tags: aggregation: metrics: - "carbon" - - "energy" type: "both" params: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: - teads-curve: - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - sum: + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh sci-embodied: path: "builtin" method: SciEmbodied - sci-o: - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" sci: path: "builtin" method: Sci @@ -62,13 +93,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -108,13 +143,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -156,13 +195,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -202,13 +245,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci diff --git a/manifests/examples/pipelines/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml index 01c491cdc..c07b093bd 100644 --- a/manifests/examples/pipelines/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -3,25 +3,57 @@ description: a full pipeline seeded with some hardcoded input data and yielding tags: initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci @@ -47,10 +79,14 @@ tree: children: child-1: pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - sci config: @@ -60,8 +96,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 component: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index bd3e637ac..7b689f1d8 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -7,25 +7,62 @@ aggregation: type: "both" initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci global-config: - functional-unit: "requests" + functional-unit: requests # factor to convert per time to per f.unit "sum-carbon": path: "builtin" method: Sum @@ -42,17 +79,18 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - "group-by": - path: builtin - method: GroupBy tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -67,8 +105,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -96,10 +134,14 @@ tree: requests: 30 child-2: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -114,8 +156,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 @@ -140,4 +182,4 @@ tree: cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west - requests: 180 + requests: 180 \ No newline at end of file diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 008e319b1..168ebd7fe 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -25,20 +25,57 @@ initialize: cpu/utilization: min: 1 max: 99 - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sum-carbon": path: "builtin" method: Sum @@ -68,10 +105,14 @@ tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -86,9 +127,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -116,10 +156,14 @@ tree: requests: 50 child-2: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -134,9 +178,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/examples/pipelines/zeros.yml b/manifests/examples/pipelines/zeros.yml new file mode 100644 index 000000000..da5541789 --- /dev/null +++ b/manifests/examples/pipelines/zeros.yml @@ -0,0 +1,130 @@ +name: generics +description: a pipeline that does arbitrary calculations using our generic arithmetic builtins +tags: +initialize: + plugins: + "sum-zero-and-one": + path: "builtin" + method: Sum + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-plus-zero + "sum-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-plus-zero + "subtract-one-and-zero": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-minus-zero + "subtract-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-minus-zero + "subtract-zero-and-one": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - zero-value + - some-value + output-parameter: zero-minus-one + "coefficient-one-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 1 + output-parameter: zero-times-one-coefficient + "coefficient-zero-times-one": + path: "builtin" + method: Coefficient + global-config: + input-parameter: some-value + coefficient: 0 + output-parameter: one-times-zero-coefficient + "coefficient-zero-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 0 + output-parameter: zero-times-zero-coefficient + "multiply-one-times-zero": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["some-value", "zero-value"] + output-parameter: "one-times-zero" + "multiply-zero-times-one": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["zero-value", "zero-value"] + output-parameter: "zero-times-one" + exponent-one-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'some-value' + exponent: 0 + output-parameter: 'one-raised-to-zero-power' + exponent-zero-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 0 + output-parameter: 'zero-raised-to-zero-power' + exponent-zero-to-one: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 1 + output-parameter: 'zero-raised-to-first-power' + "sci": + path: "builtin" + method: Sci + global-config: + functional-unit: "zero-value" +tree: + children: + child-1: + pipeline: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci + config: + defaults: + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + duration: 1 + some-value: 1 + zero-value: 0 + carbon: 10 From 9f9098dd1c7ba6eb917f65a35c1206f6a8f565a1 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 3 Jul 2024 20:58:20 +0400 Subject: [PATCH 284/863] revert(manifests): drop basic yaml --- manifests/examples/pipelines/basic.yml | 27 -------------------------- 1 file changed, 27 deletions(-) delete mode 100644 manifests/examples/pipelines/basic.yml diff --git a/manifests/examples/pipelines/basic.yml b/manifests/examples/pipelines/basic.yml deleted file mode 100644 index 0f3dc7735..000000000 --- a/manifests/examples/pipelines/basic.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: basic -description: a minimal manifest executing a single plugin on a single component for a single timestep -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 From 661112ef42c48d7bf862873ad6ca3258fa282056 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:07:10 +0100 Subject: [PATCH 285/863] fix(package): rm if-plugins dependencies --- .../bugs/initialize-error-no-config.yaml | 5 +- .../bugs/initialize-error-no-path.yaml | 5 +- .../bugs/initialize-error-no-plugins.yaml | 5 +- .../bugs/input-error-missing-duration.yaml | 5 +- ...observations-failure-duration-is-zero.yaml | 5 +- .../bugs/pipeline-error-naming-mismatch.yaml | 5 +- .../pipeline-error-uninitialized-plugin.yaml | 5 +- .../outputs/bugs/pipeline-ordering-error.yaml | 5 +- .../sci-embodied-missing-resources-total.yaml | 5 +- manifests/outputs/divide.yaml | 93 +++++++++++++++++++ .../aggregate-failure-invalid-metrics.yaml | 5 +- ...gate-failure-missing-metric-in-inputs.yaml | 5 +- .../features/aggregate-horizontal.yaml | 5 +- .../outputs/features/aggregate-vertical.yaml | 5 +- manifests/outputs/features/aggregate.yaml | 5 +- .../pipelines/cloud-metadata-divide.yaml | 5 +- .../mock-obs-group-by-cloud-meta.yaml | 5 +- .../outputs/pipelines/mock-obs-groupby.yaml | 5 +- .../outputs/pipelines/mock-obs-time-sync.yaml | 5 +- .../failure-invalid-config-input-param.yaml | 5 +- .../failure-output-param-is-null.yaml | 5 +- .../outputs/plugins/coefficient/success.yaml | 5 +- .../failure-missing-cloud-vendor.yaml | 5 +- .../csv-lookup/cloud-metadata/success.yaml | 5 +- .../failure-missing-column.yaml | 5 +- .../failure-missing-output.yaml | 5 +- .../region-metadata/success-renaming.yaml | 5 +- .../csv-lookup/region-metadata/success.yaml | 5 +- .../failure-missing-input-param.yaml | 5 +- ...ailure-unsupported-physical-processor.yaml | 5 +- .../csv-lookup/tdp-finder/success.yaml | 5 +- .../failure-invalid-config-denominator.yaml | 5 +- .../divide/failure-missing-numerator.yaml | 5 +- .../success-denominator-equal-zero.yaml | 5 +- manifests/outputs/plugins/divide/success.yaml | 5 +- .../outputs/plugins/exponent/success.yaml | 5 +- .../groupby/failure-invalid-config-group.yaml | 5 +- .../failure-missing-cloud-instance-type.yaml | 5 +- .../outputs/plugins/groupby/success.yaml | 5 +- .../plugins/interpolation/interpolation.yaml | 5 +- .../plugins/interpolation/success.yaml | 5 +- .../failure-invalid-config-cpu-range.yaml | 5 +- ...lure-invalid-memory-utilization-range.yaml | 5 +- .../failure-missing-timestamp-from-param.yaml | 5 +- .../plugins/mock-observations/success.yaml | 5 +- .../failure-input-parameter-is-missing.yaml | 5 +- .../success-with-multiple-inputs.yaml | 5 +- .../outputs/plugins/multiply/success.yaml | 5 +- .../regex/failure-missing-input-param.yaml | 5 +- .../failure-not-matching-with-regex.yaml | 5 +- manifests/outputs/plugins/regex/success.yaml | 5 +- ...ailure-invalid-default-emission-value.yaml | 5 +- .../failure-missing-expected-lifespan.yaml | 5 +- .../outputs/plugins/sci-embodied/success.yaml | 5 +- .../sci/failure-invalid-config-value.yaml | 5 +- .../sci/failure-missing-input-param.yaml | 5 +- .../outputs/plugins/sci/success.yml.yaml | 5 +- .../shell/failure-invalid-command.yaml | 5 +- manifests/outputs/plugins/shell/success.yaml | 5 +- .../outputs/plugins/subtract/success.yaml | 5 +- .../sum/failure-missing-input-param.yaml | 5 +- .../sum/failure-missing-output-param.yaml | 5 +- manifests/outputs/plugins/sum/success.yaml | 5 +- .../failure-config-start-later-end.yaml | 5 +- .../failure-missing-global-config.yaml | 5 +- .../outputs/plugins/time-sync/success.yaml | 5 +- 66 files changed, 158 insertions(+), 260 deletions(-) create mode 100644 manifests/outputs/divide.yaml diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml index 9d3c21a68..56be9add7 100644 --- a/manifests/outputs/bugs/initialize-error-no-config.yaml +++ b/manifests/outputs/bugs/initialize-error-no-config.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml index 77483ac27..e2ee4d616 100644 --- a/manifests/outputs/bugs/initialize-error-no-path.yaml +++ b/manifests/outputs/bugs/initialize-error-no-path.yaml @@ -43,10 +43,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml index 0324550ee..208010e00 100644 --- a/manifests/outputs/bugs/initialize-error-no-plugins.yaml +++ b/manifests/outputs/bugs/initialize-error-no-plugins.yaml @@ -26,10 +26,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml index 7a9a53b8e..dd339eb4f 100644 --- a/manifests/outputs/bugs/input-error-missing-duration.yaml +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -43,10 +43,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml index 6af109ec0..fedf856fb 100644 --- a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -46,10 +46,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml index b7885a361..21fc5e668 100644 --- a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -43,10 +43,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml index 75d87e3be..a37517432 100644 --- a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -43,10 +43,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml index c167f5e39..fe59b03d8 100644 --- a/manifests/outputs/bugs/pipeline-ordering-error.yaml +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -80,10 +80,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml index add3499be..e0a50cd90 100644 --- a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml +++ b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml @@ -29,10 +29,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/divide.yaml b/manifests/outputs/divide.yaml new file mode 100644 index 000000000..e0875c420 --- /dev/null +++ b/manifests/outputs/divide.yaml @@ -0,0 +1,93 @@ +name: divide +description: success path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /home/joe/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /home/joe/Code/if/src/index.ts -m ./manifests/plugins/divide/success.yml -o + ./manifests/outputs/divide + environment: + if-version: 0.4.0 + os: linux + os-version: 5.15.0-113-generic + node-version: 21.4.0 + date-time: 2024-07-03T14:02:26.789Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index a332f8476..1a737e742 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -38,10 +38,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 2aeb03fab..82d6759bc 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -38,10 +38,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index b0ee17210..3110af664 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -37,10 +37,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 5a7695520..1527a9280 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -37,10 +37,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index 91ef6a671..062cd9932 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -37,10 +37,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml index 4b1f0ebba..130c4361e 100644 --- a/manifests/outputs/pipelines/cloud-metadata-divide.yaml +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -41,10 +41,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml index 81f4ee71b..5585d4c42 100644 --- a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml +++ b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml @@ -66,10 +66,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml index 29b5aff0a..4783dffde 100644 --- a/manifests/outputs/pipelines/mock-obs-groupby.yaml +++ b/manifests/outputs/pipelines/mock-obs-groupby.yaml @@ -46,10 +46,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index 54c411b96..271340c2b 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -102,10 +102,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml index 6f3e5cb23..ba10eaee3 100644 --- a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml +++ b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml index 67ac62cff..dd2f6c952 100644 --- a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/coefficient/success.yaml b/manifests/outputs/plugins/coefficient/success.yaml index edf264092..86300012c 100644 --- a/manifests/outputs/plugins/coefficient/success.yaml +++ b/manifests/outputs/plugins/coefficient/success.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 5cbc23dec..943416663 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -36,10 +36,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml index 4b02a939b..25c8db6e3 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -34,10 +34,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml index 0826f4fa2..cad931fd1 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -35,10 +35,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml index 57cfb9358..ad5ab9ec8 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -34,10 +34,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml index 408a9d3dc..77aeecd66 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml @@ -35,10 +35,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml index aa1f3de32..10bb9a637 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml @@ -33,10 +33,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml index 7406ac879..56b6c2630 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -34,10 +34,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml index 0d4bff834..888df1ce7 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -34,10 +34,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml index e3dd6e9eb..bf12d4892 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml @@ -32,10 +32,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml index 1f70d83c8..299cc1ade 100644 --- a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml +++ b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml index 065bc9a55..6aa908327 100644 --- a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml index 9c333a41e..5617fdbf9 100644 --- a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml +++ b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml @@ -41,10 +41,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/divide/success.yaml b/manifests/outputs/plugins/divide/success.yaml index 42e60482c..3c741121f 100644 --- a/manifests/outputs/plugins/divide/success.yaml +++ b/manifests/outputs/plugins/divide/success.yaml @@ -41,10 +41,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/exponent/success.yaml b/manifests/outputs/plugins/exponent/success.yaml index 1afa27f5a..1a8588693 100644 --- a/manifests/outputs/plugins/exponent/success.yaml +++ b/manifests/outputs/plugins/exponent/success.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml index e211b0d51..3b188a07d 100644 --- a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml +++ b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml @@ -26,10 +26,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml index 38cebb9bb..ae91af1e1 100644 --- a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml +++ b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml @@ -26,10 +26,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml index cf1c7f734..04d54837b 100644 --- a/manifests/outputs/plugins/groupby/success.yaml +++ b/manifests/outputs/plugins/groupby/success.yaml @@ -25,10 +25,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/interpolation/interpolation.yaml b/manifests/outputs/plugins/interpolation/interpolation.yaml index 08036cf0b..9e3c45e4d 100644 --- a/manifests/outputs/plugins/interpolation/interpolation.yaml +++ b/manifests/outputs/plugins/interpolation/interpolation.yaml @@ -40,10 +40,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/interpolation/success.yaml b/manifests/outputs/plugins/interpolation/success.yaml index 5c81f15fa..bad3425f9 100644 --- a/manifests/outputs/plugins/interpolation/success.yaml +++ b/manifests/outputs/plugins/interpolation/success.yaml @@ -40,10 +40,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml index ebf62b776..d79f394f5 100644 --- a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -49,10 +49,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml index 72d1cf9d0..3667dff6c 100644 --- a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -47,10 +47,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml index ab340d36c..b8599cb08 100644 --- a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -46,10 +46,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/plugins/mock-observations/success.yaml index 1a89eea75..cacd16cad 100644 --- a/manifests/outputs/plugins/mock-observations/success.yaml +++ b/manifests/outputs/plugins/mock-observations/success.yaml @@ -44,10 +44,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml index 23594fbf9..1ef59959d 100644 --- a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml +++ b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml @@ -32,10 +32,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml index 22d23b8ed..76c3d93d3 100644 --- a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml +++ b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/multiply/success.yaml b/manifests/outputs/plugins/multiply/success.yaml index 19183c43c..60546f50e 100644 --- a/manifests/outputs/plugins/multiply/success.yaml +++ b/manifests/outputs/plugins/multiply/success.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml index 8ffe1bd24..8399ac20e 100644 --- a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml index da1e88503..4b1ae47d6 100644 --- a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml +++ b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/regex/success.yaml b/manifests/outputs/plugins/regex/success.yaml index e63d81e75..763cd4093 100644 --- a/manifests/outputs/plugins/regex/success.yaml +++ b/manifests/outputs/plugins/regex/success.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml index 12978e16e..a3df4f806 100644 --- a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml +++ b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml index 4288c8a7a..073b2cb45 100644 --- a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml +++ b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml @@ -27,10 +27,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci-embodied/success.yaml b/manifests/outputs/plugins/sci-embodied/success.yaml index 1a8099221..5f74a121e 100644 --- a/manifests/outputs/plugins/sci-embodied/success.yaml +++ b/manifests/outputs/plugins/sci-embodied/success.yaml @@ -26,10 +26,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml index babc11c32..61c424e91 100644 --- a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml +++ b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml @@ -28,10 +28,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml index 5ce6ba144..656f21c1d 100644 --- a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml @@ -30,10 +30,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sci/success.yml.yaml b/manifests/outputs/plugins/sci/success.yml.yaml index c9fc1e7f8..bd7b81f0c 100644 --- a/manifests/outputs/plugins/sci/success.yml.yaml +++ b/manifests/outputs/plugins/sci/success.yml.yaml @@ -28,10 +28,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/shell/failure-invalid-command.yaml b/manifests/outputs/plugins/shell/failure-invalid-command.yaml index 308dd47ea..f9ec8894b 100644 --- a/manifests/outputs/plugins/shell/failure-invalid-command.yaml +++ b/manifests/outputs/plugins/shell/failure-invalid-command.yaml @@ -29,10 +29,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/shell/success.yaml b/manifests/outputs/plugins/shell/success.yaml index 573ee41ee..3a8825817 100644 --- a/manifests/outputs/plugins/shell/success.yaml +++ b/manifests/outputs/plugins/shell/success.yaml @@ -28,10 +28,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/subtract/success.yaml b/manifests/outputs/plugins/subtract/success.yaml index feff487d4..5d028f63f 100644 --- a/manifests/outputs/plugins/subtract/success.yaml +++ b/manifests/outputs/plugins/subtract/success.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml index c9f1171d7..ce59a1f4e 100644 --- a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml @@ -32,10 +32,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml index e38b08539..548a8b14e 100644 --- a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml +++ b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/sum/success.yaml b/manifests/outputs/plugins/sum/success.yaml index 9b201185e..1d9b47a3f 100644 --- a/manifests/outputs/plugins/sum/success.yaml +++ b/manifests/outputs/plugins/sum/success.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml index 001223fc5..e0957366a 100644 --- a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml +++ b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml @@ -34,10 +34,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml index 98fec7aea..79f3bb69e 100644 --- a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml +++ b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml @@ -28,10 +28,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/time-sync/success.yaml b/manifests/outputs/plugins/time-sync/success.yaml index 01c5b695b..1f0a7f07e 100644 --- a/manifests/outputs/plugins/time-sync/success.yaml +++ b/manifests/outputs/plugins/time-sync/success.yaml @@ -31,10 +31,7 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' From 0c4c32f770f9b106eae5cba96474c673b477faa5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 4 Jul 2024 12:11:42 +0400 Subject: [PATCH 286/863] feat(.github): update manifest directory path in nodejs ci --- .github/workflows/nodejs-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index 306833939..aade2b55f 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -23,4 +23,4 @@ jobs: run: npm run test --silent - name: Run integration tests - run: npm run if-check -- -d outputs + run: npm run if-check -- -d manifests/outputs From 2adca0a28e543894f1ef77565eae6dad5749a621 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:30:47 +0400 Subject: [PATCH 287/863] fix(lib): update exhaust function to handle only yaml files --- src/lib/exhaust.ts | 43 +++++-------------------------------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 8f2c72fa3..3eb98eea5 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -1,43 +1,14 @@ -import {ERRORS} from '@grnsft/if-core/utils'; +// import {ERRORS} from '@grnsft/if-core/utils'; -/** - * @todo This is temporary solution, will be refactored to support dynamic plugins. - */ -import {ExportCSV} from '../builtins/export-csv'; -import {ExportCSVRaw} from '../builtins/export-csv-raw'; import {ExportLog} from '../builtins/export-log'; import {ExportYaml} from '../builtins/export-yaml'; import {STRINGS} from '../config'; -import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; import {Options} from '../types/process-args'; -const {InvalidExhaustPluginError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN, PREPARING_OUTPUT_DATA} = STRINGS; - -/** - * Initialize exhaust plugins based on the provided config - */ -const initializeExhaustPlugins = (plugins: string[]) => - plugins.map(initializeExhaustPlugin); - -/** - * Factory method for exhaust plugins. - */ -const initializeExhaustPlugin = (name: string): ExhaustPluginInterface => { - switch (name) { - case 'yaml': - return ExportYaml(); - case 'csv': - return ExportCSV(); - case 'csv-raw': - return ExportCSVRaw(); - default: - throw new InvalidExhaustPluginError(INVALID_EXHAUST_PLUGIN(name)); - } -}; +const {PREPARING_OUTPUT_DATA} = STRINGS; /** * Output manager - Exhaust. @@ -50,19 +21,15 @@ export const exhaust = async ( ) => { console.debug(PREPARING_OUTPUT_DATA); - const outputPlugins = context.initialize.outputs; - if (!outputOptions.noOutput && !outputOptions.outputPath) { ExportLog().execute(tree, context); } - if (!outputPlugins) { + if (!outputOptions.outputPath) { return; } - const exhaustPlugins = initializeExhaustPlugins(outputPlugins); + const exportYaml = ExportYaml(); - for await (const plugin of exhaustPlugins) { - await plugin.execute(tree, context, outputOptions.outputPath); - } + await exportYaml.execute(tree, context, outputOptions.outputPath); }; From b5683678595fc7e0b861a302d0f3554e424236fa Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:32:06 +0400 Subject: [PATCH 288/863] fix(util): remove `outputs` from validations --- src/util/validations.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/util/validations.ts b/src/util/validations.ts index 920e7cbdb..ae3eb74e0 100644 --- a/src/util/validations.ts +++ b/src/util/validations.ts @@ -63,7 +63,6 @@ export const manifestSchema = z.object({ 'global-config': z.record(z.string(), z.any()).optional(), }) ), - outputs: z.array(z.string()).optional(), }), execution: z .object({ From 9a5caa55c3b10a18b96f7972ad3742f3d7d302fe Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:34:54 +0400 Subject: [PATCH 289/863] fix(builtins): fix executed manifest extension --- src/builtins/export-yaml.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts index 624e1298f..17ed95a56 100644 --- a/src/builtins/export-yaml.ts +++ b/src/builtins/export-yaml.ts @@ -26,10 +26,14 @@ export const ExportYaml = () => { tree, }; const path = stripHashtag(outputPath); + const pathWithoutExtension = + path.split('.').length > 1 + ? path.split('.').slice(0, -1).join('.') + : path; - console.debug(EXPORTING_TO_YAML_FILE(path)); + console.debug(EXPORTING_TO_YAML_FILE(pathWithoutExtension)); - await saveYamlFileAs(outputFile, `${path}.yaml`); + await saveYamlFileAs(outputFile, `${pathWithoutExtension}.yaml`); }; return {execute}; From 2dff3b3be7c31633ccf834a083e8362187d1c060 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:39:51 +0400 Subject: [PATCH 290/863] fix(manifests): remove `outputs` from manifest --- .../failure-invalid-config-input-param.yml | 1 - .../failure-output-param-is-null.yaml | 1 - .../examples/builtins/coefficient/success.yml | 1 - .../failure-invalid-instance-type.yaml | 3 +- .../failure-invalid-vendor.yaml | 3 +- .../failure-missing-cloud-vendor.yml | 3 +- .../csv-lookup/cloud-metadata/success.yml | 3 +- .../failure-missing-column.yml | 1 - .../failure-missing-output.yml | 3 +- .../region-metadata/success-renaming.yml | 5 +- .../csv-lookup/region-metadata/success.yml | 3 +- .../failure-missing-input-param.yml | 1 - ...failure-unsupported-physical-processor.yml | 1 - .../csv-lookup/tdp-finder/success.yml | 1 - .../divide/failure-denominator-equal-zero.yml | 3 +- .../failure-invalid-config-denominator.yml | 5 +- .../divide/failure-missing-numerator.yml | 3 +- .../examples/builtins/divide/success.yml | 3 +- .../examples/builtins/exponent/success.yml | 7 +- .../groupby/failure-invalid-config-group.yml | 1 - .../failure-missing-cloud-instance-type.yml | 3 +- .../examples/builtins/groupby/success.yml | 1 - .../failure-invalid-config-cpu-range.yml | 1 - ...ilure-invalid-memory-utilization-range.yml | 1 - .../failure-missing-timestamp-from-param.yml | 1 - .../builtins/mock-observations/success.yml | 1 - .../failure-input-parameter-is-missing.yml | 1 - .../regex/failure-missing-input-param.yml | 1 - .../regex/failure-not-matching-with-regex.yml | 1 - manifests/examples/builtins/regex/success.yml | 1 - ...failure-invalid-default-emission-value.yml | 3 +- .../failure-missing-expected-lifespan.yml | 1 - .../builtins/sci-embodied/success.yml | 1 - .../sci/failure-invalid-config-value.yml | 1 - manifests/examples/builtins/sci/success.yml | 1 - .../shell/failure-invalid-command.yml | 1 - .../examples/builtins/subtract/success.yml | 9 +- .../sum/failure-missing-input-param.yml | 1 - .../sum/failure-missing-output-param.yml | 3 +- manifests/examples/builtins/sum/success.yml | 1 - manifests/examples/pipelines/generics.yml | 1 - .../examples/pipelines/instance-metadata.yml | 4 +- manifests/examples/pipelines/nesting.yml | 7 +- .../pipelines/pipeline-with-mocks.yml | 7 +- manifests/examples/pipelines/sci.yml | 8 +- .../bugs/aggregation-error-wrong-metric.yaml | 46 ++--- .../bugs/initialize-error-no-config.yaml | 24 +-- .../bugs/initialize-error-no-path.yaml | 26 ++- .../bugs/initialize-error-no-plugins.yaml | 24 +-- .../bugs/input-error-missing-duration.yaml | 26 ++- ...observations-failure-duration-is-zero.yaml | 26 ++- .../bugs/pipeline-error-naming-mismatch.yaml | 26 ++- .../pipeline-error-uninitialized-plugin.yaml | 26 ++- .../outputs/bugs/pipeline-ordering-error.yaml | 34 ++-- .../sci-embodied-missing-resources-total.yaml | 24 +-- manifests/outputs/divide.yaml | 22 +- .../aggregate-failure-invalid-metrics.yaml | 32 ++- ...gate-failure-missing-metric-in-inputs.yaml | 32 ++- .../features/aggregate-horizontal.yaml | 40 ++-- .../outputs/features/aggregate-vertical.yaml | 52 +++-- manifests/outputs/features/aggregate.yaml | 52 +++-- .../pipelines/cloud-metadata-divide.yaml | 24 +-- .../mock-obs-group-by-cloud-meta.yaml | 192 +++++++++--------- .../outputs/pipelines/mock-obs-groupby.yaml | 52 +++-- .../outputs/pipelines/mock-obs-time-sync.yaml | 64 +++--- .../failure-invalid-config-input-param.yaml | 24 +-- .../failure-output-param-is-null.yaml | 2 - .../outputs/plugins/coefficient/success.yaml | 24 +-- .../failure-invalid-instance-type.yaml | 3 +- .../failure-invalid-vendor.yaml | 3 +- .../failure-missing-cloud-vendor.yaml | 2 - .../csv-lookup/cloud-metadata/success.yaml | 24 +-- .../failure-missing-column.yaml | 26 ++- .../failure-missing-output.yaml | 24 +-- .../region-metadata/success-renaming.yaml | 24 +-- .../csv-lookup/region-metadata/success.yaml | 26 ++- .../failure-missing-input-param.yaml | 24 +-- ...ailure-unsupported-physical-processor.yaml | 24 +-- .../csv-lookup/tdp-finder/success.yaml | 24 +-- .../failure-invalid-config-denominator.yaml | 24 +-- .../divide/failure-missing-numerator.yaml | 24 +-- .../success-denominator-equal-zero.yaml | 24 +-- manifests/outputs/plugins/divide/success.yaml | 24 +-- .../outputs/plugins/exponent/success.yaml | 24 +-- .../groupby/failure-invalid-config-group.yaml | 24 +-- .../failure-missing-cloud-instance-type.yaml | 26 ++- .../outputs/plugins/groupby/success.yaml | 24 +-- .../plugins/interpolation/interpolation.yaml | 26 ++- .../plugins/interpolation/success.yaml | 26 ++- .../failure-invalid-config-cpu-range.yaml | 24 +-- ...lure-invalid-memory-utilization-range.yaml | 24 +-- .../failure-missing-timestamp-from-param.yaml | 24 +-- .../plugins/mock-observations/success.yaml | 64 +++--- .../failure-input-parameter-is-missing.yaml | 24 +-- .../success-with-multiple-inputs.yaml | 24 +-- .../outputs/plugins/multiply/success.yaml | 24 +-- .../regex/failure-missing-input-param.yaml | 24 +-- .../failure-not-matching-with-regex.yaml | 24 +-- manifests/outputs/plugins/regex/success.yaml | 24 +-- ...ailure-invalid-default-emission-value.yaml | 24 +-- .../failure-missing-expected-lifespan.yaml | 24 +-- .../outputs/plugins/sci-embodied/success.yaml | 24 +-- .../sci/failure-invalid-config-value.yaml | 26 ++- .../sci/failure-missing-input-param.yaml | 24 +-- .../outputs/plugins/sci/success.yml.yaml | 24 +-- .../shell/failure-invalid-command.yaml | 26 ++- manifests/outputs/plugins/shell/success.yaml | 26 ++- .../outputs/plugins/subtract/success.yaml | 2 - .../sum/failure-missing-input-param.yaml | 2 - .../sum/failure-missing-output-param.yaml | 24 +-- manifests/outputs/plugins/sum/success.yaml | 24 +-- .../failure-config-start-later-end.yaml | 38 ++-- .../failure-missing-global-config.yaml | 32 ++- .../outputs/plugins/time-sync/success.yaml | 62 +++--- 114 files changed, 968 insertions(+), 1151 deletions(-) diff --git a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml index 9c0416c5e..938c126aa 100644 --- a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml +++ b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml @@ -2,7 +2,6 @@ name: coefficient-demo description: failure with ivalid `global-config.input-parameter` tags: initialize: - outputs: ['yaml'] plugins: coefficient: method: Coefficient diff --git a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml index 795c04492..bfbc24d6e 100644 --- a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml @@ -2,7 +2,6 @@ name: coefficient-demo description: value of output-param is missing tags: initialize: - outputs: ['yaml'] plugins: coefficient: method: Coefficient diff --git a/manifests/examples/builtins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml index 1ce61af1b..bd7d2cc94 100644 --- a/manifests/examples/builtins/coefficient/success.yml +++ b/manifests/examples/builtins/coefficient/success.yml @@ -2,7 +2,6 @@ name: coefficient-demo description: successful path tags: initialize: - outputs: ['yaml'] plugins: coefficient: method: Coefficient diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index fa55623c2..befa110a6 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -2,7 +2,6 @@ name: cloud-metadata description: cloud/instance-type instance type is not supported in the cloud vendor tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 6f247f6c4..1cd9b609a 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -2,7 +2,6 @@ name: cloud-metadata description: failure with invalid `inputs.cloud/vendor` tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index 33c5cc4b1..a01156154 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -2,7 +2,6 @@ name: cloud-metadata description: failing because cloud/vendor is not provided tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml index bd3cfdbb7..52bda60b6 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -2,7 +2,6 @@ name: cloud-metadata description: successful path tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml index 85360f717..8ff802f89 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml @@ -2,7 +2,6 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index 005961ee0..64354be35 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -2,11 +2,10 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup - path: 'builtin' + path: "builtin" global-config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml index 66df39736..c30e11f9c 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml @@ -2,17 +2,16 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup - path: 'builtin' + path: "builtin" global-config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: "cloud/provider" cloud-region: "cloud/region" - output: ['em-zone-id','renamed-em-zone-data'] + output: ["em-zone-id", "renamed-em-zone-data"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml index 005961ee0..64354be35 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml @@ -2,11 +2,10 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup - path: 'builtin' + path: "builtin" global-config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml index b14e57d1d..52d2b660c 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -2,7 +2,6 @@ name: tdp-finder description: failure with `inputs` missing `physical-processor` param tags: initialize: - # outputs: ['yaml'] plugins: tdp-finder: method: CSVLookup diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml index 47f392fcc..f86767455 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -2,7 +2,6 @@ name: tdp-finder description: successful path tags: initialize: - # outputs: ['yaml'] plugins: tdp-finder: method: CSVLookup diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml index 42545b0df..b1953f5ca 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -2,7 +2,6 @@ name: tdp-finder description: successful path tags: initialize: - # outputs: ['yaml'] plugins: tdp-finder: method: CSVLookup diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index 4022d4797..d26272a82 100644 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -2,7 +2,6 @@ name: divide description: denominator is invalid, denominator is tags: initialize: -# outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] divide: method: Divide path: "builtin" diff --git a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 91129714a..01347d943 100644 --- a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -2,7 +2,6 @@ name: divide description: failure when `global-config.denominator` is string tags: initialize: - outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,13 +11,13 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] divide: method: Divide path: "builtin" global-config: numerator: vcpus-allocated - denominator: 'vcpus' + denominator: "vcpus" output: cpu/number-cores tree: children: diff --git a/manifests/examples/builtins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml index 7cf123976..eda63d49d 100644 --- a/manifests/examples/builtins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -2,7 +2,6 @@ name: divide description: success path tags: initialize: -# outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] divide: method: Divide path: "builtin" diff --git a/manifests/examples/builtins/divide/success.yml b/manifests/examples/builtins/divide/success.yml index 6a32d7e2c..02222a6f4 100644 --- a/manifests/examples/builtins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -2,7 +2,6 @@ name: divide description: success path tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] divide: method: Divide path: "builtin" diff --git a/manifests/examples/builtins/exponent/success.yml b/manifests/examples/builtins/exponent/success.yml index c8b59b78c..fe54f30a2 100644 --- a/manifests/examples/builtins/exponent/success.yml +++ b/manifests/examples/builtins/exponent/success.yml @@ -2,15 +2,14 @@ name: exponent demo description: tags: initialize: - # outputs: [yaml] plugins: exponent: method: Exponent - path: 'builtin' + path: "builtin" global-config: - input-parameter: 'cpu/energy' + input-parameter: "cpu/energy" exponent: 2 - output-parameter: 'energy' + output-parameter: "energy" tree: children: child: diff --git a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml index 7be0796b8..eca1dd8a9 100644 --- a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml +++ b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml @@ -1,7 +1,6 @@ name: groupby description: failure when `config->group-by->group` is not an array initialize: - outputs: ['yaml'] plugins: group-by: path: "builtin" diff --git a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml index b87081318..34f31266d 100644 --- a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml +++ b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml @@ -1,7 +1,6 @@ name: groupby -description: +description: initialize: - # outputs: ['yaml'] plugins: group-by: path: "builtin" diff --git a/manifests/examples/builtins/groupby/success.yml b/manifests/examples/builtins/groupby/success.yml index e8e164e91..f3f4161f6 100644 --- a/manifests/examples/builtins/groupby/success.yml +++ b/manifests/examples/builtins/groupby/success.yml @@ -1,7 +1,6 @@ name: groupby description: successful path initialize: - # outputs: ['yaml'] plugins: group-by: path: "builtin" diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml index 00243cc90..fc74d71a6 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml @@ -2,7 +2,6 @@ name: mock-observation-demo description: failure with `global-config->generators->randint->cpu/utilization->min` is greater than `max` tags: initialize: - outputs: ['yaml'] plugins: mock-observations: kind: plugin diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml index ef7bd3dbd..0184d280a 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml @@ -2,7 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: initialize: - # outputs: ['yaml'] plugins: mock-observations: kind: plugin diff --git a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml index 2eaa8f02d..72cd6c347 100644 --- a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml +++ b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml @@ -2,7 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: initialize: - outputs: ['yaml'] plugins: mock-observations: kind: plugin diff --git a/manifests/examples/builtins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml index ac1464322..7767a68bc 100644 --- a/manifests/examples/builtins/mock-observations/success.yml +++ b/manifests/examples/builtins/mock-observations/success.yml @@ -2,7 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: initialize: - # outputs: ['yaml'] plugins: mock-observations: kind: plugin diff --git a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml index 90951d29f..d71f9f096 100644 --- a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml +++ b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml @@ -2,7 +2,6 @@ name: multiply description: failure `inputs` is missing `cpu/energy` parameter tags: initialize: - outputs: ['yaml'] plugins: multiply: method: Multiply diff --git a/manifests/examples/builtins/regex/failure-missing-input-param.yml b/manifests/examples/builtins/regex/failure-missing-input-param.yml index 8ed278e41..f6732c632 100644 --- a/manifests/examples/builtins/regex/failure-missing-input-param.yml +++ b/manifests/examples/builtins/regex/failure-missing-input-param.yml @@ -2,7 +2,6 @@ name: regex description: failure with missing `physical-processor` field from `inputs` tags: initialize: - outputs: ['yaml'] plugins: regex: method: Regex diff --git a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml index 84189dcde..d8818265a 100644 --- a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml +++ b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml @@ -2,7 +2,6 @@ name: regex description: physical processor doesn't match the regex expression tags: initialize: - # outputs: ['yaml'] plugins: regex: method: Regex diff --git a/manifests/examples/builtins/regex/success.yml b/manifests/examples/builtins/regex/success.yml index 0fa735fa6..8e97d4c43 100644 --- a/manifests/examples/builtins/regex/success.yml +++ b/manifests/examples/builtins/regex/success.yml @@ -2,7 +2,6 @@ name: regex description: successful path tags: initialize: - # outputs: ['yaml'] plugins: regex: method: Regex diff --git a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml index 3f12dcdd7..6ccd41a6e 100644 --- a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml +++ b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml @@ -2,7 +2,6 @@ name: sci-embodied description: failure with `defaults.device/emissions-embodied` being string instead of number tags: initialize: - outputs: ['yaml'] plugins: "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor method: SciEmbodied @@ -13,7 +12,7 @@ tree: pipeline: - sci-embodied # duration & config -> embodied defaults: - device/emissions-embodied: 'fail' # gCO2eq + device/emissions-embodied: "fail" # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds resources-reserved: 1 diff --git a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml index 143bc7c95..26edf154c 100644 --- a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml +++ b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml @@ -2,7 +2,6 @@ name: sci-embodied description: missing device/expected-lifespan tags: initialize: - #outputs: ['yaml'] plugins: "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor method: SciEmbodied diff --git a/manifests/examples/builtins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml index 59ce00e52..219e76845 100644 --- a/manifests/examples/builtins/sci-embodied/success.yml +++ b/manifests/examples/builtins/sci-embodied/success.yml @@ -2,7 +2,6 @@ name: sci-embodied description: successful path tags: initialize: - outputs: ['yaml'] plugins: "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor method: SciEmbodied diff --git a/manifests/examples/builtins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml index f5a4def52..798e1debd 100644 --- a/manifests/examples/builtins/sci/failure-invalid-config-value.yml +++ b/manifests/examples/builtins/sci/failure-invalid-config-value.yml @@ -2,7 +2,6 @@ name: sci description: failure with `config.sci.functional-unit` value being number tags: initialize: - outputs: ['yaml'] plugins: sci: kind: plugin diff --git a/manifests/examples/builtins/sci/success.yml b/manifests/examples/builtins/sci/success.yml index cddfe5755..95979fd28 100644 --- a/manifests/examples/builtins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -2,7 +2,6 @@ name: sci description: successful path tags: initialize: - # outputs: ['yaml'] plugins: sci: kind: plugin diff --git a/manifests/examples/builtins/shell/failure-invalid-command.yml b/manifests/examples/builtins/shell/failure-invalid-command.yml index b395d6f4c..2944bc3ea 100644 --- a/manifests/examples/builtins/shell/failure-invalid-command.yml +++ b/manifests/examples/builtins/shell/failure-invalid-command.yml @@ -2,7 +2,6 @@ name: shell description: falure with `global-config.command` being number instead od string tags: initialize: - outputs: ['yaml'] plugins: shell: method: Shell diff --git a/manifests/examples/builtins/subtract/success.yml b/manifests/examples/builtins/subtract/success.yml index bcc27294c..b29d89fd0 100644 --- a/manifests/examples/builtins/subtract/success.yml +++ b/manifests/examples/builtins/subtract/success.yml @@ -2,14 +2,13 @@ name: subtract demo description: tags: initialize: - # outputs: ['yaml'] plugins: subtract: method: Subtract - path: 'builtin' + path: "builtin" global-config: - input-parameters: ['cpu/energy', 'network/energy'] - output-parameter: 'energy/diff' + input-parameters: ["cpu/energy", "network/energy"] + output-parameter: "energy/diff" tree: children: child: @@ -21,4 +20,4 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 cpu/energy: 0.003 - network/energy: 0.001 \ No newline at end of file + network/energy: 0.001 diff --git a/manifests/examples/builtins/sum/failure-missing-input-param.yml b/manifests/examples/builtins/sum/failure-missing-input-param.yml index 2d7c95ae1..65004b679 100644 --- a/manifests/examples/builtins/sum/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-input-param.yml @@ -2,7 +2,6 @@ name: sum description: failure with `inputs[0]` misses one of `global-config.input-parameters` tags: initialize: - outputs: ['yaml'] plugins: sum: method: Sum diff --git a/manifests/examples/builtins/sum/failure-missing-output-param.yml b/manifests/examples/builtins/sum/failure-missing-output-param.yml index c99bc4ee2..b3c21ac3e 100644 --- a/manifests/examples/builtins/sum/failure-missing-output-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-output-param.yml @@ -2,14 +2,13 @@ name: sum description: missing `output-parameter` in global-config tags: initialize: - outputs: ['yaml'] plugins: sum: method: Sum path: "builtin" global-config: input-parameters: ["cpu/energy", "network/energy"] - # output-parameter: "energy" + # output-parameter: "energy" tree: children: child: diff --git a/manifests/examples/builtins/sum/success.yml b/manifests/examples/builtins/sum/success.yml index 454efc9e0..4f5f7452b 100644 --- a/manifests/examples/builtins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -2,7 +2,6 @@ name: sum description: successful path tags: initialize: - # outputs: ['yaml'] plugins: sum: method: Sum diff --git a/manifests/examples/pipelines/generics.yml b/manifests/examples/pipelines/generics.yml index 641bedcb1..c319967f0 100644 --- a/manifests/examples/pipelines/generics.yml +++ b/manifests/examples/pipelines/generics.yml @@ -2,7 +2,6 @@ name: generics description: a pipeline that does arbitrary calculations using our generic arithmetic builtins tags: initialize: - # outputs: [yaml] plugins: "interpolate": method: Interpolation diff --git a/manifests/examples/pipelines/instance-metadata.yml b/manifests/examples/pipelines/instance-metadata.yml index 4ed443985..d79dedb8c 100644 --- a/manifests/examples/pipelines/instance-metadata.yml +++ b/manifests/examples/pipelines/instance-metadata.yml @@ -11,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv query: instance-class: cloud/instance-type - output: '*' + output: "*" extract-processor-name: path: builtin method: Regex @@ -19,8 +19,6 @@ initialize: parameter: cpu-model-name match: /^([^,])+/g output: cpu/name - outputs: - - yaml tree: children: child: diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index 978510f48..ac413d1c6 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -10,17 +10,16 @@ aggregation: type: "both" params: initialize: - # outputs: ['yaml'] plugins: "interpolate": method: Interpolation - path: 'builtin' + 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: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" "cpu-factor-to-wattage": method: Multiply path: builtin diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 168ebd7fe..2cd23920e 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -27,13 +27,13 @@ initialize: max: 99 "interpolate": method: Interpolation - path: 'builtin' + 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: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" "cpu-factor-to-wattage": method: Multiply path: builtin @@ -100,7 +100,6 @@ initialize: "group-by": path: builtin method: GroupBy - # outputs: ['yaml'] tree: children: child-1: diff --git a/manifests/examples/pipelines/sci.yml b/manifests/examples/pipelines/sci.yml index 67c55cd64..927f4eaf5 100644 --- a/manifests/examples/pipelines/sci.yml +++ b/manifests/examples/pipelines/sci.yml @@ -5,13 +5,13 @@ initialize: plugins: interpolate: method: Interpolation - path: 'builtin' + 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: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" cpu-factor-to-wattage: method: Multiply path: builtin @@ -75,8 +75,6 @@ initialize: method: Sci global-config: functional-unit: "component" - outputs: - - yaml tree: children: child-1: diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index fc0ac48b0..2bbfba839 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -8,8 +8,6 @@ aggregation: - dummy-param type: both initialize: - outputs: - - yaml plugins: interpolate: method: Interpolation @@ -21,7 +19,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -85,8 +83,8 @@ initialize: method: TimeSync path: builtin global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true group-by: @@ -102,20 +100,20 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T19:25:34.759Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -167,25 +165,25 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 10 requests: 100 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -217,25 +215,25 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 cpu/utilization: 30 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 28 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 40 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cpu/utilization: 33 cloud/instance-type: A1 diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml index 56be9add7..9576d16c1 100644 --- a/manifests/outputs/bugs/initialize-error-no-config.yaml +++ b/manifests/outputs/bugs/initialize-error-no-config.yaml @@ -4,8 +4,6 @@ description: >- required config tags: null initialize: - outputs: - - yaml plugins: interpolate: method: Interpolation @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T19:45:41.936Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml index e2ee4d616..0b907488c 100644 --- a/manifests/outputs/bugs/initialize-error-no-path.yaml +++ b/manifests/outputs/bugs/initialize-error-no-path.yaml @@ -15,15 +15,13 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor - outputs: - - yaml execution: status: fail command: >- @@ -34,21 +32,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T19:57:11.499Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml index 208010e00..4e0eb4c54 100644 --- a/manifests/outputs/bugs/initialize-error-no-plugins.yaml +++ b/manifests/outputs/bugs/initialize-error-no-plugins.yaml @@ -5,8 +5,6 @@ description: >- tags: null initialize: plugins: null - outputs: - - yaml execution: status: fail command: >- @@ -17,21 +15,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T19:52:35.214Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml index dd339eb4f..310a7d0ae 100644 --- a/manifests/outputs/bugs/input-error-missing-duration.yaml +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -15,15 +15,13 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor - outputs: - - yaml execution: status: fail command: >- @@ -34,21 +32,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T19:59:58.987Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml index fedf856fb..56ed12cee 100644 --- a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -2,8 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: null initialize: - outputs: - - yaml plugins: mock-observations: kind: plugin @@ -37,21 +35,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:02:22.596Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -72,7 +70,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: 'RangeError: Maximum call stack size exceeded' + error: "RangeError: Maximum call stack size exceeded" tree: children: child: diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml index 21fc5e668..aaf987300 100644 --- a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -15,15 +15,13 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor - outputs: - - yaml execution: status: fail command: >- @@ -34,21 +32,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:06:51.254Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml index a37517432..1fd747ce9 100644 --- a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -4,8 +4,6 @@ description: >- in a pipeline tags: null initialize: - outputs: - - yaml plugins: interpolate: method: Interpolation @@ -17,7 +15,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -34,21 +32,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:08:51.260Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml index fe59b03d8..5a47d8d3f 100644 --- a/manifests/outputs/bugs/pipeline-ordering-error.yaml +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -4,8 +4,6 @@ description: >- pipeline (before its inputs are generated) tags: null initialize: - outputs: - - yaml plugins: interpolate: method: Interpolation @@ -17,7 +15,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -71,21 +69,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:14:29.109Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -129,25 +127,25 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml index e0a50cd90..5c93301e2 100644 --- a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml +++ b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml @@ -4,8 +4,6 @@ description: >- `resources-total` issue tags: null initialize: - outputs: - - yaml plugins: sci-embodied: method: SciEmbodied @@ -20,21 +18,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:17:30.390Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/divide.yaml b/manifests/outputs/divide.yaml index e0875c420..85c681d1f 100644 --- a/manifests/outputs/divide.yaml +++ b/manifests/outputs/divide.yaml @@ -21,8 +21,6 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - outputs: - - yaml execution: command: >- /home/joe/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -35,16 +33,16 @@ execution: node-version: 21.4.0 date-time: 2024-07-03T14:02:26.789Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index 1a737e742..ad145646f 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -5,8 +5,6 @@ aggregation: - test type: both initialize: - outputs: - - yaml plugins: cloud-metadata: path: builtin @@ -29,21 +27,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:25:17.348Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -77,24 +75,24 @@ tree: children: server-1: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 59 server-2: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 82d6759bc..09b2e9338 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -5,8 +5,6 @@ aggregation: - cpu/utilization type: both initialize: - outputs: - - yaml plugins: cloud-metadata: path: builtin @@ -29,21 +27,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:26:58.250Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -77,23 +75,23 @@ tree: children: server-1: inputs: - - timestamp: '2024-01-26 00:00:00' + - timestamp: "2024-01-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 59 server-2: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws - - timestamp: '2024-02-26 00:15:00' + - timestamp: "2024-02-26 00:15:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index 3110af664..2241815d2 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -17,8 +17,6 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -28,21 +26,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:28:27.168Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -74,24 +72,24 @@ tree: children: server-1: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 59 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws @@ -101,24 +99,24 @@ tree: cpu/utilization: 74 server-2: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 27 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 1527a9280..0c7b32b6a 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -17,8 +17,6 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -28,21 +26,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:32:47.459Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -74,24 +72,24 @@ tree: children: server-1: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 59 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws @@ -99,24 +97,24 @@ tree: vcpus-allocated: 2 server-2: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 27 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws @@ -124,28 +122,28 @@ tree: vcpus-allocated: 2 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index 062cd9932..b58ac9031 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -17,8 +17,6 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -28,21 +26,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-01T20:34:35.981Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -74,24 +72,24 @@ tree: children: server-1: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 59 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 89 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws @@ -101,24 +99,24 @@ tree: cpu/utilization: 74 server-2: inputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 27 outputs: - - timestamp: '2024-02-26 00:00:00' + - timestamp: "2024-02-26 00:00:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws cpu/utilization: 24 vcpus-allocated: 2 - - timestamp: '2024-02-26 00:05:00' + - timestamp: "2024-02-26 00:05:00" duration: 300 cloud/instance-type: m5n.large cloud/vendor: aws @@ -128,28 +126,28 @@ tree: cpu/utilization: 25.5 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 outputs: - cpu/utilization: 56.5 - timestamp: '2024-02-26 00:00:00' + timestamp: "2024-02-26 00:00:00" duration: 300 - cpu/utilization: 43 - timestamp: '2024-02-26 00:05:00' + timestamp: "2024-02-26 00:05:00" duration: 300 aggregated: cpu/utilization: 49.75 diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml index 130c4361e..f85725c5c 100644 --- a/manifests/outputs/pipelines/cloud-metadata-divide.yaml +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -21,8 +21,6 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -32,21 +30,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:13:05.868Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml index 5585d4c42..44b749342 100644 --- a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml +++ b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml @@ -46,8 +46,6 @@ initialize: cpu/utilization: min: 1 max: 99 - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -57,21 +55,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:21:45.561Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -108,7 +106,7 @@ tree: children: Standard_E64_v3: inputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -116,7 +114,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 93 - - timestamp: '2024-03-05T00:05:00.000Z' + - timestamp: "2024-03-05T00:05:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -124,7 +122,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 6 - - timestamp: '2024-03-05T00:10:00.000Z' + - timestamp: "2024-03-05T00:10:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -132,7 +130,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 6 - - timestamp: '2024-03-05T00:15:00.000Z' + - timestamp: "2024-03-05T00:15:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -140,7 +138,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 3 - - timestamp: '2024-03-05T00:20:00.000Z' + - timestamp: "2024-03-05T00:20:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -148,7 +146,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 83 - - timestamp: '2024-03-05T00:25:00.000Z' + - timestamp: "2024-03-05T00:25:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -156,7 +154,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 85 - - timestamp: '2024-03-05T00:30:00.000Z' + - timestamp: "2024-03-05T00:30:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -164,7 +162,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 8 - - timestamp: '2024-03-05T00:35:00.000Z' + - timestamp: "2024-03-05T00:35:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -172,7 +170,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 59 - - timestamp: '2024-03-05T00:40:00.000Z' + - timestamp: "2024-03-05T00:40:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -180,7 +178,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 55 - - timestamp: '2024-03-05T00:45:00.000Z' + - timestamp: "2024-03-05T00:45:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -188,7 +186,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 85 - - timestamp: '2024-03-05T00:50:00.000Z' + - timestamp: "2024-03-05T00:50:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -196,7 +194,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 52 - - timestamp: '2024-03-05T00:55:00.000Z' + - timestamp: "2024-03-05T00:55:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -205,7 +203,7 @@ tree: cloud/vendor: azure cpu/utilization: 54 outputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -214,7 +212,7 @@ tree: cloud/vendor: azure cpu/utilization: 93 cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' + - timestamp: "2024-03-05T00:05:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -223,7 +221,7 @@ tree: cloud/vendor: azure cpu/utilization: 6 cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' + - timestamp: "2024-03-05T00:10:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -232,7 +230,7 @@ tree: cloud/vendor: azure cpu/utilization: 6 cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' + - timestamp: "2024-03-05T00:15:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -241,7 +239,7 @@ tree: cloud/vendor: azure cpu/utilization: 3 cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' + - timestamp: "2024-03-05T00:20:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -250,7 +248,7 @@ tree: cloud/vendor: azure cpu/utilization: 83 cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' + - timestamp: "2024-03-05T00:25:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -259,7 +257,7 @@ tree: cloud/vendor: azure cpu/utilization: 85 cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' + - timestamp: "2024-03-05T00:30:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -268,7 +266,7 @@ tree: cloud/vendor: azure cpu/utilization: 8 cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' + - timestamp: "2024-03-05T00:35:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -277,7 +275,7 @@ tree: cloud/vendor: azure cpu/utilization: 59 cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' + - timestamp: "2024-03-05T00:40:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -286,7 +284,7 @@ tree: cloud/vendor: azure cpu/utilization: 55 cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' + - timestamp: "2024-03-05T00:45:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -295,7 +293,7 @@ tree: cloud/vendor: azure cpu/utilization: 85 cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' + - timestamp: "2024-03-05T00:50:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -304,7 +302,7 @@ tree: cloud/vendor: azure cpu/utilization: 52 cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' + - timestamp: "2024-03-05T00:55:00.000Z" duration: 300 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -317,40 +315,40 @@ tree: cpu/utilization: 49.083333333333336 outputs: - cpu/utilization: 93 - timestamp: '2024-03-05T00:00:00.000Z' + timestamp: "2024-03-05T00:00:00.000Z" duration: 300 - cpu/utilization: 6 - timestamp: '2024-03-05T00:05:00.000Z' + timestamp: "2024-03-05T00:05:00.000Z" duration: 300 - cpu/utilization: 6 - timestamp: '2024-03-05T00:10:00.000Z' + timestamp: "2024-03-05T00:10:00.000Z" duration: 300 - cpu/utilization: 3 - timestamp: '2024-03-05T00:15:00.000Z' + timestamp: "2024-03-05T00:15:00.000Z" duration: 300 - cpu/utilization: 83 - timestamp: '2024-03-05T00:20:00.000Z' + timestamp: "2024-03-05T00:20:00.000Z" duration: 300 - cpu/utilization: 85 - timestamp: '2024-03-05T00:25:00.000Z' + timestamp: "2024-03-05T00:25:00.000Z" duration: 300 - cpu/utilization: 8 - timestamp: '2024-03-05T00:30:00.000Z' + timestamp: "2024-03-05T00:30:00.000Z" duration: 300 - cpu/utilization: 59 - timestamp: '2024-03-05T00:35:00.000Z' + timestamp: "2024-03-05T00:35:00.000Z" duration: 300 - cpu/utilization: 55 - timestamp: '2024-03-05T00:40:00.000Z' + timestamp: "2024-03-05T00:40:00.000Z" duration: 300 - cpu/utilization: 85 - timestamp: '2024-03-05T00:45:00.000Z' + timestamp: "2024-03-05T00:45:00.000Z" duration: 300 - cpu/utilization: 52 - timestamp: '2024-03-05T00:50:00.000Z' + timestamp: "2024-03-05T00:50:00.000Z" duration: 300 - cpu/utilization: 54 - timestamp: '2024-03-05T00:55:00.000Z' + timestamp: "2024-03-05T00:55:00.000Z" duration: 300 aggregated: cpu/utilization: 49.083333333333336 @@ -358,7 +356,7 @@ tree: children: Standard_E64_v3: inputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -366,7 +364,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 4 - - timestamp: '2024-03-05T00:05:00.000Z' + - timestamp: "2024-03-05T00:05:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -374,7 +372,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 63 - - timestamp: '2024-03-05T00:10:00.000Z' + - timestamp: "2024-03-05T00:10:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -382,7 +380,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 38 - - timestamp: '2024-03-05T00:15:00.000Z' + - timestamp: "2024-03-05T00:15:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -390,7 +388,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 10 - - timestamp: '2024-03-05T00:20:00.000Z' + - timestamp: "2024-03-05T00:20:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -398,7 +396,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 88 - - timestamp: '2024-03-05T00:25:00.000Z' + - timestamp: "2024-03-05T00:25:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -406,7 +404,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 81 - - timestamp: '2024-03-05T00:30:00.000Z' + - timestamp: "2024-03-05T00:30:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -414,7 +412,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 17 - - timestamp: '2024-03-05T00:35:00.000Z' + - timestamp: "2024-03-05T00:35:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -422,7 +420,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 11 - - timestamp: '2024-03-05T00:40:00.000Z' + - timestamp: "2024-03-05T00:40:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -430,7 +428,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 76 - - timestamp: '2024-03-05T00:45:00.000Z' + - timestamp: "2024-03-05T00:45:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -438,7 +436,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 63 - - timestamp: '2024-03-05T00:50:00.000Z' + - timestamp: "2024-03-05T00:50:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -446,7 +444,7 @@ tree: geolocation: 37.7749,-122.4194 cloud/vendor: azure cpu/utilization: 81 - - timestamp: '2024-03-05T00:55:00.000Z' + - timestamp: "2024-03-05T00:55:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -455,7 +453,7 @@ tree: cloud/vendor: azure cpu/utilization: 74 outputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -464,7 +462,7 @@ tree: cloud/vendor: azure cpu/utilization: 4 cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' + - timestamp: "2024-03-05T00:05:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -473,7 +471,7 @@ tree: cloud/vendor: azure cpu/utilization: 63 cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' + - timestamp: "2024-03-05T00:10:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -482,7 +480,7 @@ tree: cloud/vendor: azure cpu/utilization: 38 cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' + - timestamp: "2024-03-05T00:15:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -491,7 +489,7 @@ tree: cloud/vendor: azure cpu/utilization: 10 cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' + - timestamp: "2024-03-05T00:20:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -500,7 +498,7 @@ tree: cloud/vendor: azure cpu/utilization: 88 cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' + - timestamp: "2024-03-05T00:25:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -509,7 +507,7 @@ tree: cloud/vendor: azure cpu/utilization: 81 cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' + - timestamp: "2024-03-05T00:30:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -518,7 +516,7 @@ tree: cloud/vendor: azure cpu/utilization: 17 cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' + - timestamp: "2024-03-05T00:35:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -527,7 +525,7 @@ tree: cloud/vendor: azure cpu/utilization: 11 cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' + - timestamp: "2024-03-05T00:40:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -536,7 +534,7 @@ tree: cloud/vendor: azure cpu/utilization: 76 cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' + - timestamp: "2024-03-05T00:45:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -545,7 +543,7 @@ tree: cloud/vendor: azure cpu/utilization: 63 cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' + - timestamp: "2024-03-05T00:50:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -554,7 +552,7 @@ tree: cloud/vendor: azure cpu/utilization: 81 cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' + - timestamp: "2024-03-05T00:55:00.000Z" duration: 300 name: server-2 cloud/instance-type: Standard_E64_v3 @@ -567,79 +565,79 @@ tree: cpu/utilization: 50.5 outputs: - cpu/utilization: 4 - timestamp: '2024-03-05T00:00:00.000Z' + timestamp: "2024-03-05T00:00:00.000Z" duration: 300 - cpu/utilization: 63 - timestamp: '2024-03-05T00:05:00.000Z' + timestamp: "2024-03-05T00:05:00.000Z" duration: 300 - cpu/utilization: 38 - timestamp: '2024-03-05T00:10:00.000Z' + timestamp: "2024-03-05T00:10:00.000Z" duration: 300 - cpu/utilization: 10 - timestamp: '2024-03-05T00:15:00.000Z' + timestamp: "2024-03-05T00:15:00.000Z" duration: 300 - cpu/utilization: 88 - timestamp: '2024-03-05T00:20:00.000Z' + timestamp: "2024-03-05T00:20:00.000Z" duration: 300 - cpu/utilization: 81 - timestamp: '2024-03-05T00:25:00.000Z' + timestamp: "2024-03-05T00:25:00.000Z" duration: 300 - cpu/utilization: 17 - timestamp: '2024-03-05T00:30:00.000Z' + timestamp: "2024-03-05T00:30:00.000Z" duration: 300 - cpu/utilization: 11 - timestamp: '2024-03-05T00:35:00.000Z' + timestamp: "2024-03-05T00:35:00.000Z" duration: 300 - cpu/utilization: 76 - timestamp: '2024-03-05T00:40:00.000Z' + timestamp: "2024-03-05T00:40:00.000Z" duration: 300 - cpu/utilization: 63 - timestamp: '2024-03-05T00:45:00.000Z' + timestamp: "2024-03-05T00:45:00.000Z" duration: 300 - cpu/utilization: 81 - timestamp: '2024-03-05T00:50:00.000Z' + timestamp: "2024-03-05T00:50:00.000Z" duration: 300 - cpu/utilization: 74 - timestamp: '2024-03-05T00:55:00.000Z' + timestamp: "2024-03-05T00:55:00.000Z" duration: 300 aggregated: cpu/utilization: 50.5 outputs: - cpu/utilization: 48.5 - timestamp: '2024-03-05T00:00:00.000Z' + timestamp: "2024-03-05T00:00:00.000Z" duration: 300 - cpu/utilization: 34.5 - timestamp: '2024-03-05T00:05:00.000Z' + timestamp: "2024-03-05T00:05:00.000Z" duration: 300 - cpu/utilization: 22 - timestamp: '2024-03-05T00:10:00.000Z' + timestamp: "2024-03-05T00:10:00.000Z" duration: 300 - cpu/utilization: 6.5 - timestamp: '2024-03-05T00:15:00.000Z' + timestamp: "2024-03-05T00:15:00.000Z" duration: 300 - cpu/utilization: 85.5 - timestamp: '2024-03-05T00:20:00.000Z' + timestamp: "2024-03-05T00:20:00.000Z" duration: 300 - cpu/utilization: 83 - timestamp: '2024-03-05T00:25:00.000Z' + timestamp: "2024-03-05T00:25:00.000Z" duration: 300 - cpu/utilization: 12.5 - timestamp: '2024-03-05T00:30:00.000Z' + timestamp: "2024-03-05T00:30:00.000Z" duration: 300 - cpu/utilization: 35 - timestamp: '2024-03-05T00:35:00.000Z' + timestamp: "2024-03-05T00:35:00.000Z" duration: 300 - cpu/utilization: 65.5 - timestamp: '2024-03-05T00:40:00.000Z' + timestamp: "2024-03-05T00:40:00.000Z" duration: 300 - cpu/utilization: 74 - timestamp: '2024-03-05T00:45:00.000Z' + timestamp: "2024-03-05T00:45:00.000Z" duration: 300 - cpu/utilization: 66.5 - timestamp: '2024-03-05T00:50:00.000Z' + timestamp: "2024-03-05T00:50:00.000Z" duration: 300 - cpu/utilization: 64 - timestamp: '2024-03-05T00:55:00.000Z' + timestamp: "2024-03-05T00:55:00.000Z" duration: 300 aggregated: cpu/utilization: 49.791666666666664 diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml index 4783dffde..a97006df9 100644 --- a/manifests/outputs/pipelines/mock-obs-groupby.yaml +++ b/manifests/outputs/pipelines/mock-obs-groupby.yaml @@ -6,8 +6,8 @@ initialize: path: builtin method: MockObservations global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' + timestamp-from: "2024-03-05T00:00:00.000Z" + timestamp-to: "2024-03-05T00:01:00.000Z" duration: 10 components: - name: server-1 @@ -26,8 +26,6 @@ initialize: group-by: path: builtin method: GroupBy - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -37,21 +35,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:27:34.757Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -88,42 +86,42 @@ tree: children: server-1: inputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure cpu/utilization: 12 - - timestamp: '2024-03-05T00:00:10.000Z' + - timestamp: "2024-03-05T00:00:10.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure cpu/utilization: 71 - - timestamp: '2024-03-05T00:00:20.000Z' + - timestamp: "2024-03-05T00:00:20.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure cpu/utilization: 75 - - timestamp: '2024-03-05T00:00:30.000Z' + - timestamp: "2024-03-05T00:00:30.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure cpu/utilization: 39 - - timestamp: '2024-03-05T00:00:40.000Z' + - timestamp: "2024-03-05T00:00:40.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure cpu/utilization: 42 - - timestamp: '2024-03-05T00:00:50.000Z' + - timestamp: "2024-03-05T00:00:50.000Z" duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 @@ -134,42 +132,42 @@ tree: children: server-2: inputs: - - timestamp: '2024-03-05T00:00:00.000Z' + - timestamp: "2024-03-05T00:00:00.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure cpu/utilization: 14 - - timestamp: '2024-03-05T00:00:10.000Z' + - timestamp: "2024-03-05T00:00:10.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure cpu/utilization: 80 - - timestamp: '2024-03-05T00:00:20.000Z' + - timestamp: "2024-03-05T00:00:20.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure cpu/utilization: 53 - - timestamp: '2024-03-05T00:00:30.000Z' + - timestamp: "2024-03-05T00:00:30.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure cpu/utilization: 10 - - timestamp: '2024-03-05T00:00:40.000Z' + - timestamp: "2024-03-05T00:00:40.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure cpu/utilization: 40 - - timestamp: '2024-03-05T00:00:50.000Z' + - timestamp: "2024-03-05T00:00:50.000Z" duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index 271340c2b..c22a14c3e 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -30,7 +30,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -78,12 +78,10 @@ initialize: path: builtin method: TimeSync global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -93,21 +91,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:29:47.787Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -145,28 +143,28 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 10 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -180,7 +178,7 @@ tree: cpu-energy-raw: 0.0000563888888888889 vcpu-ratio: 14.399999999999999 cpu-energy-kwh: 0.000007048611111111113 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -194,7 +192,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 6.171428571428571 cpu-energy-kwh: 0.000006675347222222222 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -208,7 +206,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 3.9619047619047616 cpu-energy-kwh: 0.0000064887152777777775 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -222,7 +220,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 1.3333333333333333 cpu-energy-kwh: 0.000006488715277777778 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -236,7 +234,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 1.3333333333333333 cpu-energy-kwh: 0.000006488715277777778 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -250,7 +248,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 1.3333333333333333 cpu-energy-kwh: 0.000006488715277777778 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -264,7 +262,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 1.3333333333333333 cpu-energy-kwh: 0.000006488715277777778 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -278,7 +276,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 1.3333333333333333 cpu-energy-kwh: 0.000006488715277777778 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -292,7 +290,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 0.8 cpu-energy-kwh: 0.000003893229166666667 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -306,7 +304,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 0 cpu-energy-kwh: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -320,7 +318,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 0 cpu-energy-kwh: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -334,7 +332,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 0 cpu-energy-kwh: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west diff --git a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml index ba10eaee3..78af0bab9 100644 --- a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml +++ b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml @@ -2,8 +2,6 @@ name: coefficient-demo description: failure with ivalid `global-config.input-parameter` tags: null initialize: - outputs: - - yaml plugins: coefficient: method: Coefficient @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:41:49.144Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml index dd2f6c952..80a4b0913 100644 --- a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml @@ -2,8 +2,6 @@ name: coefficient-demo description: value of output-param is missing tags: null initialize: - outputs: - - yaml plugins: coefficient: method: Coefficient diff --git a/manifests/outputs/plugins/coefficient/success.yaml b/manifests/outputs/plugins/coefficient/success.yaml index 86300012c..c560d0411 100644 --- a/manifests/outputs/plugins/coefficient/success.yaml +++ b/manifests/outputs/plugins/coefficient/success.yaml @@ -10,8 +10,6 @@ initialize: input-parameter: carbon coefficient: 3 output-parameter: carbon-product - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:37:08.297Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index fa55623c2..befa110a6 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -2,7 +2,6 @@ name: cloud-metadata description: cloud/instance-type instance type is not supported in the cloud vendor tags: initialize: - # outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index c474c91fe..1cd9b609a 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -2,7 +2,6 @@ name: cloud-metadata description: failure with invalid `inputs.cloud/vendor` tags: initialize: - #outputs: ['yaml'] plugins: cloud-metadata: path: builtin @@ -12,7 +11,7 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: child: diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 943416663..724a47a6d 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -2,8 +2,6 @@ name: cloud-metadata description: failing because cloud/vendor is not provided tags: null initialize: - outputs: - - yaml plugins: cloud-metadata: path: builtin diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml index 25c8db6e3..7dcbac49c 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -14,8 +14,6 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -25,21 +23,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:21:45.504Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml index cad931fd1..4db0b6b2f 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -2,8 +2,6 @@ name: csv-lookup-demo description: null tags: null initialize: - outputs: - - yaml plugins: cloud-metadata: method: CSVLookup @@ -14,7 +12,7 @@ initialize: query: cloud-provider: nonexistant cloud-region: cloud/region - output: '*' + output: "*" execution: status: fail command: >- @@ -26,21 +24,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:26:59.352Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml index ad5ab9ec8..bdaa3b6ad 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -2,8 +2,6 @@ name: csv-lookup-demo description: null tags: null initialize: - outputs: - - yaml plugins: cloud-metadata: method: CSVLookup @@ -25,21 +23,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:26:09.874Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml index 77aeecd66..e7e04b535 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml @@ -15,8 +15,6 @@ initialize: output: - em-zone-id - renamed-em-zone-data - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -26,21 +24,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:24:10.894Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml index 10bb9a637..e8d31f661 100644 --- a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml @@ -12,9 +12,7 @@ initialize: query: cloud-provider: cloud/provider cloud-region: cloud/region - output: '*' - outputs: - - yaml + output: "*" execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -24,21 +22,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:23:15.965Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml index 56b6c2630..f842a3756 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -2,8 +2,6 @@ name: tdp-finder description: failure with `inputs` missing `physical-processor` param tags: null initialize: - outputs: - - yaml plugins: tdp-finder: method: CSVLookup @@ -25,21 +23,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:30:11.973Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml index 888df1ce7..7ccf90ff6 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -2,8 +2,6 @@ name: tdp-finder description: successful path tags: null initialize: - outputs: - - yaml plugins: tdp-finder: method: CSVLookup @@ -25,21 +23,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:29:16.211Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml index bf12d4892..249d2d3f4 100644 --- a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml @@ -12,8 +12,6 @@ initialize: query: name: physical-processor output: tdp - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -23,21 +21,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:28:19.790Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml index 299cc1ade..8b98a5a27 100644 --- a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml +++ b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml @@ -2,8 +2,6 @@ name: divide description: failure when `global-config.denominator` is string tags: null initialize: - outputs: - - yaml plugins: divide: method: Divide @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T06:02:25.409Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml index 6aa908327..41ac4b1ea 100644 --- a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml @@ -2,8 +2,6 @@ name: divide description: success path tags: null initialize: - outputs: - - yaml plugins: divide: method: Divide @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:49:51.802Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml index 5617fdbf9..2384df53b 100644 --- a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml +++ b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml @@ -21,8 +21,6 @@ initialize: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -32,21 +30,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T06:05:58.040Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/divide/success.yaml b/manifests/outputs/plugins/divide/success.yaml index 3c741121f..3e43a85de 100644 --- a/manifests/outputs/plugins/divide/success.yaml +++ b/manifests/outputs/plugins/divide/success.yaml @@ -21,8 +21,6 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -32,21 +30,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T05:43:34.055Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/exponent/success.yaml b/manifests/outputs/plugins/exponent/success.yaml index 1a8588693..7ad94e5bc 100644 --- a/manifests/outputs/plugins/exponent/success.yaml +++ b/manifests/outputs/plugins/exponent/success.yaml @@ -10,8 +10,6 @@ initialize: input-parameter: cpu/energy exponent: 2 output-parameter: energy - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:07:19.737Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml index 3b188a07d..22506aa2e 100644 --- a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml +++ b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml @@ -1,8 +1,6 @@ name: groupby description: failure when `config->group-by->group` is not an array initialize: - outputs: - - yaml plugins: group-by: path: builtin @@ -17,21 +15,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:11:23.166Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml index ae91af1e1..e6b2ea8ea 100644 --- a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml +++ b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml @@ -1,8 +1,6 @@ name: groupby description: null initialize: - outputs: - - yaml plugins: group-by: path: builtin @@ -17,21 +15,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:10:00.820Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -52,7 +50,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: 'InvalidGroupingError: Invalid group cloud/instance-type.' + error: "InvalidGroupingError: Invalid group cloud/instance-type." tree: children: my-app: diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml index 04d54837b..bd5188728 100644 --- a/manifests/outputs/plugins/groupby/success.yaml +++ b/manifests/outputs/plugins/groupby/success.yaml @@ -5,8 +5,6 @@ initialize: group-by: path: builtin method: GroupBy - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -16,21 +14,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:08:31.858Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/interpolation/interpolation.yaml b/manifests/outputs/plugins/interpolation/interpolation.yaml index 9e3c45e4d..8eff7b1f1 100644 --- a/manifests/outputs/plugins/interpolation/interpolation.yaml +++ b/manifests/outputs/plugins/interpolation/interpolation.yaml @@ -13,15 +13,13 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 - 1.02 input-parameter: cpu/utilization output-parameter: result - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -31,21 +29,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:14:18.033Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/interpolation/success.yaml b/manifests/outputs/plugins/interpolation/success.yaml index bad3425f9..cbfc92011 100644 --- a/manifests/outputs/plugins/interpolation/success.yaml +++ b/manifests/outputs/plugins/interpolation/success.yaml @@ -13,15 +13,13 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 - 1.02 input-parameter: cpu/utilization output-parameter: result - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -31,21 +29,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:13:22.946Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml index d79f394f5..fda4ddba7 100644 --- a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -4,8 +4,6 @@ description: >- greater than `max` tags: null initialize: - outputs: - - yaml plugins: mock-observations: kind: plugin @@ -40,21 +38,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:19:22.233Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml index 3667dff6c..cfb073fc6 100644 --- a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -2,8 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: null initialize: - outputs: - - yaml plugins: mock-observations: kind: plugin @@ -38,21 +36,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:18:11.486Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml index b8599cb08..184e86230 100644 --- a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml +++ b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -2,8 +2,6 @@ name: mock-observation-demo description: a manifest demonstrating how to use the mock observations feature tags: null initialize: - outputs: - - yaml plugins: mock-observations: kind: plugin @@ -37,21 +35,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:17:01.277Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/plugins/mock-observations/success.yaml index cacd16cad..4f8334c07 100644 --- a/manifests/outputs/plugins/mock-observations/success.yaml +++ b/manifests/outputs/plugins/mock-observations/success.yaml @@ -24,8 +24,6 @@ initialize: memory/utilization: min: 1 max: 99 - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -35,21 +33,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:15:43.108Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -78,140 +76,140 @@ tree: - mock-observations inputs: null outputs: - - timestamp: '2023-07-06T00:00:00.000Z' + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 81 memory/utilization: 63 - - timestamp: '2023-07-06T00:01:00.000Z' + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 92 memory/utilization: 63 - - timestamp: '2023-07-06T00:02:00.000Z' + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 63 memory/utilization: 95 - - timestamp: '2023-07-06T00:03:00.000Z' + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 37 memory/utilization: 13 - - timestamp: '2023-07-06T00:04:00.000Z' + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 28 memory/utilization: 50 - - timestamp: '2023-07-06T00:05:00.000Z' + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 98 memory/utilization: 29 - - timestamp: '2023-07-06T00:06:00.000Z' + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 10 memory/utilization: 93 - - timestamp: '2023-07-06T00:07:00.000Z' + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 84 memory/utilization: 37 - - timestamp: '2023-07-06T00:08:00.000Z' + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 10 memory/utilization: 30 - - timestamp: '2023-07-06T00:09:00.000Z' + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: 50 memory/utilization: 10 - - timestamp: '2023-07-06T00:00:00.000Z' + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 97 memory/utilization: 89 - - timestamp: '2023-07-06T00:01:00.000Z' + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 61 memory/utilization: 83 - - timestamp: '2023-07-06T00:02:00.000Z' + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 86 memory/utilization: 52 - - timestamp: '2023-07-06T00:03:00.000Z' + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 17 memory/utilization: 60 - - timestamp: '2023-07-06T00:04:00.000Z' + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 53 memory/utilization: 84 - - timestamp: '2023-07-06T00:05:00.000Z' + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 38 memory/utilization: 58 - - timestamp: '2023-07-06T00:06:00.000Z' + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 4 memory/utilization: 39 - - timestamp: '2023-07-06T00:07:00.000Z' + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 89 memory/utilization: 52 - - timestamp: '2023-07-06T00:08:00.000Z' + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: 38 memory/utilization: 16 - - timestamp: '2023-07-06T00:09:00.000Z' + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west diff --git a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml index 1ef59959d..8c12556fb 100644 --- a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml +++ b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml @@ -2,8 +2,6 @@ name: multiply description: failure `inputs` is missing `cpu/energy` parameter tags: null initialize: - outputs: - - yaml plugins: multiply: method: Multiply @@ -23,21 +21,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:23:15.185Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml index 76c3d93d3..b9b2470c3 100644 --- a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml +++ b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml @@ -11,8 +11,6 @@ initialize: - cpu/energy - network/energy output-parameter: energy-product - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:22:04.324Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/multiply/success.yaml b/manifests/outputs/plugins/multiply/success.yaml index 60546f50e..c2925f183 100644 --- a/manifests/outputs/plugins/multiply/success.yaml +++ b/manifests/outputs/plugins/multiply/success.yaml @@ -11,8 +11,6 @@ initialize: - cpu/energy - network/energy output-parameter: energy-product - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T19:20:34.016Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml index 8399ac20e..5ea08772c 100644 --- a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml @@ -2,8 +2,6 @@ name: regex description: failure with missing `physical-processor` field from `inputs` tags: null initialize: - outputs: - - yaml plugins: regex: method: Regex @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:26:07.477Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml index 4b1ae47d6..d07bc0484 100644 --- a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml +++ b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml @@ -2,8 +2,6 @@ name: regex description: physical processor doesn't match the regex expression tags: null initialize: - outputs: - - yaml plugins: regex: method: Regex @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:24:39.241Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/regex/success.yaml b/manifests/outputs/plugins/regex/success.yaml index 763cd4093..745e3cf71 100644 --- a/manifests/outputs/plugins/regex/success.yaml +++ b/manifests/outputs/plugins/regex/success.yaml @@ -10,8 +10,6 @@ initialize: parameter: physical-processor match: ^(.*), output: cpu/name - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:23:25.744Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml index a3df4f806..b1784d516 100644 --- a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml +++ b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -4,8 +4,6 @@ description: >- number tags: null initialize: - outputs: - - yaml plugins: sci-embodied: method: SciEmbodied @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:49:08.280Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml index 073b2cb45..5959d2b21 100644 --- a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml +++ b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml @@ -2,8 +2,6 @@ name: sci-embodied description: missing device/expected-lifespan tags: null initialize: - outputs: - - yaml plugins: sci-embodied: method: SciEmbodied @@ -18,21 +16,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:42:51.951Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sci-embodied/success.yaml b/manifests/outputs/plugins/sci-embodied/success.yaml index 5f74a121e..f7c4e8dc0 100644 --- a/manifests/outputs/plugins/sci-embodied/success.yaml +++ b/manifests/outputs/plugins/sci-embodied/success.yaml @@ -6,8 +6,6 @@ initialize: sci-embodied: path: builtin method: SciEmbodied - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -17,21 +15,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:42:03.186Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml index 61c424e91..463a855da 100644 --- a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml +++ b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml @@ -2,8 +2,6 @@ name: sci description: failure with `config.sci.functional-unit` value being number tags: null initialize: - outputs: - - yaml plugins: sci: kind: plugin @@ -19,21 +17,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:38:15.858Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -54,7 +52,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: 'InputValidationError: Required' + error: "InputValidationError: Required" tree: children: child: diff --git a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml index 656f21c1d..0aed8267c 100644 --- a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml @@ -2,8 +2,6 @@ name: sci description: missing input value (carbon-embodied) tags: null initialize: - outputs: - - yaml plugins: sci: kind: plugin @@ -21,21 +19,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:36:10.588Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sci/success.yml.yaml b/manifests/outputs/plugins/sci/success.yml.yaml index bd7b81f0c..e08d7e27e 100644 --- a/manifests/outputs/plugins/sci/success.yml.yaml +++ b/manifests/outputs/plugins/sci/success.yml.yaml @@ -8,8 +8,6 @@ initialize: method: Sci global-config: functional-unit: requests - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -19,21 +17,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:35:12.024Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/shell/failure-invalid-command.yaml b/manifests/outputs/plugins/shell/failure-invalid-command.yaml index f9ec8894b..ad11fecad 100644 --- a/manifests/outputs/plugins/shell/failure-invalid-command.yaml +++ b/manifests/outputs/plugins/shell/failure-invalid-command.yaml @@ -2,8 +2,6 @@ name: shell description: falure with `global-config.command` being number instead od string tags: null initialize: - outputs: - - yaml plugins: shell: method: Shell @@ -20,21 +18,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:51:36.186Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -64,7 +62,7 @@ tree: pipeline: - shell inputs: - - timestamp: '2023-11-02T10:35:31.820Z' + - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 cpu/energy: 0.002 memory/energy: 0.000005 diff --git a/manifests/outputs/plugins/shell/success.yaml b/manifests/outputs/plugins/shell/success.yaml index 3a8825817..0c53a27aa 100644 --- a/manifests/outputs/plugins/shell/success.yaml +++ b/manifests/outputs/plugins/shell/success.yaml @@ -8,8 +8,6 @@ initialize: method: Shell global-config: command: python3 /usr/local/bin/sampler - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -19,21 +17,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:50:37.625Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -61,7 +59,7 @@ tree: pipeline: - shell inputs: - - timestamp: '2023-11-02T10:35:31.820Z' + - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 cpu/energy: 0.002 memory/energy: 0.000005 diff --git a/manifests/outputs/plugins/subtract/success.yaml b/manifests/outputs/plugins/subtract/success.yaml index 5d028f63f..496db3630 100644 --- a/manifests/outputs/plugins/subtract/success.yaml +++ b/manifests/outputs/plugins/subtract/success.yaml @@ -11,8 +11,6 @@ initialize: - cpu/energy - network/energy output-parameter: energy/diff - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml index ce59a1f4e..c31c5d65f 100644 --- a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml +++ b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml @@ -2,8 +2,6 @@ name: sum description: failure with `inputs[0]` misses one of `global-config.input-parameters` tags: null initialize: - outputs: - - yaml plugins: sum: method: Sum diff --git a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml index 548a8b14e..624bf3fdf 100644 --- a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml +++ b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml @@ -2,8 +2,6 @@ name: sum description: missing `output-parameter` in global-config tags: null initialize: - outputs: - - yaml plugins: sum: method: Sum @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:54:23.422Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/sum/success.yaml b/manifests/outputs/plugins/sum/success.yaml index 1d9b47a3f..77b0a3f2d 100644 --- a/manifests/outputs/plugins/sum/success.yaml +++ b/manifests/outputs/plugins/sum/success.yaml @@ -11,8 +11,6 @@ initialize: - cpu/energy - network/energy output-parameter: energy - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T20:53:35.496Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml index e0957366a..d4e15593e 100644 --- a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml +++ b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml @@ -4,15 +4,13 @@ description: >- `global-config.end-time` tags: null initialize: - outputs: - - yaml plugins: time-sync: method: TimeSync path: builtin global-config: - start-time: '2023-12-12T00:01:00.000Z' - end-time: '2023-12-12T00:00:00.000Z' + start-time: "2023-12-12T00:01:00.000Z" + end-time: "2023-12-12T00:00:00.000Z" interval: 5 allow-padding: true execution: @@ -25,21 +23,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:13:59.114Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -60,7 +58,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: 'InputValidationError: `start-time` should be lower than `end-time`' + error: "InputValidationError: `start-time` should be lower than `end-time`" tree: children: child: @@ -68,15 +66,15 @@ tree: - time-sync config: null inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml index 79f3bb69e..5c1f00881 100644 --- a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml +++ b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml @@ -2,8 +2,6 @@ name: time-sync description: missing global config tags: null initialize: - outputs: - - yaml plugins: time-sync: method: TimeSync @@ -19,21 +17,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:13:12.360Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -64,15 +62,15 @@ tree: - time-sync config: null inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 3 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/success.yaml b/manifests/outputs/plugins/time-sync/success.yaml index 1f0a7f07e..17e1a71d1 100644 --- a/manifests/outputs/plugins/time-sync/success.yaml +++ b/manifests/outputs/plugins/time-sync/success.yaml @@ -7,12 +7,10 @@ initialize: path: builtin method: TimeSync global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - outputs: - - yaml execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -22,21 +20,21 @@ execution: environment: if-version: 0.4.0 os: macOS - os-version: '13.2' + os-version: "13.2" node-version: 18.14.2 date-time: 2024-07-02T21:12:32.629Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -65,55 +63,55 @@ tree: - time-sync config: null inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 energy-cpu: 0.001 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 5 energy-cpu: 0.0018000000000000004 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 energy-cpu: 0.0007714285714285716 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 energy-cpu: 0.0004952380952380952 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 energy-cpu: 0.0001666666666666667 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 energy-cpu: 0.0001666666666666667 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 energy-cpu: 0.0001666666666666667 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 energy-cpu: 0.0001666666666666667 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 energy-cpu: 0.0001666666666666667 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 energy-cpu: 0.0001 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 energy-cpu: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 energy-cpu: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 energy-cpu: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 energy-cpu: 0 From b9687f469ccdcb08e0c9a9affadb47b14a343830 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:46:00 +0400 Subject: [PATCH 291/863] docs(src): update documentations about `outputs` --- README.md | 8 - Refactor-migration-guide.md | 266 +++++++++++------------ src/builtins/README.md | 37 +--- src/builtins/coefficient/README.md | 8 +- src/builtins/csv-lookup/README.md | 30 ++- src/builtins/divide/README.md | 7 +- src/builtins/exponent/README.md | 5 +- src/builtins/interpolation/README.md | 6 +- src/builtins/mock-observations/README.md | 2 - src/builtins/multiply/README.md | 4 +- src/builtins/regex/README.md | 2 - src/builtins/sci-embodied/README.md | 4 - src/builtins/sci/README.md | 9 +- src/builtins/shell/README.md | 5 - src/builtins/subtract/README.md | 3 - src/builtins/sum/README.md | 5 +- 16 files changed, 156 insertions(+), 245 deletions(-) diff --git a/README.md b/README.md index 029a97c06..fba9fd18d 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,6 @@ Note that above command will print your outputs to the console. If you do not wa if-run -m -o ``` -Note that you also have to add configuration to your manifest to enable this, as follows: - -```yaml -initialize: - output: - - yaml -``` - The `if-run` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). Use the `debug` command if you want to diagnose and fix errors in your plugin: diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index d315d5c41..893fae424 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -9,42 +9,28 @@ If you are a IF user or developer, there are some changes you must be aware of r There have been some name changes to the CLI, specifically: - `impact-engine` --> `ie` - The command line tool has been renamed from `impact-engine` to simply `ie`. This means that to invoke the Impact Framework on the command line you simply use + The command line tool has been renamed from `impact-engine` to simply `ie`. This means that to invoke the Impact Framework on the command line you simply use - ``` - if-run ... - ``` -- `impl` --> `manifest` - We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to pass a manifest file to IF, you use the `--manifest` command, as follows: + ``` + if-run ... + ``` - ```sh - if-run --manifest - ``` +- `impl` --> `manifest` + We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to pass a manifest file to IF, you use the `--manifest` command, as follows: + ```sh + if-run --manifest + ``` - `ompl` --> `output` - - We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to define a savepath for your output file, you use the `--output` command, as follows: - ```sh - if-run --manifest --output - ``` + We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to define a savepath for your output file, you use the `--output` command, as follows: -## Outputs + ```sh + if-run --manifest --output + ``` -We currently default to exporting output data to the console only. If you want to export to a file, you have to add a small piece of config inside your manifest, as follows: - -```yaml -initalize: - plugins: ... - outputs: ['yaml'] -``` - -You then provide your savepatrh (without file extension) to the `--output` command on the CLI. - -The available options are currently `csv`, `yaml` or `log`. - -### Summary of how to run the refactored IF +### Summary of how to run the refactored IF As before, you can install IF from our npm package using @@ -64,7 +50,6 @@ This will dump the output to the console. If you want to save the output to a ya if-run --manifest --output ``` - If you want to clone the source code and install and run a local copy of IF, you can do so using: ```sh @@ -79,135 +64,133 @@ Then run IF using the following command: npm run if -- --manifest ``` - ## Manifest files There have also been some changes to the structure of manifest files. Some of these are simple renaming changes, others are more functional. - **Rename `graph` -> `tree`** - The `graph` section of the manifest file is now renamed to `tree`. This is just to help us stay consistent in our metaphors and provide a more familiar naming convention for the data beneath. + The `graph` section of the manifest file is now renamed to `tree`. This is just to help us stay consistent in our metaphors and provide a more familiar naming convention for the data beneath. - **Use plugin name as key in `Initialize` block** - In the previous version of IF, the plugins were organized into an array each having a `name` key, with the plugin name as the value. In the refactored IF, we use the name as the key identifying the plugin. For example, this is the OLD way: - - ```yaml - initialize: - plugins: - - name: ccf - model: CloudCarbonFootprint - path: if-plugins - ``` - - This is the new way: - - ```yaml - initialize: - plugins: - "sci-e": - path: "@grnsft/if-plugins" - method: SciE - ``` + In the previous version of IF, the plugins were organized into an array each having a `name` key, with the plugin name as the value. In the refactored IF, we use the name as the key identifying the plugin. For example, this is the OLD way: + + ```yaml + initialize: + plugins: + - name: ccf + model: CloudCarbonFootprint + path: if-plugins + ``` + + This is the new way: + + ```yaml + initialize: + plugins: + 'sci-e': + path: '@grnsft/if-plugins' + method: SciE + ``` - **Rename `model` to `method` in `Initialize` block** - Each plugin in the initialize block - - Each plugin in the `Initialize` block has a field where the name of the exported function representing that plugin is defined. Previously, these were class names and they were defined using the `model` key. Now, they are functions, and they are defined using the `method` key. We use `method` instead of `function` because `function` is a reserved keyword in Typescript. - - For example: - - ```yaml - "sci-embodied": - path: "builtin" - method: SciEmbodied - ``` + Each plugin in the initialize block + + Each plugin in the `Initialize` block has a field where the name of the exported function representing that plugin is defined. Previously, these were class names and they were defined using the `model` key. Now, they are functions, and they are defined using the `method` key. We use `method` instead of `function` because `function` is a reserved keyword in Typescript. + + For example: + + ```yaml + 'sci-embodied': + path: 'builtin' + method: SciEmbodied + ``` - **Global config** - We have introduced the concept of global config to the plugins. This is truly global configuration data that should be kept constant regardless of where the plugin is invoked across the manifest file. - - A good example is the `interpolation` method to use in the Teads curve plugin - this is not expected to vary from component to component and can therefore be defined in global config. The plugin code itself must expect the global config. Then, the config can be passed in the `Initialize` block, for example: - - ```yaml - initialize: - plugins: - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true - ``` + We have introduced the concept of global config to the plugins. This is truly global configuration data that should be kept constant regardless of where the plugin is invoked across the manifest file. -- **Node level config** + A good example is the `interpolation` method to use in the Teads curve plugin - this is not expected to vary from component to component and can therefore be defined in global config. The plugin code itself must expect the global config. Then, the config can be passed in the `Initialize` block, for example: - We have also introduced the concept of node-level config. This is designed for pluin configuration that might vary between components in the tree. For example, for each child in the tree you might wish to use the `groupby` plugin to group the outputs according to a different set of keys. - - ```yaml - tree: - children: - child-1: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - config: - group-by: - group: - - region - - cloud/instance-type - ``` + ```yaml + initialize: + plugins: + 'time-sync': + method: TimeSync + path: 'builtin' + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + ``` -- **Defaults** +- **Node level config** - We have also introduced the concept of `defaults`. This is a section in each component's definition that can be used to provide fallbacks for missing input data. For example, perhaps you have a value arriving from an external API that should be present in every observation in your inputs array, but for soem reason the API fails to deliver a value for some timestamps. In this case, IF would fallback to the value provided for that metric in the `defaults` section of the manifest for that component. - - You can also use `defaults` as a quick way to add values to everyobservation in your input array if those values are expected to be constant over time (e.g. some of the lifespan values for embodied carbon calculations could be appropriate to include in defaults). This saves you from having to enter the value in every observation in the input array, instead IF can automatically grab it from `defaults` for every timestamp. - - ```yaml - tree: - children: - child-1: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - ``` + We have also introduced the concept of node-level config. This is designed for pluin configuration that might vary between components in the tree. For example, for each child in the tree you might wish to use the `groupby` plugin to group the outputs according to a different set of keys. + + ```yaml + tree: + children: + child-1: + pipeline: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync + - sci + config: + group-by: + group: + - region + - cloud/instance-type + ``` +- **Defaults** + We have also introduced the concept of `defaults`. This is a section in each component's definition that can be used to provide fallbacks for missing input data. For example, perhaps you have a value arriving from an external API that should be present in every observation in your inputs array, but for soem reason the API fails to deliver a value for some timestamps. In this case, IF would fallback to the value provided for that metric in the `defaults` section of the manifest for that component. + + You can also use `defaults` as a quick way to add values to everyobservation in your input array if those values are expected to be constant over time (e.g. some of the lifespan values for embodied carbon calculations could be appropriate to include in defaults). This saves you from having to enter the value in every observation in the input array, instead IF can automatically grab it from `defaults` for every timestamp. + + ```yaml + tree: + children: + child-1: + pipeline: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.120 # gCO2eq + time-reserved: 3600 # 1hr in seconds + device/expected-lifespan: 94608000 # 3 years in seconds + resources-reserved: 1 + resources-total: 8 + ``` ## New IF features ### Time-sync -Technically time-sync is not a new feature as it was present in IF before the refactor, but there are some tweaks to how the plugin is configured that are worth explaining here. Time sync snaps all input arrays across an entire graph to a common time grid. + +Technically time-sync is not a new feature as it was present in IF before the refactor, but there are some tweaks to how the plugin is configured that are worth explaining here. Time sync snaps all input arrays across an entire graph to a common time grid. This means you have to define a global start time, end time and interval to use everywhere. There is also a boolean to toggle whether you should allow the time sync model to pad the start and end of your time series with zeroes. You should default to `true` unless you have a specific reason not to. In the refactored IF we expect this information to be provided in global config, as follows: ```yaml initialize: - plugins: - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true + plugins: + 'time-sync': + method: TimeSync + path: 'builtin' + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true ``` ### Aggregate @@ -216,7 +199,7 @@ The aggregate plugin aggregates data in two ways: first it condenses individual This is a builtin feature of IF, meaning it does not have to be initialized as a plugin. Instead, you just have to include a short config block in the top of the manifest file. There are two pieces of information required: -- `metrics`: which metrics do you want to aggregate? Every metric you provide here must exist in the output array. +- `metrics`: which metrics do you want to aggregate? Every metric you provide here must exist in the output array. - `type`: the options are `horizontal`, `vertical` or both. Horizontal aggregation is the type that condenses each time series into a single summary value. Vertical aggregation is aggregated across components. @@ -229,10 +212,9 @@ aggregation: type: 'both' ``` - ### Groupby -Groupby allows you to regroup your outputs according to keys you define. For example, maybe you want to group your outputs by region (show me all the outputs for applications run in `uk-south` etc). Groupby *is* a plugin that needs to be initialized in the manifest. +Groupby allows you to regroup your outputs according to keys you define. For example, maybe you want to group your outputs by region (show me all the outputs for applications run in `uk-south` etc). Groupby _is_ a plugin that needs to be initialized in the manifest. You can initialize the plugin as follows: @@ -266,11 +248,10 @@ tree: ### Exhaust -We have introduced `exhaust` as an IF feature. This is a wrapper around export plugins and it allows community contributors to create plugins for exporting to different formats. +We have introduced `exhaust` as an IF feature. This is a wrapper around export plugins and it allows community contributors to create plugins for exporting to different formats. Details tbc... - ## Plugins The plugins themselves require some changes to keep them compatible with the refactored IF. @@ -295,18 +276,17 @@ The plugin still requires an execute function. This is where you implement the p Here's a minimal example for a plugin that sums some inputs defined in global config - see inline comments for some important notes: ```ts - // Here's the function definition - notice that global config is passed in here! export const Sum = (globalConfig: SumConfig): PluginInterface => { const inputParameters = globalConfig['input-parameters'] || []; const outputParameter = globalConfig['output-parameter']; - - // we also return metadata now too - you can add more or just use this default + + // we also return metadata now too - you can add more or just use this default const metadata = { kind: 'execute', }; - - /** + + /** * Calculate the sum of the input metrics for each timestamp. */ const execute = async (inputs: PluginParams[]): Promise => { @@ -332,7 +312,7 @@ export const Sum = (globalConfig: SumConfig): PluginInterface => { ); }; - // return the metadata and the execute function + // return the metadata and the execute function return { metadata, execute, diff --git a/src/builtins/README.md b/src/builtins/README.md index c37e143a1..df743e93c 100644 --- a/src/builtins/README.md +++ b/src/builtins/README.md @@ -31,9 +31,6 @@ The following should be defined in the plugin initialization: - `inputs`: time-synchronized version of the tree - - - #### Overview A manifest file for a tree might contain many nodes each representing some different part of an application's stack or even different applications running on different machines. It is therefore common to have time series data in each component that is not directly comparable to other components either because the temporal resolution of the data is different, they cover different periods, or there are gaps in some records (e.g. some apps might burst but then go dormant, while others run continuously). This makes post-hoc visualization, analysis and aggregation of data from groups of nodes difficult to achieve. To address this, we created a time synchronization plugin that takes in non-uniform times series and snaps them all to a regular timeline with uniform start time, end time and temporal resolution. @@ -170,7 +167,6 @@ Note that when `error-on-padding` is `true` no padding is performed and the plug Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `intervalk` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `params.ts`. The returned array is the final, synchronized time series at the desired temporal resolution. - #### Assumptions and limitations To do time synchronization, we assume: @@ -178,10 +174,8 @@ To do time synchronization, we assume: - There is no environmental impact for an application when there is no data available. - Evenly distributing the total for a `duration` across higher resolution `observations` is appropriate, as opposed to having some non-uniform distribution. - ### Typescript implementation - To run the plugin, you must first create an instance of `TimeSync`. Then, you can call `execute()`. @@ -216,7 +210,7 @@ const results = timeSync.execute([ IF users will typically call the plugin as part of a pipeline defined in an `manifest` file. In this case, instantiating and configuring the plugin is handled by -`ie` and does not have to be done explicitly by the user. +`if-run` and does not have to be done explicitly by the user. The following is an example `manifest` that calls `time-sync`: ```yaml @@ -281,23 +275,10 @@ tree: requests: 380 ``` - -## CSV Exporter +## CSV Exporter IF supports exporting data to CSV files. This provides users with a data format that enables visualization and data analysis using standard data analysis tools. -### Manifest config - -To export your data to a CSV file, you have to provide a small piece of config data to your manifest file: - -```yaml -initialize: - outputs: - - csv -``` - -You can also add `- yaml` if you want to export to both `yaml` and `csv` simultaneously. - ### CLI command Then, you must select the metric you want to export to CSV. The name of that metric must be added to the savepath provided to the `--output` command in the CLI, after a hashtag. @@ -319,10 +300,9 @@ This will save a CSV file called `example.csv`. The contents will look similar t | tree.children.france.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | | tree.children.france.children.server-2.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | - ### Comparing CSV to Yaml -The CSV above is generated from the following yaml. The `carbon` metric is extracted and added to the CSV. Otherwise, the CSV is an exact representation of the following yaml tree. You can see that the CSV representation is *much* easier to understand than the full yaml tree: +The CSV above is generated from the following yaml. The `carbon` metric is extracted and added to the CSV. Otherwise, the CSV is an exact representation of the following yaml tree. You can see that the CSV representation is _much_ easier to understand than the full yaml tree: ```yaml tree: @@ -653,21 +633,19 @@ tree: ### CSV and aggregation -The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the *rows* of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the *columns* in the CSV representation (this is not *exactly* accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). - +The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the _rows_ of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the _columns_ in the CSV representation (this is not _exactly_ accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). ## Groupby Groupby is an IF plugin that reorganizes a tree according to keys provided by the user. This allows users to regroup their observations according to various properties of their application. For example, the following manifest file contains a flat array of observations. This is how you might expect data to arrive from an importer plugin, maybe one that hits a metrics API for a cloud service. - ```yaml name: if-demo description: demo pipeline graph: children: my-app: - pipeline: + pipeline: - group-by - teads-curve config: @@ -691,7 +669,7 @@ graph: cloud/region: uk-west cpu-util: 12 - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp - duration: 300 + duration: 300 instance-type: B1 cloud/region: uk-west cpu-util: 11 @@ -701,7 +679,7 @@ graph: cloud/region: uk-west cpu-util: 67 - timestamp: 2023-07-06T10:00 - duration: 300 + duration: 300 instance-type: B1 cloud/region: uk-west cpu-util: 1 @@ -775,7 +753,6 @@ group-by: You then have to provide config defining which keys to group by in each component. This is done at the component level (i.e. not global config). For example: - ```yaml tree: children: diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index 4579cd5b8..fb42e32a1 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -53,15 +53,13 @@ const result = coeff.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 `coefficient`: +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 `coefficient`: ```yaml name: coefficient-demo description: tags: initialize: - outputs: - - yaml plugins: coefficient: method: Coefficient @@ -86,12 +84,11 @@ tree: You can run this example by saving it as `./examples/manifests/coefficient.yml` and executing the following command from the project root: ```sh -if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml +if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient ``` The results will be saved to a new `yaml` file in `./examples/outputs` - ## Errors `Coefficient` exposes one of the IF error classes. @@ -101,6 +98,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs` You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: + - `input-parameter`: this must be a string - `coefficient`: this must be a number - `output-parameter`: this must be a string diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index 3663f4123..61af5b292 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -13,19 +13,17 @@ For example, for the following CSV: | 2022 | Google Cloud | asia-east2 | Hong Kong | HK | HK | Hong Kong | 22.3,114.2 | 0.28 | | | 0 | 453 | | | | 360 | | 2022 | Google Cloud | asia-northeast1 | Tokyo | JP-TK | JP-TK | Tokyo | 35.6897,139.692 | 0.28 | | | 0 | 463 | | | | 463 | - You could select all the data for the cloud provider `Google Cloud` in the region `asia-east2` using the following configuration: ```yaml filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" -output: "*" + cloud-provider: 'cloud/provider' + cloud-region: 'cloud/region' +output: '*' ``` -Notice that the query parameters are key/value pairs where the key is the column name in the target CSV and the value is a **reference to a value** in your `input` data (*not* an actual value - a reference). This is to enable you to chain CSV lookups together based on information from other plugins in your pipeline. - +Notice that the query parameters are key/value pairs where the key is the column name in the target CSV and the value is a **reference to a value** in your `input` data (_not_ an actual value - a reference). This is to enable you to chain CSV lookups together based on information from other plugins in your pipeline. ## Parameters @@ -33,23 +31,23 @@ Notice that the query parameters are key/value pairs where the key is the column - `filepath` - path to a csv file, either on the local filesystem or on the internet - `query` - an array of key/value pairs where the key is a column name in the target csv and the value is a parameter from inputs -- `output` - the columns to grab data from and add to output data - should support wildcard or multiple values. +- `output` - the columns to grab data from and add to output data - should support wildcard or multiple values. -The plugin also supports data renaming. This means you can grab data from a named column but push it into your manifest file data under another name, for example, maybe we want to grab data from the `processor-name` column int he target csv and add it to the manifest file data as `processor-id` because this is the name expected by some other plugin in your piepline. You can do this by passing comma separated values in arrays. +The plugin also supports data renaming. This means you can grab data from a named column but push it into your manifest file data under another name, for example, maybe we want to grab data from the `processor-name` column int he target csv and add it to the manifest file data as `processor-id` because this is the name expected by some other plugin in your piepline. You can do this by passing comma separated values in arrays. ```yaml -output: - ["processor-name": "processor-id"] +output: ['processor-name': 'processor-id'] ``` You can nest arrays to do this renaming for multiple columns. ```yaml output: - [["processor-name", "processor-model-id"],["tdp","thermal-design-power"]] + [['processor-name', 'processor-model-id'], ['tdp', 'thermal-design-power']] ``` All the following values are valid for the `output` field: + - `"*"` - `"tdp"` - `["processor-name", "processor-model-id"]` @@ -108,8 +106,6 @@ name: csv-lookup-demo description: tags: initialize: - outputs: - - yaml plugins: cloud-metadata: method: CSVLookup @@ -117,9 +113,9 @@ initialize: global-config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" - output: "*" + cloud-provider: 'cloud/provider' + cloud-region: 'cloud/region' + output: '*' tree: children: child: @@ -141,7 +137,6 @@ if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/cs The results will be saved to a new `yaml` file in `manifests/outputs`. - ## Errors Coefficient exposes six of the IF error classes. @@ -171,6 +166,7 @@ This error arises due to problems parsing CSV data into IF. This can occur when You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: + - `filepath`: This must be a path to a csv file - `query`: this must be an array of key-value pairs where the key is a string containing a column name an the value is a string containing the name of a value in `inputs` - `output`: this must be a string containing a name or a wildcard character (`"*"`) diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index 9a4d04f36..99f8a23ee 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -24,7 +24,7 @@ You provide the names of the values you want to divide, and a name to use to add The plugin throws an exception if the division result is not a number. ->Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. +> Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. ## Calculation @@ -62,8 +62,6 @@ name: divide-demo description: tags: initialize: - outputs: - - yaml plugins: divide: method: Divide @@ -103,6 +101,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: + - `numerator`: a string containing the name of the input parameter whose value should be divided by `denominator` - `denominator`: a number to use as the denominator - ``output`: a string containing the name to assign the result of the division @@ -113,9 +112,9 @@ You can fix this error by checking you are providing valid values for each param This error arises when a necessary piece of input data is missing from the `inputs` array. Every element in the ``inputs` array must contain: + - `timestamp` - `duration` - whatever value you passed to `numerator` - For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index 91d938cef..fa36319b8 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -63,8 +63,6 @@ name: exponent demo description: tags: initialize: - outputs: - - yaml plugins: exponent: method: Exponent @@ -91,7 +89,7 @@ You can run this example by saving it as `manifests/examples/test/exponent.yml` ```sh npm i -g @grnsft/if -if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml +if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent ``` The results will be saved to a new `yaml` file in `manifests/outputs`. @@ -109,7 +107,6 @@ Every element in the `inputs` array must contain: - `duration` - whatever value you passed to `input-parameter` - ### `InputValidationError` This error arises when an invalid value is passed to `Exponent`. 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. diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md index 498c26c6e..74c8498a3 100644 --- a/src/builtins/interpolation/README.md +++ b/src/builtins/interpolation/README.md @@ -102,8 +102,6 @@ name: interpolation-demo description: simple demo of interpolation plugin tags: initialize: - outputs: - - yaml plugins: interpolation: method: Interpolation @@ -132,8 +130,6 @@ name: interpolation-demo description: simple demo of interpolation plugin tags: initialize: - outputs: - - yaml plugins: interpolation: method: Interpolation @@ -178,6 +174,7 @@ if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/ou You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: + - `method`: a string containing either `linear`, `spline` or `polynomial` - `x`: an array of numbers - `y`: an array of numbers @@ -189,6 +186,7 @@ You can fix this error by checking you are providing valid values for each param ### Validation errors There are also several validation errors that can arise, including: + - if the lengths of `x` and `y` are not equal - if `x` or `y` are empty - if the requested point to interpolate at is outside the range of `x` diff --git a/src/builtins/mock-observations/README.md b/src/builtins/mock-observations/README.md index 1af4cd6d6..0da9211da 100644 --- a/src/builtins/mock-observations/README.md +++ b/src/builtins/mock-observations/README.md @@ -54,8 +54,6 @@ name: mock-observation-demo description: example invoking mock-observation plugin tags: initialize: - outputs: - - yaml plugins: mock-observations: kind: plugin diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index 7e9c2dfbd..0ce42c7c0 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -61,8 +61,6 @@ name: multiply-demo description: tags: initialize: - outputs: - - yaml plugins: multiply: method: Multiply @@ -93,7 +91,6 @@ if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/out The results will be saved to a new `yaml` file in `./examples/outputs` - ## Errors `Multiply` uses one of the IF error classes. @@ -102,6 +99,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs` This error arises when a necessary piece of input data is missing from the `inputs` array. Every element in the `inputs` array must contain: + - `timestamp` - `duration` - whatever values you passed to `input-parameters` diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index a0fa5d624..f031f13b1 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -56,8 +56,6 @@ name: regex-demo description: tags: initialize: - outputs: - - yaml plugins: regex: method: Regex diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md index 97b6ce4af..b4d71304b 100644 --- a/src/builtins/sci-embodied/README.md +++ b/src/builtins/sci-embodied/README.md @@ -79,8 +79,6 @@ name: sci-embodied description: simple demo invoking sci-embodied tags: initialize: - outputs: - - yaml plugins: sci-embodied: method: SciEmbodied @@ -109,7 +107,6 @@ if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/ The results will be saved to a new `yaml` file in `./examples/outputs`. - ## Errors `SciEmbodied` uses one of IF's error classes @@ -120,5 +117,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 diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 592bd1ed0..d975e42f3 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -8,10 +8,8 @@ - `functional-unit`: the name of the functional unit in which to express the carbon impact (required) - ### Inputs - - `carbon`: total carbon in gCO2eq (required) - `functional-unit`: whatever `functional-unit` you define in global config also has to be present in each input, for example if you provide `functional-unit: requests` in global config, `requests` must be present in your input data. @@ -19,7 +17,7 @@ - `sci`: carbon expressed in terms of the given functional unit ->Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. +> Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. ## Calculation @@ -29,7 +27,6 @@ SCI is calculated as: sci = carbon / functional unit ``` - ## IF Implementation To run the plugin, you must first create an instance of `Sci`. Then, you can call `execute()` to return `sci`. @@ -60,8 +57,6 @@ name: sci-demo description: example invoking sci plugin tags: initialize: - outputs: - - yaml plugins: sci: method: Sci @@ -99,12 +94,12 @@ The results will be saved to a new `yaml` file. This error arises when a necessary piece of input data is missing from the `inputs` array. Every element in the `inputs` array must contain: + - `timestamp` - `duration` - `carbon`: a numeric value named `carbon` must exist in the inputs array - whatever value you passed to `functional-unit` - ### Validation errors There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md index bacba1255..962fb46d4 100644 --- a/src/builtins/shell/README.md +++ b/src/builtins/shell/README.md @@ -66,8 +66,6 @@ name: shell-demo description: tags: initialize: - outputs: - - yaml plugins: sampler: method: Shell @@ -94,8 +92,6 @@ name: shell-demo description: tags: initialize: - outputs: - - yaml plugins: sampler: method: Shell @@ -129,7 +125,6 @@ if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.y The results will be saved to a new `yaml` file. - ## Errors `Shell` uses one of the error classes provided by IF diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md index 8ff9a922f..726f982b2 100644 --- a/src/builtins/subtract/README.md +++ b/src/builtins/subtract/README.md @@ -61,8 +61,6 @@ name: subtract demo description: tags: initialize: - outputs: - - yaml plugins: subtract: method: Subtract @@ -93,7 +91,6 @@ if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/sub The results will be saved to a new `yaml` file in `manifests/outputs`. - ## Errors `Subtract` uses one of IF's error classes: diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md index ea0f0113d..997a6e1cf 100644 --- a/src/builtins/sum/README.md +++ b/src/builtins/sum/README.md @@ -59,8 +59,6 @@ name: sum demo description: tags: initialize: - outputs: - - yaml plugins: sum: method: Sum @@ -90,7 +88,6 @@ if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.y The results will be saved to a new `yaml` file in `./examples/outputs`. - ## Errors `Sum` exposes two of the IF error classes. @@ -100,6 +97,7 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: + - `input-parameters`: this must be an array of strings, each being the name of a value in the `inputs` array - `output-parameter`: this must be a string @@ -114,5 +112,4 @@ Every element in the ``inputs` array must contain: - `duration` - whatever values you passed to `input-parameters` - For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors). From bc9711add27d4117a0cbb09adcde4a9fd505ffb7 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:47:37 +0400 Subject: [PATCH 292/863] docs(src): change `ie` to `if-run` --- Refactor-migration-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 893fae424..0e662110a 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -8,8 +8,8 @@ If you are a IF user or developer, there are some changes you must be aware of r There have been some name changes to the CLI, specifically: -- `impact-engine` --> `ie` - The command line tool has been renamed from `impact-engine` to simply `ie`. This means that to invoke the Impact Framework on the command line you simply use +- `impact-engine` --> `if-run` + The command line tool has been renamed from `impact-engine` to simply `if-run`. This means that to invoke the Impact Framework on the command line you simply use ``` if-run ... @@ -61,7 +61,7 @@ npm i Then run IF using the following command: ```sh -npm run if -- --manifest +npm run if-run -- --manifest ``` ## Manifest files From 07258b225bab1fe5ff320e6daca235fcb6c07384 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:51:59 +0400 Subject: [PATCH 293/863] fix(config): remove outputs from if-env template manifest --- src/config/env-template.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/config/env-template.yml b/src/config/env-template.yml index f5fd65a6a..ba64c88dc 100644 --- a/src/config/env-template.yml +++ b/src/config/env-template.yml @@ -2,8 +2,6 @@ name: template manifest # rename me! description: auto-generated template # update description! tags: # add any tags that will help you to track your manifests initialize: - outputs: - - yaml # you can add - csv to export to csv plugins: # add more plugins for your use-case memory-energy-from-memory-util: # you can name this any way you like! method: Coefficient # the name of the function exported from the plugin From c9bb4ba4db774dff5bd5c94e89b799133b5fd677 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:56:09 +0400 Subject: [PATCH 294/863] fix(src): remove export-csv and export-scv-raw file and related tests/mocks files --- .../{export-csv.ts => export-yaml.ts} | 2 - .../unit/builtins/export-csv-raw.test.ts | 77 ------ .../unit/builtins/export-csv.test.ts | 236 ------------------ src/builtins/export-csv-raw.ts | 156 ------------ src/builtins/export-csv.ts | 117 --------- 5 files changed, 588 deletions(-) rename src/__mocks__/builtins/{export-csv.ts => export-yaml.ts} (99%) delete mode 100644 src/__tests__/unit/builtins/export-csv-raw.test.ts delete mode 100644 src/__tests__/unit/builtins/export-csv.test.ts delete mode 100644 src/builtins/export-csv-raw.ts delete mode 100644 src/builtins/export-csv.ts diff --git a/src/__mocks__/builtins/export-csv.ts b/src/__mocks__/builtins/export-yaml.ts similarity index 99% rename from src/__mocks__/builtins/export-csv.ts rename to src/__mocks__/builtins/export-yaml.ts index 1f0e00e73..cb623f04e 100644 --- a/src/__mocks__/builtins/export-csv.ts +++ b/src/__mocks__/builtins/export-yaml.ts @@ -164,5 +164,3 @@ export const aggregation = { metrics: ['carbon'], type: 'both', }; - -export const outputs = ['csv']; diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts deleted file mode 100644 index e97242a4d..000000000 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as fs from 'fs/promises'; - -import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; - -import {STRINGS} from '../../../config'; - -import {tree, context, outputs} from '../../../__mocks__/builtins/export-csv'; - -const {ExhaustOutputArgError} = ERRORS; -const {WRITE_CSV_ERROR, OUTPUT_REQUIRED} = STRINGS; - -jest.mock('fs/promises', () => ({ - __esModule: true, - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('builtins/export-csv-raw: ', () => { - describe('ExportCSVRaw: ', () => { - const exportCSVRaw = ExportCSVRaw(); - - beforeEach(() => { - jest.resetAllMocks(); - }); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(exportCSVRaw).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output#carbon'; - const content = - "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,8000.000004051243,"; - - await exportCSVRaw.execute(tree, context, outputPath); - - expect(fs.writeFile).toHaveBeenCalledWith(`${outputPath}.csv`, content); - }); - - it('throws an error when the CSV file could not be created.', async () => { - const outputPath = 'output#carbon'; - const expectedMessage = 'Could not write CSV file.'; - - expect.assertions(1); - - jest.spyOn(fs, 'writeFile').mockRejectedValue(expectedMessage); - - await expect( - exportCSVRaw.execute(tree, context, outputPath) - ).rejects.toThrow( - new ExhaustOutputArgError( - WRITE_CSV_ERROR(outputPath, expectedMessage) - ) - ); - }); - - it('throws an error when output path is empty.', async () => { - const outputPath = ''; - - context.initialize = Object.assign({}, context.initialize, outputs); - - expect.assertions(2); - try { - await exportCSVRaw.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts deleted file mode 100644 index 78feaf534..000000000 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ /dev/null @@ -1,236 +0,0 @@ -import * as fs from 'fs/promises'; - -import {stringify} from 'csv-stringify/sync'; -import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {ExportCSV} from '../../../builtins/export-csv'; - -import {STRINGS} from '../../../config'; - -import { - tree, - context, - outputs, - aggregated, - aggregation, -} from '../../../__mocks__/builtins/export-csv'; - -const {ExhaustOutputArgError} = ERRORS; -const {OUTPUT_REQUIRED, CSV_EXPORT} = STRINGS; - -jest.mock('fs/promises', () => ({ - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('builtins/export-csv: ', () => { - describe('ExportCSV: ', () => { - const exportCSV = ExportCSV(); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(exportCSV).toMatchObject({metadata: {kind: 'exhaust'}}); - expect(exportCSV).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - const reformedContext = Object.assign({}, context, {outputs}); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, reformedContext, outputPath); - - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when the `outputs` type is missing.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, context, outputPath); - - expect.assertions(1); - - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when `aggregation` persists.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, reformedContext, outputPath); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when `aggregation` is missing.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedContext = Object.assign({}, context, {outputs}); - - await exportCSV.execute(tree, reformedContext, outputPath); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('throws an error when output path is empty.', async () => { - const outputPath = ''; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); - } - }); - - it('throws an error when output path does not contains `#`.', async () => { - const outputPath = 'output.csv'; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); - } - }); - - it('throws an error when output path does not contains a criteria.', async () => { - const outputPath = 'output.csv#'; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); - } - }); - }); - }); -}); diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts deleted file mode 100644 index 7afc21cb2..000000000 --- a/src/builtins/export-csv-raw.ts +++ /dev/null @@ -1,156 +0,0 @@ -import * as fs from 'fs/promises'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {STRINGS} from '../config'; - -import {Context} from '../types/manifest'; - -const {ExhaustOutputArgError, WriteFileError} = ERRORS; -const {OUTPUT_REQUIRED, WRITE_CSV_ERROR, EXPORTING_RAW_CSV_FILE} = STRINGS; - -export const ExportCSVRaw = () => { - /** - * handle a tree leaf, where there are no child nodes, by adding it as key->value pair to the flat map - * and capturing key as a header - */ - const handleLeafValue = ( - value: any, - fullPath: string, - key: any, - flatMap: {[key: string]: any}, - headers: Set - ) => { - if (fullPath.includes('outputs')) { - headers.add(key); - flatMap[fullPath] = value; - } - }; - - /** - * handle a tree node, recursively traverse the children and append their results to the flat map and captured headers - */ - const handleNodeValue = ( - value: any, - fullPath: string, - flatMap: Record, - headers: Set - ) => { - const [subFlatMap, subHeaders] = extractFlatMapAndHeaders(value, fullPath); - - if (Object.keys(subFlatMap).length > 0) { - Object.entries(subFlatMap).forEach(([subKey, value]) => { - flatMap[subKey] = value; - }); - - subHeaders.forEach(subHeader => { - headers.add(subHeader); - }); - } - }; - - /** - * Handles a key at the top level of the tree - */ - const handleKey = ( - value: any, - key: any, - prefix: string, - flatMap: Record, - headers: Set - ) => { - const fullPath = prefix ? `${prefix}.${key}` : key; - - if (value !== null && typeof value === 'object') { - return handleNodeValue(value, fullPath, flatMap, headers); - } - - return handleLeafValue(value, fullPath, key, flatMap, headers); - }; - - /** - * Recursively extract a flat map and headers from the hierarcial tree. - */ - const extractFlatMapAndHeaders = ( - tree: any, - prefix = '' - ): [Record, Set] => { - const headers: Set = new Set(); - const flatMap: Record = []; - - for (const key in tree) { - if (key in tree) { - handleKey(tree[key], key, prefix, flatMap, headers); - } - } - - return [flatMap, headers]; - }; - - /** - * extract the id of the key, that is removing the last token (which is the index). - * in this manner, multiple keys that identical besides their index share the same id. - */ - const extractIdHelper = (key: string): string => { - const parts = key.split('.'); - parts.pop(); - - return parts.join('.'); - }; - - /** - * generate a CSV formatted string based on a flat key->value map, headers and ids - */ - const getCsvString = ( - map: {[key: string]: any}, - headers: Set, - ids: Set - ): string => { - const csvRows: string[] = []; - csvRows.push(['id', ...headers].join(',')); - - ids.forEach(id => { - const rowData = [id]; - - headers.forEach(header => { - const value = map[`${id}.${header}`] ?? ''; - rowData.push(value.toString()); - }); - csvRows.push(rowData.join(',')); - }); - - return csvRows.join('\n'); - }; - - /** - * write the given string content to a file at the provided path - */ - const writeOutputFile = async (content: string, outputPath: string) => { - try { - await fs.writeFile(`${outputPath}.csv`, content); - } catch (error) { - throw new WriteFileError(WRITE_CSV_ERROR(outputPath, error)); - } - }; - - /** - * export the provided tree content to a CSV file, represented in a flat structure - */ - const execute = async (tree: any, _context: Context, outputPath: string) => { - if (!outputPath) { - throw new ExhaustOutputArgError(OUTPUT_REQUIRED); - } - - console.debug(EXPORTING_RAW_CSV_FILE(outputPath)); - - const [extractredFlatMap, extractedHeaders] = - extractFlatMapAndHeaders(tree); - const ids = new Set( - Object.keys(extractredFlatMap).map(key => extractIdHelper(key)) - ); - const csvString = getCsvString(extractredFlatMap, extractedHeaders, ids); - - await writeOutputFile(csvString, outputPath); - }; - - return {execute}; -}; diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts deleted file mode 100644 index 53a105733..000000000 --- a/src/builtins/export-csv.ts +++ /dev/null @@ -1,117 +0,0 @@ -import {writeFile} from 'fs/promises'; - -import {stringify} from 'csv-stringify/sync'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {PluginParams} from '@grnsft/if-core/types'; - -import {STRINGS} from '../config'; - -import {Context} from '../types/manifest'; - -const {ExhaustOutputArgError} = ERRORS; -const {CSV_EXPORT, OUTPUT_REQUIRED, EXPORTING_TO_CSV_FILE} = STRINGS; - -/** - * Extension to IF that outputs the tree in a CSV format. - */ -export const ExportCSV = () => { - const parseOutputAndField = (outputPath: string) => { - const validatedPath = validateOutputPath(outputPath); - - const paths = validatedPath.split('#'); - const criteria = paths[paths.length - 1]; - - if (paths.length <= 1 || !criteria) { - throw new ExhaustOutputArgError(CSV_EXPORT); - } - - const output = paths.slice(0, paths.length - 1).join(''); - console.debug(EXPORTING_TO_CSV_FILE(output)); - - return { - output, - criteria, - }; - }; - - /** - * Validates output path. - */ - const validateOutputPath = (outputPath: string) => { - if (!outputPath) { - throw new ExhaustOutputArgError(OUTPUT_REQUIRED); - } - - return outputPath; - }; - - /** - * Grabs output and criteria from cli args, then call tree walker to collect csv data. - */ - const execute = async (tree: any, context: Context, outputPath: string) => { - const columns = ['Path']; - const matrix = [columns]; - const {output, criteria} = parseOutputAndField(outputPath); - const aggregationIsEnabled = !!context.aggregation; - - /** - * Walks through all tree branches and leaves, collecting the data - */ - const treeWalker = (node: any, criteria: string, path = 'tree') => { - /** Hmm aggregated, then checks if it's the first one. If so adds column, pushes the value. */ - if (node.aggregated) { - if (path === 'tree') { - columns.push('Aggregated'); - } - - matrix.push([`${path}.${criteria}`, node.aggregated[criteria]]); - } - - /** So it has outputs, whats then? checks if timestamp is not there, adds one. Then appends values to it. */ - if (node.outputs) { - node.outputs.forEach((output: PluginParams) => { - const {timestamp} = output; - - if (!columns.includes(timestamp)) { - columns.push(output.timestamp); - } - - const lastRow = matrix[matrix.length - 1]; - - if (aggregationIsEnabled) { - lastRow.push(output[criteria]); - } else { - /** Handle without aggregation export strategy. */ - if (matrix.length === 1 || lastRow.length === columns.length) { - matrix.push([`${path}.${criteria}`, output[criteria]]); - } else { - lastRow.push(output[criteria]); - } - } - }); - } - - /** Ohh children? then call every one and execute. */ - if (node.children) { - for (const child in node.children) { - treeWalker( - node.children[child], - criteria, - `${path}.children.${child}` - ); - } - } - }; - - treeWalker(tree, criteria); - - await writeFile(`${output}.csv`, stringify(matrix, {columns})); - }; - - return { - execute, - metadata: { - kind: 'exhaust', - }, - }; -}; From 6604ca166602fb94731818ca844e060d32e53358 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 4 Jul 2024 15:57:58 +0400 Subject: [PATCH 295/863] test(src): update test according to changes --- src/__mocks__/mock-manifest.yaml | 2 - .../unit/builtins/export-log.test.ts | 2 +- .../unit/builtins/export-yaml.test.ts | 4 +- src/__tests__/unit/lib/exhaust.test.ts | 76 +++++-------------- 4 files changed, 24 insertions(+), 60 deletions(-) diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml index 1e38c1b13..64e00e301 100644 --- a/src/__mocks__/mock-manifest.yaml +++ b/src/__mocks__/mock-manifest.yaml @@ -10,8 +10,6 @@ initialize: input-parameter: memory/utilization coefficient: 0.0001 output-parameter: memory/energy - outputs: - - yaml execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/src/__tests__/unit/builtins/export-log.test.ts b/src/__tests__/unit/builtins/export-log.test.ts index f6990ab1e..573df3e75 100644 --- a/src/__tests__/unit/builtins/export-log.test.ts +++ b/src/__tests__/unit/builtins/export-log.test.ts @@ -1,7 +1,7 @@ import * as YAML from 'js-yaml'; import {ExportLog} from '../../../builtins/export-log'; -import {tree, context} from '../../../__mocks__/builtins/export-csv'; +import {tree, context} from '../../../__mocks__/builtins/export-yaml'; describe('builtins/export-log:', () => { describe('ExportLog: ', () => { diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts index fb7954c1e..27e9a5ddc 100644 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ b/src/__tests__/unit/builtins/export-yaml.test.ts @@ -5,7 +5,7 @@ import {saveYamlFileAs} from '../../../util/yaml'; import {STRINGS} from '../../../config'; -import {tree, context} from '../../../__mocks__/builtins/export-csv'; +import {tree, context} from '../../../__mocks__/builtins/export-yaml'; jest.mock('../../../util/yaml', () => ({ saveYamlFileAs: jest.fn(), @@ -32,7 +32,7 @@ describe('builtins/export-yaml: ', () => { expect(saveYamlFileAs).toHaveBeenCalledWith( {...context, tree}, - `${outputPath.split('#')[0]}.yaml` + outputPath.split('#')[0] ); }); diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index 66a797ebb..728c8c625 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -1,15 +1,16 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ jest.mock('fs', () => require('../../../__mocks__/fs')); -import {ERRORS} from '@grnsft/if-core/utils'; - import {exhaust} from '../../../lib/exhaust'; -import {STRINGS} from '../../../config'; - -const {ExhaustOutputArgError, InvalidExhaustPluginError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN, OUTPUT_REQUIRED} = STRINGS; - +jest.mock('../../../builtins/export-yaml', () => ({ + ExportYaml: jest.fn().mockImplementation(() => ({ + // @ts-ignore + execute: (tree, context, outputOptions) => { + expect(outputOptions).toBe('mock-path'); + }, + })), +})); describe('lib/exhaust: ', () => { describe('exhaust(): ', () => { const spy = jest.spyOn(global.console, 'log'); @@ -18,75 +19,40 @@ describe('lib/exhaust: ', () => { spy.mockReset(); }); - it('returns void if no exhaust plugin selected.', async () => { + it('successfully executes provided yaml file.', async () => { const tree = {}; const context = { - initialize: { - outputs: null, - }, + initialize: {}, }; + const outputOptions = {outputPath: 'mock-path'}; // @ts-ignore - const result = await exhaust(tree, context, {}); + await exhaust(tree, context, outputOptions); - expect(result).toBeUndefined(); + expect.assertions(1); }); - it('uses log exhaust plugin as export.', async () => { + it('returns void if no exhaust plugin selected.', async () => { const tree = {}; const context = { initialize: {}, }; // @ts-ignore - await exhaust(tree, context, {'no-outout': false}); - expect(spy).toHaveBeenCalledTimes(1); - }); - - it('rejects with cli input error if output path is not provided with yaml.', async () => { - const tree = {}; - const context = { - initialize: { - outputs: ['yaml'], - }, - }; - - expect.assertions(2); - - try { - // @ts-ignore - await exhaust(tree, context, {}); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); + const result = await exhaust(tree, context, {}); - if (error instanceof ExhaustOutputArgError) { - expect(error.message).toEqual(OUTPUT_REQUIRED); - } - } + expect(result).toBeUndefined(); }); - it('rejects with module init error if output module is not supported.', async () => { + it('uses log exhaust plugin as export.', async () => { const tree = {}; const context = { - initialize: { - outputs: ['mock'], - }, + initialize: {}, }; - expect.assertions(2); - - try { - // @ts-ignore - await exhaust(tree, context, {}); - } catch (error) { - expect(error).toBeInstanceOf(InvalidExhaustPluginError); - - if (error instanceof InvalidExhaustPluginError) { - expect(error.message).toEqual( - INVALID_EXHAUST_PLUGIN(context.initialize.outputs[0]) - ); - } - } + // @ts-ignore + await exhaust(tree, context, {'no-outout': false}); + expect(spy).toHaveBeenCalledTimes(1); }); }); }); From 2ca87e633b66223bfeb11ad7a36773d7a542ee24 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 13:41:53 +0400 Subject: [PATCH 296/863] fix(manifests): optimized outputs for CI/CD --- .../failure-missing-global-config.yml | 34 ------- .../bugs/initialize-error-no-config.yaml | 78 ---------------- .../bugs/initialize-error-no-path.yaml | 91 ------------------ .../bugs/initialize-error-no-plugins.yaml | 74 --------------- manifests/outputs/divide.yaml | 93 ------------------- .../failure-invalid-instance-type.yaml | 61 +++++++++++- .../failure-invalid-vendor.yaml | 27 ------ .../failure-missing-cloud-vendor.yaml | 11 ++- .../csv-lookup/cloud-metadata/success.yaml | 11 ++- .../plugins/mock-observations/success.yaml | 80 ++++++++-------- .../failure-missing-global-config.yaml | 78 ---------------- 11 files changed, 110 insertions(+), 528 deletions(-) delete mode 100644 manifests/examples/builtins/time-sync/failure-missing-global-config.yml delete mode 100644 manifests/outputs/bugs/initialize-error-no-config.yaml delete mode 100644 manifests/outputs/bugs/initialize-error-no-path.yaml delete mode 100644 manifests/outputs/bugs/initialize-error-no-plugins.yaml delete mode 100644 manifests/outputs/divide.yaml delete mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml delete mode 100644 manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml diff --git a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml deleted file mode 100644 index 7b8e110fb..000000000 --- a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: time-sync -description: missing global config -tags: -initialize: - output: - - yaml - plugins: - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - # start-time: '2023-12-12T00:00:00.000Z' - # end-time: '2023-12-12T00:01:00.000Z' - # interval: 5 - # allow-padding: true -tree: - children: - child: - pipeline: - - time-sync - config: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 3 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - energy-cpu: 0.001 diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml deleted file mode 100644 index 56be9add7..000000000 --- a/manifests/outputs/bugs/initialize-error-no-config.yaml +++ /dev/null @@ -1,78 +0,0 @@ -name: initialize-error-no-config -description: >- - a negative test case that fails due to plugin initialization missing some - required config -tags: null -initialize: - outputs: - - yaml - plugins: - interpolate: - method: Interpolation - path: builtin - global-config: null -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-config.yml -o - manifests/outputs/bugs/initialize-error-no-config - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:45:41.936Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.interpolate.global-config" - parameter is expected object, received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml deleted file mode 100644 index e2ee4d616..000000000 --- a/manifests/outputs/bugs/initialize-error-no-path.yaml +++ /dev/null @@ -1,91 +0,0 @@ -name: initialize-error-no-path -description: >- - a negative test case that fails because the path is mising in a plugin - initialization -tags: null -initialize: - plugins: - interpolate: - method: Interpolation - path: null - 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-factor - outputs: - - yaml -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-path.yml -o - manifests/outputs/bugs/initialize-error-no-path - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:57:11.499Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.interpolate.path" parameter is - expected string, received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml deleted file mode 100644 index 208010e00..000000000 --- a/manifests/outputs/bugs/initialize-error-no-plugins.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: initialize-error-no-path -description: >- - a negative test case that fails becuase no plugins are included in the - initialize block -tags: null -initialize: - plugins: null - outputs: - - yaml -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-plugins.yml -o - manifests/outputs/bugs/initialize-error-no-plugins - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:52:35.214Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins" parameter is expected object, - received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/outputs/divide.yaml b/manifests/outputs/divide.yaml deleted file mode 100644 index e0875c420..000000000 --- a/manifests/outputs/divide.yaml +++ /dev/null @@ -1,93 +0,0 @@ -name: divide -description: success path -tags: null -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: - - cpu-cores-utilized - - vcpus-allocated - divide: - path: builtin - method: Divide - global-config: - numerator: vcpus-allocated - denominator: 2 - output: cpu/number-cores - outputs: - - yaml -execution: - command: >- - /home/joe/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /home/joe/Code/if/src/index.ts -m ./manifests/plugins/divide/success.yml -o - ./manifests/outputs/divide - environment: - if-version: 0.4.0 - os: linux - os-version: 5.15.0-113-generic - node-version: 21.4.0 - date-time: 2024-07-03T14:02:26.789Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child: - pipeline: - - cloud-metadata - - divide - config: - divide: null - defaults: - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 - outputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - vcpus-allocated: 2 - cpu/number-cores: 1 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index fa55623c2..6a8ed7fed 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -1,8 +1,9 @@ name: cloud-metadata description: cloud/instance-type instance type is not supported in the cloud vendor -tags: +tags: null initialize: - # outputs: ['yaml'] + outputs: + - yaml plugins: cloud-metadata: path: builtin @@ -12,15 +13,65 @@ initialize: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml + -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type-1 + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-04T13:44:58.641Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. tree: children: child: pipeline: - cloud-metadata - config: + config: null inputs: - - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + - timestamp: 2023-07-06T00:00 cloud/vendor: aws cloud/instance-type: m6 duration: 100 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml deleted file mode 100644 index c474c91fe..000000000 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: cloud-metadata -description: failure with invalid `inputs.cloud/vendor` -tags: -initialize: - #outputs: ['yaml'] - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - child: - pipeline: - - cloud-metadata - config: - inputs: - - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred - cloud/vendor: gcp - cloud/instance-type: m5n.large - duration: 100 - cpu/utilization: 10 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 943416663..adc1705eb 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -21,22 +21,25 @@ execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml -o - manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor1 environment: if-version: 0.4.0 os: macOS os-version: '13.2' node-version: 18.14.2 - date-time: 2024-07-02T21:20:08.333Z (UTC) + date-time: 2024-07-05T09:07:35.386Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml index 25c8db6e3..59a6d9739 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -20,21 +20,24 @@ execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yml -o - manifests/outputs/plugins/csv-lookup/cloud-metadata/success + manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/success1 environment: if-version: 0.4.0 os: macOS os-version: '13.2' node-version: 18.14.2 - date-time: 2024-07-02T21:21:45.504Z (UTC) + date-time: 2024-07-05T09:05:09.577Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> + file:../../../../if-unofficial-models - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/plugins/mock-observations/success.yaml index cacd16cad..e9629813c 100644 --- a/manifests/outputs/plugins/mock-observations/success.yaml +++ b/manifests/outputs/plugins/mock-observations/success.yaml @@ -83,138 +83,138 @@ tree: cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 81 - memory/utilization: 63 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 92 - memory/utilization: 63 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 63 - memory/utilization: 95 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 37 - memory/utilization: 13 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 28 - memory/utilization: 50 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 98 - memory/utilization: 29 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 10 - memory/utilization: 93 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 84 - memory/utilization: 37 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 10 - memory/utilization: 30 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 50 - memory/utilization: 10 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 97 - memory/utilization: 89 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 61 - memory/utilization: 83 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 86 - memory/utilization: 52 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 17 - memory/utilization: 60 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 53 - memory/utilization: 84 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 38 - memory/utilization: 58 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 4 - memory/utilization: 39 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 89 - memory/utilization: 52 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 38 - memory/utilization: 16 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 25 - memory/utilization: 78 + cpu/utilization: '*' + memory/utilization: '*' diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml deleted file mode 100644 index 79f3bb69e..000000000 --- a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml +++ /dev/null @@ -1,78 +0,0 @@ -name: time-sync -description: missing global config -tags: null -initialize: - outputs: - - yaml - plugins: - time-sync: - method: TimeSync - path: builtin - global-config: null -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/time-sync/failure-missing-global-config.yml -o - manifests/outputs/plugins/time-sync/failure-missing-global-config - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T21:13:12.360Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.time-sync.global-config" - parameter is expected object, received null. Error code: invalid_type. -tree: - children: - child: - pipeline: - - time-sync - config: null - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 3 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - energy-cpu: 0.001 From 743561c115ebff78dc5521ed02ad1c7acf66ff07 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:10:17 +0400 Subject: [PATCH 297/863] feat(package): update scripts --- package-lock.json | 8 ++++---- package.json | 25 +++++++++++-------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9d64c6b7b..dc90ceca3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,10 +24,10 @@ "zod": "^3.22.4" }, "bin": { - "if-check": "build/check.js", - "if-diff": "build/diff.js", - "if-env": "build/env.js", - "if-run": "build/index.js" + "if-check": "build/if-check/index.js", + "if-diff": "build/if-diff/index.js", + "if-env": "build/if-env/index.js", + "if-run": "build/if-run/index.js" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/package.json b/package.json index 0d965de37..bd89b8ddc 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,10 @@ "email": "info@gsf.com" }, "bin": { - "if-diff": "./build/diff.js", - "if-run": "./build/index.js", - "if-env": "./build/env.js", - "if-check": "./build/check.js" + "if-diff": "./build/if-diff/index.js", + "if-run": "./build/if-run/index.js", + "if-env": "./build/if-env/index.js", + "if-check": "./build/if-check/index.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -63,7 +63,6 @@ "models" ], "license": "MIT", - "main": "build/index.js", "publishConfig": { "access": "public" }, @@ -73,21 +72,19 @@ "scripts": { "build": "npm run clean && tsc --project tsconfig.build.json", "clean": "rimraf build/", - "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/unit", + "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/", "fix": "gts fix", "fix:package": "fixpack", - "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/check.ts", - "if-diff": "npx ts-node src/diff.ts", - "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", - "if-run": "npx ts-node src/index.ts", + "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-check/index.ts", + "if-diff": "npx ts-node src/if-diff/index.ts", + "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-env/index.ts", + "if-run": "npx ts-node src/if-run/index.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", "prepublish": "npm run build", "release": "release-it", - "test": "jest --verbose --testPathPattern=src/__tests__/unit", - "test:integration": "jest --verbose --testPathPattern=src/__tests__/integration" + "test": "jest --verbose --testPathPattern=src/__tests__/" }, - "stability": "stable", - "types": "src/index.d.ts" + "stability": "stable" } From a0b498d6a407f965e483066b5691c8e66282010b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:13:31 +0400 Subject: [PATCH 298/863] revert(src): remove old structure --- src/lib/aggregate.ts | 91 -------- src/lib/compare.ts | 67 ------ src/lib/compute.ts | 117 ----------- src/lib/environment.ts | 97 --------- src/lib/exhaust.ts | 68 ------ src/lib/initialize.ts | 115 ----------- src/lib/load.ts | 61 ------ src/lib/parameterize.ts | 77 ------- src/types/aggregation.ts | 3 - src/types/compute.ts | 30 --- src/types/environment.ts | 19 -- src/types/exhaust-plugin-interface.ts | 8 - src/types/if-env.ts | 6 - src/types/interface.ts | 9 - src/types/lib/compare.ts | 7 - src/types/manifest.ts | 18 -- src/types/npm.ts | 3 - src/types/parameters.ts | 7 - src/types/plugin-storage.ts | 8 - src/types/process-args.ts | 38 ---- src/types/time-sync.ts | 20 -- src/types/util/args.ts | 5 - src/util/aggregation-helper.ts | 68 ------ src/util/args.ts | 248 ---------------------- src/util/debug-logger.ts | 134 ------------ src/util/fs.ts | 68 ------ src/util/helpers.ts | 285 -------------------------- src/util/json.ts | 10 - src/util/log-memoize.ts | 20 -- src/util/logger.ts | 22 -- src/util/npm.ts | 193 ----------------- src/util/os-checker.ts | 112 ---------- src/util/plugin-storage.ts | 39 ---- src/util/validations.ts | 153 -------------- src/util/yaml.ts | 36 ---- 35 files changed, 2262 deletions(-) delete mode 100644 src/lib/aggregate.ts delete mode 100644 src/lib/compare.ts delete mode 100644 src/lib/compute.ts delete mode 100644 src/lib/environment.ts delete mode 100644 src/lib/exhaust.ts delete mode 100644 src/lib/initialize.ts delete mode 100644 src/lib/load.ts delete mode 100644 src/lib/parameterize.ts delete mode 100644 src/types/aggregation.ts delete mode 100644 src/types/compute.ts delete mode 100644 src/types/environment.ts delete mode 100644 src/types/exhaust-plugin-interface.ts delete mode 100644 src/types/if-env.ts delete mode 100644 src/types/interface.ts delete mode 100644 src/types/lib/compare.ts delete mode 100644 src/types/manifest.ts delete mode 100644 src/types/npm.ts delete mode 100644 src/types/parameters.ts delete mode 100644 src/types/plugin-storage.ts delete mode 100644 src/types/process-args.ts delete mode 100644 src/types/time-sync.ts delete mode 100644 src/types/util/args.ts delete mode 100644 src/util/aggregation-helper.ts delete mode 100644 src/util/args.ts delete mode 100644 src/util/debug-logger.ts delete mode 100644 src/util/fs.ts delete mode 100644 src/util/helpers.ts delete mode 100644 src/util/json.ts delete mode 100644 src/util/log-memoize.ts delete mode 100644 src/util/logger.ts delete mode 100644 src/util/npm.ts delete mode 100644 src/util/os-checker.ts delete mode 100644 src/util/plugin-storage.ts delete mode 100644 src/util/validations.ts delete mode 100644 src/util/yaml.ts diff --git a/src/lib/aggregate.ts b/src/lib/aggregate.ts deleted file mode 100644 index c6eef11cc..000000000 --- a/src/lib/aggregate.ts +++ /dev/null @@ -1,91 +0,0 @@ -import {PluginParams} from '@grnsft/if-core/types'; - -import {aggregateInputsIntoOne} from '../util/aggregation-helper'; - -import {STRINGS} from '../config/strings'; - -import {AggregationParams, AggregationParamsSure} from '../types/manifest'; - -const {AGGREGATING_NODE, AGGREGATING_OUTPUTS} = STRINGS; - -/** - * Gets `i`th element from all children outputs and collects them in single array. - */ -const getIthElementsFromChildren = (children: any, i: number) => { - const values = Object.values(children); - - return values.map((value: any) => { - const output = value.outputs; - - return output[i]; - }); -}; - -/** - * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). - * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. - */ -const temporalAggregation = (node: any, metrics: string[]) => { - const outputs: PluginParams[] = []; - const values: any = Object.values(node.children); - - for (let i = 0; i < values[0].outputs.length; i++) { - const ithSliceOfOutputs = getIthElementsFromChildren(node.children, i); - outputs.push(aggregateInputsIntoOne(ithSliceOfOutputs, metrics, true)); - } - - return outputs; -}; - -/** - * Navigates the tree depth first, bottom up, - * left to right aggregating the component nodes and then the grouping nodes will be aggregated - * only when all their child nodes have been aggregated. - * 1. Aggregates all the children. - * 2. At this point you can be positive all your children have been aggregated and so you can now work on aggregating yourself. - * 3. It's component node, аggregates just the outputs of THIS component node (horizontal/component aggregation). - * 4. Else it's grouping node, first does temporal aggregation. This assumes everything is on the same time-grid. - * The outputs of the grouping node are the aggregated time bucketed outputs of it's children. - * 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them. - */ -const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { - const metrics = aggregationParams!.metrics; - const type = aggregationParams!.type; - - if (node.children) { - for (const child in node.children) { - console.debug(AGGREGATING_NODE(child)); - - aggregateNode(node.children[child], aggregationParams); - } - } - - if (!node.children) { - if (type === 'horizontal' || type === 'both') { - node.aggregated = aggregateInputsIntoOne(node.outputs, metrics); - } - } else { - if (type === 'vertical' || type === 'both') { - const outputs = temporalAggregation(node, metrics); - node.outputs = outputs; - node.aggregated = aggregateInputsIntoOne(outputs, metrics); - } - } -}; - -/** - * If aggregation is disabled, then returns given `tree`. - * Otherwise creates copy of the tree, then applies aggregation to it. - */ -export const aggregate = (tree: any, aggregationParams: AggregationParams) => { - console.debug(AGGREGATING_OUTPUTS); - - if (!aggregationParams || !aggregationParams.type) { - return tree; - } - - const copyOfTree = structuredClone(tree); - aggregateNode(copyOfTree, aggregationParams); - - return copyOfTree; -}; diff --git a/src/lib/compare.ts b/src/lib/compare.ts deleted file mode 100644 index 34d084488..000000000 --- a/src/lib/compare.ts +++ /dev/null @@ -1,67 +0,0 @@ -import {checkIfEqual, oneIsPrimitive} from '../util/helpers'; - -import {Difference} from '../types/lib/compare'; - -/** - * 1. If objects are not of the same type or are primitive types, compares directly. - * 2. Gets the keys from both objects. - * 3. If both are arrays, checks their elements. - * 4. Checks for keys present in both objects. - * If key is `execution`, omit unnecessary params. - * 5. If all keys are checked and no differences are found, return empty object. - */ -export const compare = (source: any, target: any, path = ''): Difference => { - if (oneIsPrimitive(source, target)) { - return checkIfEqual(source, target) - ? {} - : { - path, - source, - target, - }; - } - - const keys1 = Object.keys(source); - const keys2 = Object.keys(target); - - const allKeys = new Set([...keys1, ...keys2]); - - if (path === '') { - allKeys.delete('name'); - allKeys.delete('description'); - allKeys.delete('tags'); - } - - if (path === 'initialize') { - allKeys.delete('outputs'); - } - - if (path === 'execution') { - const whitelist = ['status', 'error']; - allKeys.forEach(value => { - if (!whitelist.includes(value)) { - allKeys.delete(value); - } - }); - } - - if (Array.isArray(source) && Array.isArray(target)) { - source.forEach((_record, i) => { - compare(source[i], target[i], path ? `${path}[${i}]` : `${i}`); - }); - } - - for (const key of allKeys) { - const result = compare( - source[key], - target[key], - path ? `${path}.${key}` : key - ); - - if (Object.keys(result).length) { - return result; - } - } - - return {}; -}; diff --git a/src/lib/compute.ts b/src/lib/compute.ts deleted file mode 100644 index b83a22d2e..000000000 --- a/src/lib/compute.ts +++ /dev/null @@ -1,117 +0,0 @@ -import {PluginParams, GroupByConfig} from '@grnsft/if-core/types'; - -import {debugLogger} from '../util/debug-logger'; -import {mergeObjects} from '../util/helpers'; - -import {ComputeParams, Node, Params} from '../types/compute'; -import {isExecute, isGroupBy} from '../types/interface'; - -import {STRINGS} from '../config/strings'; - -const {MERGING_DEFAULTS_WITH_INPUT_DATA, COMPUTING_PIPELINE_FOR_NODE} = STRINGS; - -/** - * Traverses all child nodes based on children grouping. - */ -const traverse = async (children: any, params: Params) => { - for (const child in children) { - await computeNode(children[child], params); - } -}; - -/** - * Appends `default` values to `inputs`. - */ -const mergeDefaults = ( - inputs: PluginParams[], - defaults: PluginParams | undefined -) => { - if (inputs) { - const response = defaults - ? inputs.map(input => mergeObjects(defaults, input)) - : inputs; - - return response; - } - - console.debug(MERGING_DEFAULTS_WITH_INPUT_DATA); - - return defaults ? [defaults] : []; -}; - -/** - * 1. If the node has it's own pipeline, defaults or config then use that, - * otherwise use whatever has been passed down from further up the tree. - * 2. If it's a grouping node, then first of all computes all it's children. - * This is doing a depth first traversal. - * 3. Otherwise merges the defaults into the inputs. - * 4. Goes through the pipeline plugins, by checking if it's `execute` plugin. If so sets outputs. - * If is a `groupby` plugin, it will return child components rather than outputs. - * 5. Since after `groupby`, there are new child components, then computes them. - * Note: `pipeline` now equals the remaining plu.gins to apply to each child - */ -const computeNode = async (node: Node, params: Params): Promise => { - const pipeline = (node.pipeline || params.pipeline) as string[]; - const config = node.config || params.config; - const defaults = node.defaults || params.defaults; - - if (node.children) { - return traverse(node.children, { - ...params, - pipeline, - defaults, - config, - }); - } - - let inputStorage = structuredClone(node.inputs) as PluginParams[]; - inputStorage = mergeDefaults(inputStorage, defaults); - const pipelineCopy = structuredClone(pipeline); - - while (pipelineCopy.length !== 0) { - const pluginName = pipelineCopy.shift() as string; - const plugin = params.pluginStorage.get(pluginName); - const nodeConfig = config && config[pluginName]; - - console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); - debugLogger.setExecutingPluginName(pluginName); - - if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); - debugLogger.setExecutingPluginName(); - - node.outputs = inputStorage; - } - - if (isGroupBy(plugin)) { - node.children = await plugin.execute( - inputStorage, - nodeConfig as GroupByConfig - ); - delete node.inputs; - delete node.outputs; - - await traverse(node.children, { - ...params, - pipeline: pipelineCopy, - defaults, - config, - }); - - debugLogger.setExecutingPluginName(); - - break; - } - } -}; - -/** - * Creates copy of existing tree, then applies computing strategy. - */ -export const compute = async (tree: any, params: ComputeParams) => { - const copyOfTree = structuredClone(tree); - - await computeNode(copyOfTree, params); - - return copyOfTree; -}; diff --git a/src/lib/environment.ts b/src/lib/environment.ts deleted file mode 100644 index 52e2b0c9c..000000000 --- a/src/lib/environment.ts +++ /dev/null @@ -1,97 +0,0 @@ -import {DateTime} from 'luxon'; - -import {execPromise} from '../util/helpers'; - -import {Manifest} from '../types/manifest'; -import {NpmListResponse, PackageDependency} from '../types/environment'; -import {osInfo} from '../util/os-checker'; - -import {STRINGS} from '../config/strings'; - -const packageJson = require('../../package.json'); - -const {CAPTURING_RUNTIME_ENVIRONMENT_DATA} = STRINGS; - -/** - * 1. Gets the high-resolution real time when the application starts. - * 2. Converts the high-resolution time to milliseconds. - * 3. Gets the current DateTime. - * 4. Subtracts the milliseconds from the current DateTime. - */ -const getProcessStartingTimestamp = () => { - const startTime = process.hrtime(); - - const [seconds, nanoseconds] = process.hrtime(startTime); - const milliseconds = seconds * 1000 + nanoseconds / 1e6; - - const currentDateTime = DateTime.local(); - - const applicationStartDateTime = currentDateTime.minus({ - milliseconds: milliseconds, - }); - - return applicationStartDateTime.toUTC().toString(); -}; - -/** - * Goes through the dependencies, converts them into oneliner. - */ -const flattenDependencies = (dependencies: [string, PackageDependency][]) => - dependencies.map(dependency => { - const [packageName, versionInfo] = dependency; - const {version, extraneous, resolved} = versionInfo; - const ifExtraneous = extraneous ? ` extraneous -> ${resolved}` : ''; - const ifFromGithub = - resolved && resolved.startsWith('git') ? ` (${resolved})` : ''; - const formattedString = `${packageName}@${version}${ - ifExtraneous || ifFromGithub - }`; - - return formattedString; - }); - -/** - * 1. Runs `npm list --json`. - * 2. Parses json data and converts to list. - */ -const listDependencies = async () => { - const {stdout} = await execPromise('npm list --json'); - const npmListResponse: NpmListResponse = JSON.parse(stdout); - - if (npmListResponse.dependencies) { - const dependencies = Object.entries(npmListResponse.dependencies); - - return flattenDependencies(dependencies); - } - - return []; -}; - -/** - * Injects execution information (command, environment) to existing manifest. - */ -export const injectEnvironment = async ( - manifest: Manifest -): Promise => { - console.debug(CAPTURING_RUNTIME_ENVIRONMENT_DATA); - - const dependencies = await listDependencies(); - const info = await osInfo(); - const dateTime = `${getProcessStartingTimestamp()} (UTC)`; - - return { - ...manifest, - execution: { - status: 'success', - command: process.argv.join(' '), - environment: { - 'if-version': packageJson.version, - os: info.os, - 'os-version': info['os-version'], - 'node-version': process.versions.node, - 'date-time': dateTime, - dependencies, - }, - }, - }; -}; diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts deleted file mode 100644 index 1b65ca898..000000000 --- a/src/lib/exhaust.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -/** - * @todo This is temporary solution, will be refactored to support dynamic plugins. - */ -import {ExportCSV} from '../builtins/export-csv'; -import {ExportCSVRaw} from '../builtins/export-csv-raw'; -import {ExportLog} from '../builtins/export-log'; -import {ExportYaml} from '../builtins/export-yaml'; - -import {STRINGS} from '../config'; - -import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; -import {Context} from '../types/manifest'; -import {Options} from '../types/process-args'; - -const {InvalidExhaustPluginError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN, PREPARING_OUTPUT_DATA} = STRINGS; - -/** - * Initialize exhaust plugins based on the provided config - */ -const initializeExhaustPlugins = (plugins: string[]) => - plugins.map(initializeExhaustPlugin); - -/** - * Factory method for exhaust plugins. - */ -const initializeExhaustPlugin = (name: string): ExhaustPluginInterface => { - switch (name) { - case 'yaml': - return ExportYaml(); - case 'csv': - return ExportCSV(); - case 'csv-raw': - return ExportCSVRaw(); - default: - throw new InvalidExhaustPluginError(INVALID_EXHAUST_PLUGIN(name)); - } -}; - -/** - * Output manager - Exhaust. - * Grabs output plugins from context, executes every. - */ -export const exhaust = async ( - tree: any, - context: Context, - outputOptions: Options -) => { - console.debug(PREPARING_OUTPUT_DATA); - - const outputPlugins = context.initialize.outputs; - - if (outputOptions.stdout) { - ExportLog().execute(tree, context); - } - - if (!outputPlugins) { - return; - } - - const exhaustPlugins = initializeExhaustPlugins(outputPlugins); - - for await (const plugin of exhaustPlugins) { - await plugin.execute(tree, context, outputOptions.outputPath); - } -}; diff --git a/src/lib/initialize.ts b/src/lib/initialize.ts deleted file mode 100644 index 212d98e37..000000000 --- a/src/lib/initialize.ts +++ /dev/null @@ -1,115 +0,0 @@ -import * as path from 'node:path'; - -import {ERRORS} from '@grnsft/if-core/utils'; - -import {logger} from '../util/logger'; -import {memoizedLog} from '../util/log-memoize'; -import {pluginStorage} from '../util/plugin-storage'; - -import {CONFIG, STRINGS} from '../config'; - -import {PluginInterface} from '../types/interface'; -import {GlobalPlugins, PluginOptions} from '../types/manifest'; -import {PluginStorageInterface} from '../types/plugin-storage'; - -const { - PluginInitializationError, - MissingPluginMethodError, - MissingPluginPathError, -} = ERRORS; - -const {GITHUB_PATH, NATIVE_PLUGIN} = CONFIG; -const { - MISSING_METHOD, - MISSING_PATH, - NOT_NATIVE_PLUGIN, - INVALID_MODULE_PATH, - LOADING_PLUGIN_FROM_PATH, - INITIALIZING_PLUGIN, - INITIALIZING_PLUGINS, -} = STRINGS; - -/** - * Imports module by given `path`. - */ -const importModuleFrom = async (path: string) => { - const module = await import(path).catch(error => { - throw new PluginInitializationError(INVALID_MODULE_PATH(path, error)); - }); - - return module; -}; - -/** - * Imports `module` from given `path`, then checks if it's `ModelPluginInterface` extension. - */ -const importAndVerifyModule = async (method: string, path: string) => { - const pluginModule = await importModuleFrom(path); - - return pluginModule[method]; -}; - -/** - * Checks if plugin is missing then rejects with error. - * Then checks if `path` is starting with github, then grabs the repository name. - * Imports module, then checks if it's a valid plugin. - */ -const handModule = (method: string, pluginPath: string) => { - console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath)); - - if (pluginPath === 'builtin') { - pluginPath = path.normalize(`${__dirname}/../builtins`); - } else { - if (pluginPath?.startsWith(GITHUB_PATH)) { - const parts = pluginPath.split('/'); - pluginPath = parts[parts.length - 1]; - } - - if (!pluginPath.includes(NATIVE_PLUGIN)) { - memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(pluginPath)); - } - } - - return importAndVerifyModule(method, pluginPath); -}; - -/** - * Initializes plugin with global config. - */ -const initPlugin = async ( - initPluginParams: PluginOptions -): Promise => { - const {method, path, 'global-config': globalConfig} = initPluginParams; - - console.debug(INITIALIZING_PLUGIN(method)); - - if (!method) { - throw new MissingPluginMethodError(MISSING_METHOD); - } - - if (!path) { - throw new MissingPluginPathError(MISSING_PATH); - } - - const plugin = await handModule(method, path); - - return plugin(globalConfig); -}; - -/** - * Registers all plugins from `manifest`.`initialize` property. - */ -export const initialize = async ( - plugins: GlobalPlugins -): Promise => { - console.debug(INITIALIZING_PLUGINS); - - const storage = pluginStorage(); - - for await (const pluginName of Object.keys(plugins)) { - const plugin = await initPlugin(plugins[pluginName]); - storage.set(pluginName, plugin); - } - - return storage; -}; diff --git a/src/lib/load.ts b/src/lib/load.ts deleted file mode 100644 index 61f2b6cf5..000000000 --- a/src/lib/load.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as YAML from 'js-yaml'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {openYamlFileAsObject} from '../util/yaml'; -import {readAndParseJson} from '../util/json'; - -import {PARAMETERS} from '../config'; -import {STRINGS} from '../config'; - -import {Parameters} from '../types/parameters'; -import {LoadDiffParams} from '../types/util/args'; -import {Manifest} from '../types/manifest'; - -const {CliSourceFileError} = ERRORS; - -const {INVALID_SOURCE, LOADING_MANIFEST} = STRINGS; - -/** - * Parses manifest file as an object. Checks if parameter file is passed via CLI, then loads it too. - * Returns context, tree and parameters (either the default one, or from CLI). - */ -export const load = async (inputPath: string, paramPath?: string) => { - console.debug(LOADING_MANIFEST); - - const rawManifest = await openYamlFileAsObject(inputPath); - const parametersFromCli = - paramPath && - (await readAndParseJson(paramPath)); /** @todo validate json */ - const parameters = - parametersFromCli || - PARAMETERS; /** @todo PARAMETERS should be specified in parameterize only */ - - return { - rawManifest, - parameters, - }; -}; - -/** - * Loads files to compare. As a source file checks if data is piped and then decides which one to take. - */ -export const loadIfDiffFiles = async (params: LoadDiffParams) => { - const {sourcePath, targetPath, pipedSourceManifest} = params; - - if (!sourcePath && !pipedSourceManifest) { - throw new CliSourceFileError(INVALID_SOURCE); - } - - const loadFromSource = - sourcePath && (await openYamlFileAsObject(sourcePath!)); - const loadFromSTDIN = - pipedSourceManifest && (await YAML.load(pipedSourceManifest!)); - - const rawSourceManifest = loadFromSource || loadFromSTDIN; - const rawTargetManifest = await openYamlFileAsObject(targetPath); - - return { - rawSourceManifest, - rawTargetManifest, - }; -}; diff --git a/src/lib/parameterize.ts b/src/lib/parameterize.ts deleted file mode 100644 index 591ef781e..000000000 --- a/src/lib/parameterize.ts +++ /dev/null @@ -1,77 +0,0 @@ -import {logger} from '../util/logger'; -import {memoizedLog} from '../util/log-memoize'; -import {debugLogger} from '../util/debug-logger'; - -import {STRINGS, PARAMETERS} from '../config'; - -import {ManifestParameter} from '../types/manifest'; -import {Parameters} from '../types/parameters'; - -const { - REJECTING_OVERRIDE, - UNKNOWN_PARAM, - SYNCING_PARAMETERS, - CHECKING_AGGREGATION_METHOD, -} = STRINGS; - -/** - * Parameters manager. Provides get aggregation method and combine functionality. - */ -const Parameterize = () => { - let parametersStorage = PARAMETERS; - - /** - * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. - */ - const getAggregationMethod = (unitName: string) => { - debugLogger.setExecutingPluginName(); - memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); - - if (`${unitName}` in parametersStorage) { - return parametersStorage[unitName as keyof typeof PARAMETERS].aggregation; - } - - memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - - return 'sum'; - }; - - /** - * Checks if additional parameters are provided in context. - * If so, then checks if they are coincident with default ones and exits with warning message. - * Otherwise appends context based parameters to defaults. - */ - const combine = ( - contextParameters: ManifestParameter[] | null | undefined, - parameters: Parameters - ) => { - console.debug(SYNCING_PARAMETERS); - - if (contextParameters) { - contextParameters.forEach(param => { - if (`${param.name}` in parameters) { - logger.warn(REJECTING_OVERRIDE(param)); - - return; - } - - const {description, unit, aggregation, name} = param; - - parameters[name] = { - description, - unit, - aggregation, - }; - }); - } - - parametersStorage = parameters; - }; - - return { - combine, - getAggregationMethod, - }; -}; - -export const parameterize = Parameterize(); diff --git a/src/types/aggregation.ts b/src/types/aggregation.ts deleted file mode 100644 index d15322d29..000000000 --- a/src/types/aggregation.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type AggregationResult = Record; - -export const AGGREGATION_METHODS = ['horizontal', 'vertical', 'both'] as const; diff --git a/src/types/compute.ts b/src/types/compute.ts deleted file mode 100644 index 2de3e6e33..000000000 --- a/src/types/compute.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {PluginParams} from '@grnsft/if-core/types'; - -import {Context} from './manifest'; -import {PluginStorageInterface} from './plugin-storage'; - -export type NodeConfig = { - [key: string]: Record; -}; - -export type Params = { - pluginStorage: PluginStorageInterface; - context: Context; - pipeline?: string[]; - config?: NodeConfig; - defaults?: PluginParams; -}; - -export type Node = { - children?: any; - pipeline?: string[]; - config?: NodeConfig; - defaults?: PluginParams; - inputs?: PluginParams[]; - outputs?: PluginParams[]; -}; - -export type ComputeParams = { - context: Context; - pluginStorage: PluginStorageInterface; -}; diff --git a/src/types/environment.ts b/src/types/environment.ts deleted file mode 100644 index 94c3e6a82..000000000 --- a/src/types/environment.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type PackageDependency = { - version: string; - resolved?: string; - overridden: boolean; - extraneous?: boolean; -}; - -type PackageProblem = { - extraneous: string; -}; - -export type NpmListResponse = { - version: string; - name: string; - problems?: PackageProblem[]; - dependencies: { - [key: string]: PackageDependency; - }; -}; diff --git a/src/types/exhaust-plugin-interface.ts b/src/types/exhaust-plugin-interface.ts deleted file mode 100644 index 3dc00182a..000000000 --- a/src/types/exhaust-plugin-interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Context} from './manifest'; - -export interface ExhaustPluginInterface { - /** - * Execute exhaust based on `context` and `tree`, produce output to a file in `outputPath`. - */ - execute(tree: any, context: Context, outputPath?: string): void; -} diff --git a/src/types/if-env.ts b/src/types/if-env.ts deleted file mode 100644 index 03ace8ec9..000000000 --- a/src/types/if-env.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type EnvironmentOptions = { - folderPath: string; - install: boolean; - cwd: boolean; - dependencies: {[path: string]: string}; -}; diff --git a/src/types/interface.ts b/src/types/interface.ts deleted file mode 100644 index 6834a3ebb..000000000 --- a/src/types/interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {ExecutePlugin, GroupByPlugin} from '@grnsft/if-core/types'; - -export type PluginInterface = ExecutePlugin | GroupByPlugin; - -export const isExecute = (plugin: PluginInterface): plugin is ExecutePlugin => - (plugin as ExecutePlugin).metadata.kind === 'execute'; - -export const isGroupBy = (plugin: PluginInterface): plugin is GroupByPlugin => - (plugin as GroupByPlugin).metadata.kind === 'groupby'; diff --git a/src/types/lib/compare.ts b/src/types/lib/compare.ts deleted file mode 100644 index 0f0cae8cf..000000000 --- a/src/types/lib/compare.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type Difference = { - path?: string; - source?: any; - target?: any; - message?: string; - [key: string]: any; -}; diff --git a/src/types/manifest.ts b/src/types/manifest.ts deleted file mode 100644 index 2359a3433..000000000 --- a/src/types/manifest.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {z} from 'zod'; - -import {manifestSchema} from '../util/validations'; - -export type Manifest = z.infer; - -export type GlobalPlugins = Manifest['initialize']['plugins']; - -export type PluginOptions = GlobalPlugins[string]; - -export type AggregationParams = Manifest['aggregation']; -export type AggregationParamsSure = Extract; - -export type Context = Omit; - -export type ContextWithExec = Omit; - -export type ManifestParameter = Extract[number]; diff --git a/src/types/npm.ts b/src/types/npm.ts deleted file mode 100644 index cbb3e0680..000000000 --- a/src/types/npm.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type PathWithVersion = {[path: string]: string}; - -export type ManifestPlugin = {[key: string]: {path: string; method: string}}; diff --git a/src/types/parameters.ts b/src/types/parameters.ts deleted file mode 100644 index 7434777ce..000000000 --- a/src/types/parameters.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {ManifestParameter} from './manifest'; - -export const AGGREGATION_TYPES = ['sum', 'none', 'avg'] as const; - -type ParameterProps = Omit; - -export type Parameters = Record; diff --git a/src/types/plugin-storage.ts b/src/types/plugin-storage.ts deleted file mode 100644 index 0d3d865c5..000000000 --- a/src/types/plugin-storage.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {pluginStorage} from '../util/plugin-storage'; -import {PluginInterface} from './interface'; - -export type PluginStorage = { - [key: string]: PluginInterface; -}; - -export type PluginStorageInterface = ReturnType; diff --git a/src/types/process-args.ts b/src/types/process-args.ts deleted file mode 100644 index 0f3799f5a..000000000 --- a/src/types/process-args.ts +++ /dev/null @@ -1,38 +0,0 @@ -export interface IEArgs { - manifest?: string; - output?: string; - 'override-params'?: string; - stdout?: boolean; - debug?: boolean; -} - -export interface IFDiffArgs { - source?: string; - target: string; -} - -export interface IFEnvArgs { - manifest?: string; - install?: boolean; - cwd?: boolean; -} - -export interface IFCheckArgs { - manifest?: string; - directory?: string; -} - -export interface Options { - outputPath?: string; - stdout?: boolean; -} - -export interface ProcessArgsOutputs { - inputPath: string; - outputOptions: { - outputPath?: string; - stdout?: boolean; - }; - paramPath?: string; - debug?: boolean; -} diff --git a/src/types/time-sync.ts b/src/types/time-sync.ts deleted file mode 100644 index 505a91f82..000000000 --- a/src/types/time-sync.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {DateTime} from 'luxon'; - -export type TimeNormalizerConfig = { - 'start-time': Date | string; - 'end-time': Date | string; - interval: number; - 'allow-padding': boolean; -}; - -export type PaddingReceipt = { - start: boolean; - end: boolean; -}; - -export type TimeParams = { - startTime: DateTime; - endTime: DateTime; - interval: number; - allowPadding: boolean; -}; diff --git a/src/types/util/args.ts b/src/types/util/args.ts deleted file mode 100644 index ae78fa4d0..000000000 --- a/src/types/util/args.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type LoadDiffParams = { - sourcePath?: string; - targetPath: string; - pipedSourceManifest?: string; -}; diff --git a/src/util/aggregation-helper.ts b/src/util/aggregation-helper.ts deleted file mode 100644 index 408a4e9f7..000000000 --- a/src/util/aggregation-helper.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {PluginParams} from '@grnsft/if-core/types'; - -import {parameterize} from '../lib/parameterize'; - -import {CONFIG, STRINGS} from '../config'; - -import {AggregationResult} from '../types/aggregation'; - -const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; -const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; -const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; - -/** - * Validates metrics array before applying aggregator. - * If aggregation method is `none`, then throws error. - */ -const checkIfMetricsAreValid = (metrics: string[]) => { - metrics.forEach(metric => { - const method = parameterize.getAggregationMethod(metric); - - if (method === 'none') { - throw new InvalidAggregationMethodError( - INVALID_AGGREGATION_METHOD(metric) - ); - } - }); -}; - -/** - * Aggregates child node level metrics. Validates if metric aggregation type is `none`, then rejects with error. - * Appends aggregation additional params to metrics. Otherwise iterates over inputs by aggregating per given `metrics`. - */ -export const aggregateInputsIntoOne = ( - inputs: PluginParams[], - metrics: string[], - isTemporal?: boolean -) => { - checkIfMetricsAreValid(metrics); - const extendedMetrics = [...metrics, ...AGGREGATION_ADDITIONAL_PARAMS]; - - return inputs.reduce((acc, input, index) => { - for (const metric of extendedMetrics) { - if (!(metric in input)) { - throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); - } - - /** Checks if metric is timestamp or duration, then adds to aggregated value. */ - if (AGGREGATION_ADDITIONAL_PARAMS.includes(metric)) { - if (isTemporal) { - acc[metric] = input[metric]; - } - } else { - acc[metric] = acc[metric] ?? 0; - acc[metric] += parseFloat(input[metric]); - - /** Checks for the last iteration. */ - if (index === inputs.length - 1) { - if (parameterize.getAggregationMethod(metric) === 'avg') { - acc[metric] /= inputs.length; - } - } - } - } - - return acc; - }, {} as AggregationResult); -}; diff --git a/src/util/args.ts b/src/util/args.ts deleted file mode 100644 index 31da90461..000000000 --- a/src/util/args.ts +++ /dev/null @@ -1,248 +0,0 @@ -import * as path from 'path'; - -import {parse} from 'ts-command-line-args'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {checkIfFileIsYaml} from './yaml'; - -import {isDirectoryExists, isFileExists} from './fs'; - -import {logger} from './logger'; - -import {CONFIG, STRINGS} from '../config'; - -import { - IFDiffArgs, - IEArgs, - ProcessArgsOutputs, - IFEnvArgs, - IFCheckArgs, -} from '../types/process-args'; -import {LoadDiffParams} from '../types/util/args'; - -const { - ParseCliParamsError, - CliTargetFileError, - CliSourceFileError, - InvalidDirectoryError, - MissingCliFlagsError, -} = ERRORS; - -const {IE, IF_DIFF, IF_ENV, IF_CHECK} = CONFIG; - -const { - MANIFEST_IS_MISSING, - MANIFEST_NOT_FOUND, - NO_OUTPUT, - SOURCE_IS_NOT_YAML, - TARGET_IS_NOT_YAML, - INVALID_TARGET, - IF_CHECK_FLAGS_MISSING, - DIRECTORY_NOT_FOUND, -} = STRINGS; - -/** - * Validates `ie` process arguments. - */ -const validateAndParseProcessArgs = () => { - try { - return parse(IE.ARGS, IE.HELP); - } catch (error) { - if (error instanceof Error) { - throw new ParseCliParamsError(error.message); - } - - throw error; - } -}; - -/** - * Prepends process path to given `filePath`. - */ -const prependFullFilePath = (filePath: string) => { - const processRunningPath = process.cwd(); - - if (path.isAbsolute(filePath)) { - return filePath; - } - - return path.normalize(`${processRunningPath}/${filePath}`); -}; - -/** - * 1. Parses process arguments like `manifest`, `output`, `override-params`, `help` and `debug`. - * 2. Checks if `help` param is provided, then logs help message and exits. - * 3. If output params are missing, warns user about it. - * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. - * If it is, then returns object containing full path. - * 4. If params are missing or invalid, then rejects with `ParseCliParamsError`. - */ -export const parseIEProcessArgs = (): ProcessArgsOutputs => { - const { - manifest, - output, - 'override-params': overrideParams, - stdout, - debug, - } = validateAndParseProcessArgs(); - - if (!output && !stdout) { - logger.warn(NO_OUTPUT); - } - - if (manifest) { - if (checkIfFileIsYaml(manifest)) { - return { - inputPath: prependFullFilePath(manifest), - outputOptions: { - ...(output && {outputPath: prependFullFilePath(output)}), - ...(stdout && {stdout}), - }, - ...(overrideParams && {paramPath: overrideParams}), - debug, - }; - } - - throw new CliSourceFileError(SOURCE_IS_NOT_YAML); - } - - throw new CliSourceFileError(MANIFEST_IS_MISSING); -}; - -/** -- IF Diff -- */ - -/** - * Parses `if-diff` process arguments. - */ -const validateAndParseIfDiffArgs = () => { - try { - return parse(IF_DIFF.ARGS, IF_DIFF.HELP); - } catch (error) { - if (error instanceof Error) { - throw new ParseCliParamsError(error.message); - } - - throw error; - } -}; - -/** - * Checks for `source` and `target` flags to be present. - */ -export const parseIfDiffArgs = () => { - const {source, target} = validateAndParseIfDiffArgs(); - - if (target) { - if (source && !checkIfFileIsYaml(source)) { - throw new CliSourceFileError(SOURCE_IS_NOT_YAML); - } - - if (checkIfFileIsYaml(target)) { - const response: LoadDiffParams = { - targetPath: prependFullFilePath(target), - }; - - if (source && checkIfFileIsYaml(source)) { - response.sourcePath = prependFullFilePath(source); - } - - return response; - } - - throw new CliTargetFileError(TARGET_IS_NOT_YAML); - } - - throw new ParseCliParamsError(INVALID_TARGET); -}; - -/** -- IF Env -- */ - -/** - * Parses `if-env` process arguments. - */ -const validateAndParseIfEnvArgs = () => { - try { - return parse(IF_ENV.ARGS, IF_ENV.HELP); - } catch (error) { - if (error instanceof Error) { - throw new ParseCliParamsError(error.message); - } - - throw error; - } -}; - -/** - * Checks if the `manifest` command is provided and it is valid manifest file. - */ -export const parseIfEnvArgs = async () => { - const {manifest, install, cwd} = validateAndParseIfEnvArgs(); - - if (manifest) { - const response = prependFullFilePath(manifest); - const isManifestFileExists = await isFileExists(response); - - if (!isManifestFileExists) { - throw new ParseCliParamsError(MANIFEST_NOT_FOUND); - } - - if (checkIfFileIsYaml(manifest)) { - return {manifest: response, install, cwd}; - } - - throw new CliSourceFileError(SOURCE_IS_NOT_YAML); - } - - return {install, cwd}; -}; - -/** -- IF Check -- */ - -/** - * Parses `if-check` process arguments. - */ -const validateAndParseIfCheckArgs = () => { - try { - return parse(IF_CHECK.ARGS, IF_CHECK.HELP); - } catch (error) { - if (error instanceof Error) { - throw new ParseCliParamsError(error.message); - } - - throw error; - } -}; - -/** - * Checks if either `manifest` or `directory` command is provided. - */ -export const parseIfCheckArgs = async () => { - const {manifest, directory} = validateAndParseIfCheckArgs(); - - if (manifest) { - const response = prependFullFilePath(manifest); - const isManifestFileExists = await isFileExists(response); - - if (!isManifestFileExists) { - throw new ParseCliParamsError(MANIFEST_NOT_FOUND); - } - - if (checkIfFileIsYaml(manifest)) { - return {manifest}; - } - - throw new CliSourceFileError(SOURCE_IS_NOT_YAML); - } else if (directory) { - const isDirExists = await isDirectoryExists(directory); - - if (!isDirExists) { - throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); - } - - const response = prependFullFilePath(directory); - - return {directory: response}; - } - - throw new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING); -}; diff --git a/src/util/debug-logger.ts b/src/util/debug-logger.ts deleted file mode 100644 index f1f34ae0e..000000000 --- a/src/util/debug-logger.ts +++ /dev/null @@ -1,134 +0,0 @@ -import {STRINGS} from '../config/strings'; - -const logMessagesKeys: (keyof typeof STRINGS)[] = [ - 'STARTING_IF', - 'EXITING_IF', - 'LOADING_MANIFEST', - 'VALIDATING_MANIFEST', - 'CAPTURING_RUNTIME_ENVIRONMENT_DATA', - 'SYNCING_PARAMETERS', - 'CHECKING_AGGREGATION_METHOD', - 'INITIALIZING_PLUGINS', - 'INITIALIZING_PLUGIN', - 'LOADING_PLUGIN_FROM_PATH', - 'COMPUTING_PIPELINE_FOR_NODE', - 'MERGING_DEFAULTS_WITH_INPUT_DATA', - 'AGGREGATING_OUTPUTS', - 'AGGREGATING_NODE', - 'PREPARING_OUTPUT_DATA', - 'EXPORTING_TO_YAML_FILE', - 'EXPORTING_TO_CSV_FILE', - 'EXPORTING_RAW_CSV_FILE', -]; - -enum LogLevel { - Info = 'INFO', - Warn = 'WARN', - Error = 'ERROR', - Debug = 'DEBUG', -} - -const originalConsole = { - log: console.log, - info: console.info, - warn: console.warn, - error: console.error, - debug: console.debug, -}; - -/** - * Overrides console methods with custom debug logging. - */ -const overrideConsoleMethods = (debugMode: boolean) => { - console.log = (...args: any[]) => debugLog(LogLevel.Info, args, debugMode); - console.info = (...args: any[]) => debugLog(LogLevel.Info, args, debugMode); - console.warn = (...args: any[]) => debugLog(LogLevel.Warn, args, debugMode); - console.error = (...args: any[]) => debugLog(LogLevel.Error, args, debugMode); - console.debug = (...args: any[]) => debugLog(LogLevel.Debug, args, debugMode); -}; - -/** - * Creates an encapsulated object to retrieve the plugin name. - */ -const pluginNameManager = (() => { - let pluginName: string | undefined = ''; - - const manager = { - get currentPluginName() { - return pluginName; - }, - set currentPluginName(value: string | undefined) { - pluginName = value; - }, - }; - - return manager; -})(); - -/** - * Sets the name of the currently executing plugin. - */ -const setExecutingPluginName = (pluginName?: string) => { - pluginNameManager.currentPluginName = pluginName; -}; - -/** - * Logs messages with the specified log level and format. - */ -const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { - if (!debugMode) { - if (level === LogLevel.Debug) { - return; - } - - const isDebugLog = - typeof args[0] === 'string' && - logMessagesKeys.some(key => { - const message = - typeof STRINGS[key] === 'function' - ? (STRINGS[key] as Function).call(null, '') - : (STRINGS[key] as string); - - return args[0].includes(message); - }); - - if (!isDebugLog) { - originalConsole.log(...args); - } - - return; - } - - if (args[0].includes('# start')) { - originalConsole.log(...args); - return; - } - - const date = new Date().toISOString(); - const plugin = pluginNameManager.currentPluginName; - const formattedMessage = `${level}: ${date}: ${ - plugin ? plugin + ': ' : '' - }${args.join(', ')}`; - - if (debugMode) { - switch (level) { - case LogLevel.Info: - originalConsole.info(formattedMessage); - break; - case LogLevel.Warn: - originalConsole.warn(formattedMessage); - break; - case LogLevel.Error: - originalConsole.error(formattedMessage); - break; - case LogLevel.Debug: - originalConsole.debug(formattedMessage); - break; - } - } -}; - -export const debugLogger = { - overrideConsoleMethods, - setExecutingPluginName, -}; diff --git a/src/util/fs.ts b/src/util/fs.ts deleted file mode 100644 index bf10af9ba..000000000 --- a/src/util/fs.ts +++ /dev/null @@ -1,68 +0,0 @@ -import * as fs from 'fs/promises'; -import * as path from 'path'; - -/** - * Checks if file exists with the given `filePath`. - */ -export const isFileExists = async (filePath: string) => { - try { - await fs.stat(filePath); - return true; - } catch (error) { - return false; - } -}; - -/** - * Checks if the directory exists with the given `filePath`. - */ -export const isDirectoryExists = async (directoryPath: string) => { - try { - await fs.access(directoryPath); - return true; - } catch (error) { - return false; - } -}; - -/** - * Gets all files that have either .yml or .yaml extension in the given directory. - */ -export const getYamlFiles = async (directory: string) => { - let yamlFiles: string[] = []; - - const files = await fs.readdir(directory); - - for (const file of files) { - const fullPath = path.join(directory, file); - const stat = await fs.lstat(fullPath); - - if (stat.isDirectory()) { - yamlFiles = yamlFiles.concat(await getYamlFiles(fullPath)); - } else { - if (file.endsWith('.yml') || file.endsWith('.yaml')) { - yamlFiles.push(fullPath); - } - } - } - - return yamlFiles; -}; - -/** - * Gets fileName from the given path without an extension. - */ -export const getFileName = (filePath: string) => { - const baseName = path.basename(filePath); - const extension = path.extname(filePath); - return baseName.replace(extension, ''); -}; - -/** - * Removes the given file if exists. - */ -export const removeFileIfExists = async (filePath: string) => { - if (await isFileExists(filePath)) { - await fs.unlink(filePath); - } -}; diff --git a/src/util/helpers.ts b/src/util/helpers.ts deleted file mode 100644 index c55b43724..000000000 --- a/src/util/helpers.ts +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-process-exit */ -import {createInterface} from 'node:readline/promises'; -import {exec} from 'node:child_process'; -import {promisify} from 'node:util'; - -import * as fs from 'fs/promises'; -import * as path from 'path'; - -import {ERRORS} from '@grnsft/if-core/utils'; - -import {STRINGS, CONFIG} from '../config'; - -import {Difference} from '../types/lib/compare'; - -import {load} from '../lib/load'; - -import { - installDependencies, - initPackageJsonIfNotExists, - updatePackageJsonDependencies, - extractPathsWithVersion, - updatePackageJsonProperties, -} from './npm'; - -import {logger} from './logger'; -import {EnvironmentOptions} from '../types/if-env'; - -const {IF_ENV} = CONFIG; -const { - FAILURE_MESSAGE, - FAILURE_MESSAGE_TEMPLATE, - FAILURE_MESSAGE_DEPENDENCIES, -} = IF_ENV; - -const {UNSUPPORTED_ERROR, IF_CHECK_FAILED, IF_CHECK_SUMMARY_ERROR_MESSAGE} = - STRINGS; -const {MissingPluginDependenciesError} = ERRORS; - -/** - * Impact engine error handler. Logs errors and appends issue template if error is unknown. - */ -export const andHandle = (error: Error) => { - const knownErrors = Object.keys(ERRORS); - - logger.error(error); - - if (!knownErrors.includes(error.name)) { - logger.error(UNSUPPORTED_ERROR(error.name)); - // eslint-disable-next-line no-process-exit - process.exit(2); - } -}; - -/** - * Append entries from defaults which are missing from inputs. - */ -export const mergeObjects = (defaults: any, input: any) => { - const merged: Record = structuredClone(input); - - for (const key in defaults) { - if (!(key in input)) { - merged[key] = defaults[key]; - } - - if (merged[key] === undefined || merged[key] === null) { - merged[key] = defaults[key]; - } - } - - return merged; -}; - -/** - * Promise version of Node's `exec` from `child-process`. - */ -export const execPromise = promisify(exec); - -/** - * `If-diff` equality checker. - */ -export const checkIfEqual = (source: any, target: any) => { - if (source === target) { - return true; - } - - if (source === '*' || target === '*') { - return true; - } - - return false; -}; - -/** - * Converts given `value` to either `1` or `0`. - */ -const convertToXorable = (value: any) => { - if (typeof value === 'number') { - return value !== 0 ? 1 : 0; - } - - if (typeof value === 'boolean') { - return value ? 1 : 0; - } - - if (typeof value === 'string') { - return value.length > 0 ? 1 : 0; - } - - if (typeof value === 'object') { - return 1; - } - - return 0; -}; - -/** - * If one of the `valuesToCheck` values is undefined, then set `missing`, otherwise `exists`. - */ -const setValuesIfMissing = (response: Difference) => { - const source = convertToXorable(response.source); - const target = convertToXorable(response.target); - - if (source ^ target) { - ['source', 'target'].forEach(value => { - response[value] = response[value] ? 'exists' : 'missing'; - }); - - return response; - } - - return response; -}; - -/** - * Checks if objects are primitive types. - */ -export const oneIsPrimitive = (source: any, target: any) => { - // eslint-disable-next-line eqeqeq - if (source == null || target == null) { - return true; - } - - return source !== Object(source) && target !== Object(target); -}; - -/** - * Format not matching message for CLI logging. - */ -export const formatNotMatchingLog = (message: Difference) => { - const flattenMessage = setValuesIfMissing(message); - - Object.keys(flattenMessage).forEach(key => { - if (key === 'message' || key === 'path') { - console.log(message[key]); - } else { - console.log(`${key}: ${message[key]}`); - } - }); -}; - -/** - * Checks if there is data piped, then collects it. - * Otherwise returns empty string. - */ -const collectPipedData = async () => { - if (process.stdin.isTTY) { - return ''; - } - - const readline = createInterface({ - input: process.stdin, - }); - - const data: string[] = []; - - for await (const line of readline) { - data.push(line); - } - - return data.join('\n'); -}; - -/** - * Checks if there is piped data, tries to parse yaml from it. - * Returns empty string if haven't found anything. - */ -export const parseManifestFromStdin = async () => { - const pipedSourceManifest = await collectPipedData(); - - if (!pipedSourceManifest) { - return ''; - } - - const regex = /# start((?:.*\n)+?)# end/; - const match = regex.exec(pipedSourceManifest); - - if (!match) { - return ''; - } - - return match![1]; -}; - -/** - * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. - */ -export const getOptionsFromArgs = async (commandArgs: { - manifest: string; - install: boolean | undefined; -}) => { - const {manifest, install} = commandArgs; - const folderPath = path.dirname(manifest); - const loadedManifest = await load(manifest); - const rawManifest = loadedManifest.rawManifest; - const plugins = rawManifest?.initialize?.plugins || {}; - const dependencies = rawManifest?.execution?.environment.dependencies || []; - - if (!dependencies.length) { - throw new MissingPluginDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); - } - - const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); - - return { - folderPath, - dependencies: pathsWithVersion, - install, - }; -}; - -/** - * Creates folder if not exists, installs dependencies if required, update depenedencies. - */ -export const initializeAndInstallLibs = async (options: EnvironmentOptions) => { - try { - const {folderPath, install, cwd, dependencies} = options; - const packageJsonPath = await initPackageJsonIfNotExists(folderPath); - - await updatePackageJsonProperties(packageJsonPath, cwd); - - if (install) { - await installDependencies(folderPath, dependencies); - } else { - await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); - } - } catch (error) { - console.log(FAILURE_MESSAGE); - process.exit(2); - } -}; - -/** - * Adds a manifest template to the folder where the if-env CLI command runs. - */ -export const addTemplateManifest = async (destinationDir: string) => { - try { - const templateManifest = path.resolve( - __dirname, - '../config/env-template.yml' - ); - - const destinationPath = path.resolve(destinationDir, 'manifest.yml'); - const data = await fs.readFile(templateManifest, 'utf-8'); - - await fs.writeFile(destinationPath, data, 'utf-8'); - } catch (error) { - console.log(FAILURE_MESSAGE_TEMPLATE); - process.exit(1); - } -}; - -/** - * Logs the failure message from the stdout of an error. - */ -export const logStdoutFailMessage = (error: any, fileName: string) => { - console.log(IF_CHECK_FAILED(fileName)); - - const stdout = error.stdout; - const logs = stdout.split('\n\n'); - const failMessage = logs[logs.length - 1]; - - console.log(failMessage); - return IF_CHECK_SUMMARY_ERROR_MESSAGE(fileName, failMessage); -}; diff --git a/src/util/json.ts b/src/util/json.ts deleted file mode 100644 index c9180a788..000000000 --- a/src/util/json.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as fs from 'fs/promises'; - -/** - * Reads and parses json file. - */ -export const readAndParseJson = async (paramPath: string): Promise => { - const file = await fs.readFile(paramPath, 'utf-8'); - - return JSON.parse(file) as T; -}; diff --git a/src/util/log-memoize.ts b/src/util/log-memoize.ts deleted file mode 100644 index f0afa4d9e..000000000 --- a/src/util/log-memoize.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {LeveledLogMethod} from 'winston'; - -/** - * Keeps in memory logged messages. If called with redundant message, skips logging. - */ -const memoizedLogger = () => { - const memory: string[] = []; - - return (logger: LeveledLogMethod | typeof console.debug, message: string) => { - if (memory.includes(message)) { - return; - } - - memory.push(message); - logger(message); - }; -}; - -/** Singleton pattern. */ -export const memoizedLog = memoizedLogger(); diff --git a/src/util/logger.ts b/src/util/logger.ts deleted file mode 100644 index 4d01d5960..000000000 --- a/src/util/logger.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as winston from 'winston'; - -const {combine, timestamp, printf, colorize, align} = winston.format; - -/** - * Winston logger instance. - */ -export const logger = winston.createLogger({ - format: combine( - colorize({all: true}), - timestamp({ - format: 'YYYY-MM-DD hh:mm:ss.SSS A', - }), - align(), - printf( - (info: any) => - `[${info.timestamp}] ${info.level}: ${info.message} -${info.stack || ''}` - ) - ), - transports: [new winston.transports.Console()], -}); diff --git a/src/util/npm.ts b/src/util/npm.ts deleted file mode 100644 index de27ae4de..000000000 --- a/src/util/npm.ts +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-process-exit */ -import * as fs from 'fs/promises'; -import * as path from 'path'; - -import {execPromise} from './helpers'; -import { - isDirectoryExists, - getFileName, - isFileExists, - removeFileIfExists, -} from './fs'; -import {logger} from './logger'; - -import {STRINGS} from '../config'; -import {ManifestPlugin, PathWithVersion} from '../types/npm'; - -const packageJson = require('../../package.json'); - -const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES, IF_CHECK_VERIFIED} = - STRINGS; - -/** - * Checks if the package.json is exists, if not, initializes it. - */ -export const initPackageJsonIfNotExists = async (folderPath: string) => { - const packageJsonPath = path.resolve(folderPath, 'package.json'); - const isPackageJsonExists = await isFileExists(packageJsonPath); - - if (!isPackageJsonExists) { - logger.info(INITIALIZING_PACKAGE_JSON); - - const nodeModulesPath = path.resolve(folderPath, 'node_modules'); - const isNodeModulesExists = await isDirectoryExists(nodeModulesPath); - - if (isNodeModulesExists) { - await fs.rm(nodeModulesPath, {recursive: true}); - } - - await execPromise('npm init -y', {cwd: folderPath}); - } - - return packageJsonPath; -}; - -/** - * Installs packages from the specified dependencies in the specified folder. - */ -export const installDependencies = async ( - folderPath: string, - dependencies: {[path: string]: string} -) => { - const packages = Object.entries(dependencies).map( - ([dependency, version]) => `${dependency}@${version.replace('^', '')}` - ); - - logger.info(INSTALLING_NPM_PACKAGES); - await execPromise(`npm install ${packages.join(' ')}`, { - cwd: folderPath, - }); -}; - -/** - * Updates package.json dependencies. - */ -export const updatePackageJsonDependencies = async ( - packageJsonPath: string, - dependencies: PathWithVersion, - cwd: boolean -) => { - const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); - - const parsedPackageJson = JSON.parse(packageJsonContent); - - if (cwd) { - parsedPackageJson.dependencies = { - ...parsedPackageJson.dependencies, - ...dependencies, - }; - } else { - parsedPackageJson.dependencies = {...dependencies}; - } - - await fs.writeFile( - packageJsonPath, - JSON.stringify(parsedPackageJson, null, 2) - ); -}; - -/** - * Gets depencecies with versions. - */ -export const extractPathsWithVersion = ( - plugins: ManifestPlugin, - dependencies: string[] -) => { - const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); - const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); - const pathsWithVersion: PathWithVersion = {}; - - uniquePaths.forEach(pluginPath => { - const dependency = dependencies.find((dependency: string) => - dependency.startsWith(pluginPath) - ); - - if (dependency) { - const splittedDependency = dependency.split('@'); - const version = - splittedDependency.length > 2 - ? splittedDependency[2].split(' ')[0] - : splittedDependency[1]; - - pathsWithVersion[pluginPath] = `^${version}`; - } - }); - - return pathsWithVersion; -}; - -/** - * Update the package.json properties. - */ -export const updatePackageJsonProperties = async ( - newPackageJsonPath: string, - appendDependencies: boolean -) => { - const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); - const parsedPackageJsonContent = JSON.parse(packageJsonContent); - - const properties = { - name: 'if-environment', - description: packageJson.description, - author: packageJson.author, - bugs: packageJson.bugs, - engines: packageJson.engines, - homepage: packageJson.homepage, - dependencies: appendDependencies - ? parsedPackageJsonContent.dependencies - : {}, - }; - - const newPackageJson = Object.assign( - {}, - parsedPackageJsonContent, - properties - ); - - await fs.writeFile( - newPackageJsonPath, - JSON.stringify(newPackageJson, null, 2) - ); -}; - -/** - * Executes a series of npm commands based on the provided manifest file. - */ -export const executeCommands = async (manifest: string, cwd: boolean) => { - // TODO: After release remove isGlobal and appropriate checks - const isGlobal = !!process.env.npm_config_global; - const manifestDirPath = path.dirname(manifest); - const manifestFileName = getFileName(manifest); - const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); - const prefixFlag = - process.env.CURRENT_DIR && process.env.CURRENT_DIR !== process.cwd() - ? `--prefix=${path.relative(process.env.CURRENT_DIR!, process.cwd())}` - : ''; - const ifEnv = `${ - isGlobal ? `if-env ${prefixFlag}` : `npm run if-env ${prefixFlag} --` - } -m ${manifest}`; - const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; - const ifRunCommand = `${ - isGlobal ? `if-run ${prefixFlag}` : `npm run if-run ${prefixFlag} --` - } -m ${manifest} -o ${executedManifest}`; - const ifDiffCommand = `${ - isGlobal ? `if-diff ${prefixFlag}` : `npm run if-diff ${prefixFlag} --` - } -s ${executedManifest}.yaml -t ${manifest}`; - const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; - - await execPromise( - `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, - { - cwd: process.env.CURRENT_DIR || process.cwd(), - } - ); - - if (!cwd) { - await removeFileIfExists(`${manifestDirPath}/package.json`); - } - - await removeFileIfExists(`${executedManifest}.yaml`); - - console.log(IF_CHECK_VERIFIED(path.basename(manifest))); -}; diff --git a/src/util/os-checker.ts b/src/util/os-checker.ts deleted file mode 100644 index c795ecc61..000000000 --- a/src/util/os-checker.ts +++ /dev/null @@ -1,112 +0,0 @@ -import {release, platform} from 'os'; - -import {execPromise} from './helpers'; - -/** - * Executes `lsb_release -a` command in terminal. - * - * ``` - * Distributor ID: Ubuntu - * Description: Ubuntu 22.04.4 LTS - * Release: 22.04 - * Codename: jammy - * ``` - * - * Parses os and os-version from the response. - */ -const getLinuxInfo = async () => { - const {stdout} = await execPromise('lsb_release -a'); - - const parseLinuxVersion = (lsbReleaseResponse: string) => { - const regex = - /Distributor ID: ([^\n]+)\nDescription: +([^ ]+) +([^ ]+) +(.+)\n/; - const match = lsbReleaseResponse.match(regex); - - return { - os: match ? match[1] : platform(), - 'os-version': match ? `${match[3]} ${match[4]}` : release(), - }; - }; - - return parseLinuxVersion(stdout); -}; - -/** - * Executes in CMD `systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"` command. - * - * ``` - * OS Name: Microsoft Windows 11 Enterprise - * OS Version: 10.0.22631 N/A Build 22631 - * ``` - * - * Parses os and os-version from the response. - */ -const getWindowsInfo = async () => { - const {stdout} = await execPromise( - 'systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"' - ); - - const parseWindowsInfo = (systemInfoResponse: string) => { - const regex = - /OS Name:\s+([^\n]+)\nOS Version:\s+([\d.]+)\s+(N\/A\s+Build\s+(\d+))/; - const match = systemInfoResponse.match(regex); - - return { - os: match ? match[1] : platform(), - 'os-version': match ? `${match[2]} ${match[3]}` : release(), - }; - }; - - return parseWindowsInfo(stdout); -}; - -/** - * Executes `sw_vers` command in terminal. - * - * ``` - * ProductName: macOS - * ProductVersion: 14.3.1 - * BuildVersion: 23D60 - * ``` - * - * Parses os and os version from the response. - */ -const getMacVersion = async () => { - const {stdout} = await execPromise('sw_vers'); - - const parseMacInfo = (swVersResponse: string) => { - const productNameRegex = /ProductName:\s*(.+)/; - const productVersionRegex = /ProductVersion:\s*(.+)/; - - const nameMatch = swVersResponse.match(productNameRegex); - const versionMatch = swVersResponse.match(productVersionRegex); - - return { - os: nameMatch ? nameMatch[1].trim() : platform(), - 'os-version': versionMatch ? versionMatch[1].trim() : release(), - }; - }; - - return parseMacInfo(stdout); -}; - -/** - * Finds operating system information like name and version. - */ -export const osInfo = async () => { - const osKind = platform(); - - switch (osKind) { - case 'darwin': - return getMacVersion(); - case 'linux': - return getLinuxInfo(); - case 'win32': - return getWindowsInfo(); - default: - return { - os: osKind, - 'os-version': release(), - }; - } -}; diff --git a/src/util/plugin-storage.ts b/src/util/plugin-storage.ts deleted file mode 100644 index 1f9711943..000000000 --- a/src/util/plugin-storage.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {STRINGS} from '../config'; - -import {PluginInterface} from '../types/interface'; -import {PluginStorage} from '../types/plugin-storage'; - -const {PluginInitializationError} = ERRORS; -const {NOT_INITALIZED_PLUGIN} = STRINGS; - -/** - * Storage for maintaining plugins. - */ -export const pluginStorage = () => { - const storage: PluginStorage = {}; - - return { - /** - * Gets plugin by given `name`. If it's missing then throws error. - */ - get: (name: string) => { - const plugin = storage[name]; - - if (!plugin) { - throw new PluginInitializationError(NOT_INITALIZED_PLUGIN(name)); - } - - return plugin; - }, - /** - * Saves given `plugin` with given `name`. - */ - set: function (name: string, plugin: PluginInterface) { - storage[name] = plugin; - - return this; - }, - }; -}; diff --git a/src/util/validations.ts b/src/util/validations.ts deleted file mode 100644 index 920e7cbdb..000000000 --- a/src/util/validations.ts +++ /dev/null @@ -1,153 +0,0 @@ -import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {STRINGS} from '../config/strings'; - -import {AGGREGATION_METHODS} from '../types/aggregation'; -import {AGGREGATION_TYPES} from '../types/parameters'; - -const {ManifestValidationError, InputValidationError} = ERRORS; -const {VALIDATING_MANIFEST} = STRINGS; - -/** - * At least one property defined handler. - */ -export const atLeastOneDefined = ( - obj: Record -) => Object.values(obj).some(v => v !== undefined); - -/** - * All properties are defined handler. - */ -export const allDefined = (obj: Record) => - Object.values(obj).every(v => v !== undefined); - -/** - * Validation schema for manifests. - */ -export const manifestSchema = z.object({ - name: z.string(), - description: z.string().optional().nullable(), - tags: z - .object({ - kind: z.string().optional().nullable(), - complexity: z.string().optional().nullable(), - category: z.string().optional().nullable(), - }) - .optional() - .nullable(), - aggregation: z - .object({ - metrics: z.array(z.string()), - type: z.enum(AGGREGATION_METHODS), - }) - .optional() - .nullable(), - params: z - .array( - z.object({ - name: z.string(), - description: z.string(), - aggregation: z.enum(AGGREGATION_TYPES), - unit: z.string(), - }) - ) - .optional() - .nullable(), - initialize: z.object({ - plugins: z.record( - z.string(), - z.object({ - path: z.string(), - method: z.string(), - 'global-config': z.record(z.string(), z.any()).optional(), - }) - ), - outputs: z.array(z.string()).optional(), - }), - execution: z - .object({ - command: z.string().optional(), - environment: z - .object({ - 'if-version': z.string(), - os: z.string(), - 'os-version': z.string(), - 'node-version': z.string(), - 'date-time': z.string(), - dependencies: z.array(z.string()), - }) - .optional(), - status: z.string(), - error: z.string().optional(), - }) - .optional(), - tree: z.record(z.string(), z.any()), -}); - -/** - * Validates given `manifest` object to match pattern. - */ -export const validateManifest = (manifest: any) => { - console.debug(VALIDATING_MANIFEST); - - return validate(manifestSchema, manifest, undefined, ManifestValidationError); -}; - -/** - * Validates given `object` with given `schema`. - */ -export const validate = ( - schema: ZodSchema, - object: any, - index?: number, - errorConstructor: ErrorConstructor = InputValidationError -) => { - const validationResult = schema.safeParse(object); - - if (!validationResult.success) { - throw new errorConstructor( - prettifyErrorMessage(validationResult.error.message, index) - ); - } - - return validationResult.data; -}; - -/** - * Error message formatter for zod issues. - */ -const prettifyErrorMessage = (issues: string, index?: number) => { - const issuesArray = JSON.parse(issues); - - return issuesArray.map((issue: ZodIssue) => { - const code = issue.code; - let {path, message} = issue; - - const indexErrorMessage = index !== undefined ? ` at index ${index}` : ''; - - if (issue.code === ZodIssueCode.invalid_union) { - message = issue.unionErrors[0].issues[0].message; - path = issue.unionErrors[0].issues[0].path; - } - - const fullPath = flattenPath(path); - - if (!fullPath) { - return message; - } - - return `"${fullPath}" parameter is ${message.toLowerCase()}${indexErrorMessage}. Error code: ${code}.`; - }); -}; - -/** - * Flattens an array representing a nested path into a string. - */ -const flattenPath = (path: (string | number)[]): string => { - const flattenPath = path.map(part => - typeof part === 'number' ? `[${part}]` : part - ); - - return flattenPath.join('.'); -}; diff --git a/src/util/yaml.ts b/src/util/yaml.ts deleted file mode 100644 index beaedd71f..000000000 --- a/src/util/yaml.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as fs from 'fs/promises'; -import * as path from 'path'; - -import * as YAML from 'js-yaml'; - -/** - * Reads and parses `yaml` file to object. - */ -export const openYamlFileAsObject = async (filePath: string): Promise => { - const yamlFileBuffer = await fs.readFile(filePath, 'utf8'); - - return YAML.load(yamlFileBuffer) as T; -}; - -/** - * Saves given `yaml` dump as a file. - */ -export const saveYamlFileAs = async (object: any, pathToFile: string) => { - const dirPath = path.dirname(pathToFile); - await fs.mkdir(dirPath, {recursive: true}); - const yamlString = YAML.dump(object, {noRefs: true}); - - return fs.writeFile(pathToFile, yamlString); -}; - -/** - * Checks if given `fileName` is yaml. - */ -export const checkIfFileIsYaml = (fileName: string) => { - const yamlFileTypes = ['yaml', 'yml']; - const splittedParts = fileName.split('.'); - const lastIndex = splittedParts.length - 1; - const extension = splittedParts[lastIndex]; - - return yamlFileTypes.includes(extension); -}; From ec610d2f81b24e6a3161c44ca9922eddc856aead Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:14:03 +0400 Subject: [PATCH 299/863] feat(src): init if-run utils --- src/if-run/util/aggregation-helper.ts | 68 ++++++++++++++++ src/if-run/util/args.ts | 73 +++++++++++++++++ src/if-run/util/helpers.ts | 41 ++++++++++ src/if-run/util/json.ts | 10 +++ src/if-run/util/log-memoize.ts | 20 +++++ src/if-run/util/os-checker.ts | 112 ++++++++++++++++++++++++++ src/if-run/util/plugin-storage.ts | 39 +++++++++ 7 files changed, 363 insertions(+) create mode 100644 src/if-run/util/aggregation-helper.ts create mode 100644 src/if-run/util/args.ts create mode 100644 src/if-run/util/helpers.ts create mode 100644 src/if-run/util/json.ts create mode 100644 src/if-run/util/log-memoize.ts create mode 100644 src/if-run/util/os-checker.ts create mode 100644 src/if-run/util/plugin-storage.ts diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts new file mode 100644 index 000000000..408a4e9f7 --- /dev/null +++ b/src/if-run/util/aggregation-helper.ts @@ -0,0 +1,68 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {parameterize} from '../lib/parameterize'; + +import {CONFIG, STRINGS} from '../config'; + +import {AggregationResult} from '../types/aggregation'; + +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; +const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; +const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; + +/** + * Validates metrics array before applying aggregator. + * If aggregation method is `none`, then throws error. + */ +const checkIfMetricsAreValid = (metrics: string[]) => { + metrics.forEach(metric => { + const method = parameterize.getAggregationMethod(metric); + + if (method === 'none') { + throw new InvalidAggregationMethodError( + INVALID_AGGREGATION_METHOD(metric) + ); + } + }); +}; + +/** + * Aggregates child node level metrics. Validates if metric aggregation type is `none`, then rejects with error. + * Appends aggregation additional params to metrics. Otherwise iterates over inputs by aggregating per given `metrics`. + */ +export const aggregateInputsIntoOne = ( + inputs: PluginParams[], + metrics: string[], + isTemporal?: boolean +) => { + checkIfMetricsAreValid(metrics); + const extendedMetrics = [...metrics, ...AGGREGATION_ADDITIONAL_PARAMS]; + + return inputs.reduce((acc, input, index) => { + for (const metric of extendedMetrics) { + if (!(metric in input)) { + throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); + } + + /** Checks if metric is timestamp or duration, then adds to aggregated value. */ + if (AGGREGATION_ADDITIONAL_PARAMS.includes(metric)) { + if (isTemporal) { + acc[metric] = input[metric]; + } + } else { + acc[metric] = acc[metric] ?? 0; + acc[metric] += parseFloat(input[metric]); + + /** Checks for the last iteration. */ + if (index === inputs.length - 1) { + if (parameterize.getAggregationMethod(metric) === 'avg') { + acc[metric] /= inputs.length; + } + } + } + } + + return acc; + }, {} as AggregationResult); +}; diff --git a/src/if-run/util/args.ts b/src/if-run/util/args.ts new file mode 100644 index 000000000..78f125bb1 --- /dev/null +++ b/src/if-run/util/args.ts @@ -0,0 +1,73 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {checkIfFileIsYaml} from '../../common/util/yaml'; +import {prependFullFilePath} from '../../common/util/helpers'; + +import {logger} from '../../common/util/logger'; + +import {CONFIG, STRINGS} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IfRunArgs, ProcessArgsOutputs} from '../types/process-args'; + +const {ParseCliParamsError, CliSourceFileError} = ERRORS; + +const {IF_RUN} = CONFIG; +const {NO_OUTPUT} = STRINGS; +const {SOURCE_IS_NOT_YAML, MANIFEST_IS_MISSING} = COMMON_STRINGS; + +/** + * Validates `ie` process arguments. + */ +const validateAndParseProcessArgs = () => { + try { + return parse(IF_RUN.ARGS, IF_RUN.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * 1. Parses process arguments like `manifest`, `output`, `override-params`, `help` and `debug`. + * 2. Checks if `help` param is provided, then logs help message and exits. + * 3. If output params are missing, warns user about it. + * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. + * If it is, then returns object containing full path. + * 4. If params are missing or invalid, then rejects with `ParseCliParamsError`. + */ +export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { + const { + manifest, + output, + 'override-params': overrideParams, + stdout, + debug, + } = validateAndParseProcessArgs(); + + if (!output && !stdout) { + logger.warn(NO_OUTPUT); + } + + if (manifest) { + if (checkIfFileIsYaml(manifest)) { + return { + inputPath: prependFullFilePath(manifest), + outputOptions: { + ...(output && {outputPath: prependFullFilePath(output)}), + ...(stdout && {stdout}), + }, + ...(overrideParams && {paramPath: overrideParams}), + debug, + }; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + throw new CliSourceFileError(MANIFEST_IS_MISSING); +}; diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts new file mode 100644 index 000000000..978ef128f --- /dev/null +++ b/src/if-run/util/helpers.ts @@ -0,0 +1,41 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../config'; + +import {logger} from '../../common/util/logger'; + +const {UNSUPPORTED_ERROR} = STRINGS; + +/** + * Impact engine error handler. Logs errors and appends issue template if error is unknown. + */ +export const andHandle = (error: Error) => { + const knownErrors = Object.keys(ERRORS); + + logger.error(error); + + if (!knownErrors.includes(error.name)) { + logger.error(UNSUPPORTED_ERROR(error.name)); + // eslint-disable-next-line no-process-exit + process.exit(2); + } +}; + +/** + * Append entries from defaults which are missing from inputs. + */ +export const mergeObjects = (defaults: any, input: any) => { + const merged: Record = structuredClone(input); + + for (const key in defaults) { + if (!(key in input)) { + merged[key] = defaults[key]; + } + + if (merged[key] === undefined || merged[key] === null) { + merged[key] = defaults[key]; + } + } + + return merged; +}; diff --git a/src/if-run/util/json.ts b/src/if-run/util/json.ts new file mode 100644 index 000000000..c9180a788 --- /dev/null +++ b/src/if-run/util/json.ts @@ -0,0 +1,10 @@ +import * as fs from 'fs/promises'; + +/** + * Reads and parses json file. + */ +export const readAndParseJson = async (paramPath: string): Promise => { + const file = await fs.readFile(paramPath, 'utf-8'); + + return JSON.parse(file) as T; +}; diff --git a/src/if-run/util/log-memoize.ts b/src/if-run/util/log-memoize.ts new file mode 100644 index 000000000..f0afa4d9e --- /dev/null +++ b/src/if-run/util/log-memoize.ts @@ -0,0 +1,20 @@ +import {LeveledLogMethod} from 'winston'; + +/** + * Keeps in memory logged messages. If called with redundant message, skips logging. + */ +const memoizedLogger = () => { + const memory: string[] = []; + + return (logger: LeveledLogMethod | typeof console.debug, message: string) => { + if (memory.includes(message)) { + return; + } + + memory.push(message); + logger(message); + }; +}; + +/** Singleton pattern. */ +export const memoizedLog = memoizedLogger(); diff --git a/src/if-run/util/os-checker.ts b/src/if-run/util/os-checker.ts new file mode 100644 index 000000000..1614d5a4b --- /dev/null +++ b/src/if-run/util/os-checker.ts @@ -0,0 +1,112 @@ +import {release, platform} from 'os'; + +import {execPromise} from '../../common/util/helpers'; + +/** + * Executes `lsb_release -a` command in terminal. + * + * ``` + * Distributor ID: Ubuntu + * Description: Ubuntu 22.04.4 LTS + * Release: 22.04 + * Codename: jammy + * ``` + * + * Parses os and os-version from the response. + */ +const getLinuxInfo = async () => { + const {stdout} = await execPromise('lsb_release -a'); + + const parseLinuxVersion = (lsbReleaseResponse: string) => { + const regex = + /Distributor ID: ([^\n]+)\nDescription: +([^ ]+) +([^ ]+) +(.+)\n/; + const match = lsbReleaseResponse.match(regex); + + return { + os: match ? match[1] : platform(), + 'os-version': match ? `${match[3]} ${match[4]}` : release(), + }; + }; + + return parseLinuxVersion(stdout); +}; + +/** + * Executes in CMD `systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"` command. + * + * ``` + * OS Name: Microsoft Windows 11 Enterprise + * OS Version: 10.0.22631 N/A Build 22631 + * ``` + * + * Parses os and os-version from the response. + */ +const getWindowsInfo = async () => { + const {stdout} = await execPromise( + 'systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"' + ); + + const parseWindowsInfo = (systemInfoResponse: string) => { + const regex = + /OS Name:\s+([^\n]+)\nOS Version:\s+([\d.]+)\s+(N\/A\s+Build\s+(\d+))/; + const match = systemInfoResponse.match(regex); + + return { + os: match ? match[1] : platform(), + 'os-version': match ? `${match[2]} ${match[3]}` : release(), + }; + }; + + return parseWindowsInfo(stdout); +}; + +/** + * Executes `sw_vers` command in terminal. + * + * ``` + * ProductName: macOS + * ProductVersion: 14.3.1 + * BuildVersion: 23D60 + * ``` + * + * Parses os and os version from the response. + */ +const getMacVersion = async () => { + const {stdout} = await execPromise('sw_vers'); + + const parseMacInfo = (swVersResponse: string) => { + const productNameRegex = /ProductName:\s*(.+)/; + const productVersionRegex = /ProductVersion:\s*(.+)/; + + const nameMatch = swVersResponse.match(productNameRegex); + const versionMatch = swVersResponse.match(productVersionRegex); + + return { + os: nameMatch ? nameMatch[1].trim() : platform(), + 'os-version': versionMatch ? versionMatch[1].trim() : release(), + }; + }; + + return parseMacInfo(stdout); +}; + +/** + * Finds operating system information like name and version. + */ +export const osInfo = async () => { + const osKind = platform(); + + switch (osKind) { + case 'darwin': + return getMacVersion(); + case 'linux': + return getLinuxInfo(); + case 'win32': + return getWindowsInfo(); + default: + return { + os: osKind, + 'os-version': release(), + }; + } +}; diff --git a/src/if-run/util/plugin-storage.ts b/src/if-run/util/plugin-storage.ts new file mode 100644 index 000000000..ca2907fcc --- /dev/null +++ b/src/if-run/util/plugin-storage.ts @@ -0,0 +1,39 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../config'; + +import {PluginStorage} from '../types/plugin-storage'; +import {PluginInterface} from '../types/interface'; + +const {PluginInitializationError} = ERRORS; +const {NOT_INITALIZED_PLUGIN} = STRINGS; + +/** + * Storage for maintaining plugins. + */ +export const pluginStorage = () => { + const storage: PluginStorage = {}; + + return { + /** + * Gets plugin by given `name`. If it's missing then throws error. + */ + get: (name: string) => { + const plugin = storage[name]; + + if (!plugin) { + throw new PluginInitializationError(NOT_INITALIZED_PLUGIN(name)); + } + + return plugin; + }, + /** + * Saves given `plugin` with given `name`. + */ + set: function (name: string, plugin: PluginInterface) { + storage[name] = plugin; + + return this; + }, + }; +}; From 4e8444d0c677336d746ed6d47dce77194a4a8e85 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:14:34 +0400 Subject: [PATCH 300/863] feat(src): init if-run types --- src/if-run/types/aggregation.ts | 3 ++ src/if-run/types/compute.ts | 30 ++++++++++++++++++++ src/if-run/types/environment.ts | 19 +++++++++++++ src/if-run/types/exhaust-plugin-interface.ts | 8 ++++++ src/if-run/types/interface.ts | 9 ++++++ src/if-run/types/parameters.ts | 7 +++++ src/if-run/types/plugin-storage.ts | 8 ++++++ src/if-run/types/process-args.ts | 22 ++++++++++++++ src/if-run/types/time-sync.ts | 20 +++++++++++++ 9 files changed, 126 insertions(+) create mode 100644 src/if-run/types/aggregation.ts create mode 100644 src/if-run/types/compute.ts create mode 100644 src/if-run/types/environment.ts create mode 100644 src/if-run/types/exhaust-plugin-interface.ts create mode 100644 src/if-run/types/interface.ts create mode 100644 src/if-run/types/parameters.ts create mode 100644 src/if-run/types/plugin-storage.ts create mode 100644 src/if-run/types/process-args.ts create mode 100644 src/if-run/types/time-sync.ts diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts new file mode 100644 index 000000000..d15322d29 --- /dev/null +++ b/src/if-run/types/aggregation.ts @@ -0,0 +1,3 @@ +export type AggregationResult = Record; + +export const AGGREGATION_METHODS = ['horizontal', 'vertical', 'both'] as const; diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts new file mode 100644 index 000000000..bfe294241 --- /dev/null +++ b/src/if-run/types/compute.ts @@ -0,0 +1,30 @@ +import {PluginParams} from '@grnsft/if-core/types'; + +import {PluginStorageInterface} from './plugin-storage'; +import {Context} from '../../common/types/manifest'; + +export type NodeConfig = { + [key: string]: Record; +}; + +export type Params = { + pluginStorage: PluginStorageInterface; + context: Context; + pipeline?: string[]; + config?: NodeConfig; + defaults?: PluginParams; +}; + +export type Node = { + children?: any; + pipeline?: string[]; + config?: NodeConfig; + defaults?: PluginParams; + inputs?: PluginParams[]; + outputs?: PluginParams[]; +}; + +export type ComputeParams = { + context: Context; + pluginStorage: PluginStorageInterface; +}; diff --git a/src/if-run/types/environment.ts b/src/if-run/types/environment.ts new file mode 100644 index 000000000..94c3e6a82 --- /dev/null +++ b/src/if-run/types/environment.ts @@ -0,0 +1,19 @@ +export type PackageDependency = { + version: string; + resolved?: string; + overridden: boolean; + extraneous?: boolean; +}; + +type PackageProblem = { + extraneous: string; +}; + +export type NpmListResponse = { + version: string; + name: string; + problems?: PackageProblem[]; + dependencies: { + [key: string]: PackageDependency; + }; +}; diff --git a/src/if-run/types/exhaust-plugin-interface.ts b/src/if-run/types/exhaust-plugin-interface.ts new file mode 100644 index 000000000..de6183842 --- /dev/null +++ b/src/if-run/types/exhaust-plugin-interface.ts @@ -0,0 +1,8 @@ +import {Context} from '../../common/types/manifest'; + +export interface ExhaustPluginInterface { + /** + * Execute exhaust based on `context` and `tree`, produce output to a file in `outputPath`. + */ + execute(tree: any, context: Context, outputPath?: string): void; +} diff --git a/src/if-run/types/interface.ts b/src/if-run/types/interface.ts new file mode 100644 index 000000000..6834a3ebb --- /dev/null +++ b/src/if-run/types/interface.ts @@ -0,0 +1,9 @@ +import {ExecutePlugin, GroupByPlugin} from '@grnsft/if-core/types'; + +export type PluginInterface = ExecutePlugin | GroupByPlugin; + +export const isExecute = (plugin: PluginInterface): plugin is ExecutePlugin => + (plugin as ExecutePlugin).metadata.kind === 'execute'; + +export const isGroupBy = (plugin: PluginInterface): plugin is GroupByPlugin => + (plugin as GroupByPlugin).metadata.kind === 'groupby'; diff --git a/src/if-run/types/parameters.ts b/src/if-run/types/parameters.ts new file mode 100644 index 000000000..939ac2ba6 --- /dev/null +++ b/src/if-run/types/parameters.ts @@ -0,0 +1,7 @@ +import {ManifestParameter} from '../../common/types/manifest'; + +export const AGGREGATION_TYPES = ['sum', 'none', 'avg'] as const; + +type ParameterProps = Omit; + +export type Parameters = Record; diff --git a/src/if-run/types/plugin-storage.ts b/src/if-run/types/plugin-storage.ts new file mode 100644 index 000000000..0d3d865c5 --- /dev/null +++ b/src/if-run/types/plugin-storage.ts @@ -0,0 +1,8 @@ +import {pluginStorage} from '../util/plugin-storage'; +import {PluginInterface} from './interface'; + +export type PluginStorage = { + [key: string]: PluginInterface; +}; + +export type PluginStorageInterface = ReturnType; diff --git a/src/if-run/types/process-args.ts b/src/if-run/types/process-args.ts new file mode 100644 index 000000000..8f7903112 --- /dev/null +++ b/src/if-run/types/process-args.ts @@ -0,0 +1,22 @@ +export interface IfRunArgs { + manifest?: string; + output?: string; + 'override-params'?: string; + stdout?: boolean; + debug?: boolean; +} + +export interface ProcessArgsOutputs { + inputPath: string; + outputOptions: { + outputPath?: string; + stdout?: boolean; + }; + paramPath?: string; + debug?: boolean; +} + +export interface Options { + outputPath?: string; + stdout?: boolean; +} diff --git a/src/if-run/types/time-sync.ts b/src/if-run/types/time-sync.ts new file mode 100644 index 000000000..505a91f82 --- /dev/null +++ b/src/if-run/types/time-sync.ts @@ -0,0 +1,20 @@ +import {DateTime} from 'luxon'; + +export type TimeNormalizerConfig = { + 'start-time': Date | string; + 'end-time': Date | string; + interval: number; + 'allow-padding': boolean; +}; + +export type PaddingReceipt = { + start: boolean; + end: boolean; +}; + +export type TimeParams = { + startTime: DateTime; + endTime: DateTime; + interval: number; + allowPadding: boolean; +}; From f77d293d1a7f9d3303a12be2b24fead612d1c293 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:14:46 +0400 Subject: [PATCH 301/863] feat(src): init if-run lib --- src/if-run/lib/aggregate.ts | 93 ++++++++++++++++++++++++++ src/if-run/lib/compute.ts | 117 +++++++++++++++++++++++++++++++++ src/if-run/lib/environment.ts | 96 +++++++++++++++++++++++++++ src/if-run/lib/exhaust.ts | 68 +++++++++++++++++++ src/if-run/lib/initialize.ts | 115 ++++++++++++++++++++++++++++++++ src/if-run/lib/parameterize.ts | 79 ++++++++++++++++++++++ 6 files changed, 568 insertions(+) create mode 100644 src/if-run/lib/aggregate.ts create mode 100644 src/if-run/lib/compute.ts create mode 100644 src/if-run/lib/environment.ts create mode 100644 src/if-run/lib/exhaust.ts create mode 100644 src/if-run/lib/initialize.ts create mode 100644 src/if-run/lib/parameterize.ts diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts new file mode 100644 index 000000000..4c16a0d0d --- /dev/null +++ b/src/if-run/lib/aggregate.ts @@ -0,0 +1,93 @@ +import {PluginParams} from '@grnsft/if-core/types'; + +import {aggregateInputsIntoOne} from '../util/aggregation-helper'; + +import {STRINGS} from '../config/strings'; +import { + AggregationParams, + AggregationParamsSure, +} from '../../common/types/manifest'; + +const {AGGREGATING_NODE, AGGREGATING_OUTPUTS} = STRINGS; + +/** + * Gets `i`th element from all children outputs and collects them in single array. + */ +const getIthElementsFromChildren = (children: any, i: number) => { + const values = Object.values(children); + + return values.map((value: any) => { + const output = value.outputs; + + return output[i]; + }); +}; + +/** + * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). + * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. + */ +const temporalAggregation = (node: any, metrics: string[]) => { + const outputs: PluginParams[] = []; + const values: any = Object.values(node.children); + + for (let i = 0; i < values[0].outputs.length; i++) { + const ithSliceOfOutputs = getIthElementsFromChildren(node.children, i); + outputs.push(aggregateInputsIntoOne(ithSliceOfOutputs, metrics, true)); + } + + return outputs; +}; + +/** + * Navigates the tree depth first, bottom up, + * left to right aggregating the component nodes and then the grouping nodes will be aggregated + * only when all their child nodes have been aggregated. + * 1. Aggregates all the children. + * 2. At this point you can be positive all your children have been aggregated and so you can now work on aggregating yourself. + * 3. It's component node, аggregates just the outputs of THIS component node (horizontal/component aggregation). + * 4. Else it's grouping node, first does temporal aggregation. This assumes everything is on the same time-grid. + * The outputs of the grouping node are the aggregated time bucketed outputs of it's children. + * 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them. + */ +const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { + const metrics = aggregationParams!.metrics; + const type = aggregationParams!.type; + + if (node.children) { + for (const child in node.children) { + console.debug(AGGREGATING_NODE(child)); + + aggregateNode(node.children[child], aggregationParams); + } + } + + if (!node.children) { + if (type === 'horizontal' || type === 'both') { + node.aggregated = aggregateInputsIntoOne(node.outputs, metrics); + } + } else { + if (type === 'vertical' || type === 'both') { + const outputs = temporalAggregation(node, metrics); + node.outputs = outputs; + node.aggregated = aggregateInputsIntoOne(outputs, metrics); + } + } +}; + +/** + * If aggregation is disabled, then returns given `tree`. + * Otherwise creates copy of the tree, then applies aggregation to it. + */ +export const aggregate = (tree: any, aggregationParams: AggregationParams) => { + console.debug(AGGREGATING_OUTPUTS); + + if (!aggregationParams || !aggregationParams.type) { + return tree; + } + + const copyOfTree = structuredClone(tree); + aggregateNode(copyOfTree, aggregationParams); + + return copyOfTree; +}; diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts new file mode 100644 index 000000000..dde49d3f7 --- /dev/null +++ b/src/if-run/lib/compute.ts @@ -0,0 +1,117 @@ +import {PluginParams, GroupByConfig} from '@grnsft/if-core/types'; + +import {mergeObjects} from '../util/helpers'; +import {debugLogger} from '../../common/util/debug-logger'; + +import {STRINGS} from '../config/strings'; + +import {isExecute, isGroupBy} from '../types/interface'; +import {ComputeParams, Node, Params} from '../types/compute'; + +const {MERGING_DEFAULTS_WITH_INPUT_DATA, COMPUTING_PIPELINE_FOR_NODE} = STRINGS; + +/** + * Traverses all child nodes based on children grouping. + */ +const traverse = async (children: any, params: Params) => { + for (const child in children) { + await computeNode(children[child], params); + } +}; + +/** + * Appends `default` values to `inputs`. + */ +const mergeDefaults = ( + inputs: PluginParams[], + defaults: PluginParams | undefined +) => { + if (inputs) { + const response = defaults + ? inputs.map(input => mergeObjects(defaults, input)) + : inputs; + + return response; + } + + console.debug(MERGING_DEFAULTS_WITH_INPUT_DATA); + + return defaults ? [defaults] : []; +}; + +/** + * 1. If the node has it's own pipeline, defaults or config then use that, + * otherwise use whatever has been passed down from further up the tree. + * 2. If it's a grouping node, then first of all computes all it's children. + * This is doing a depth first traversal. + * 3. Otherwise merges the defaults into the inputs. + * 4. Goes through the pipeline plugins, by checking if it's `execute` plugin. If so sets outputs. + * If is a `groupby` plugin, it will return child components rather than outputs. + * 5. Since after `groupby`, there are new child components, then computes them. + * Note: `pipeline` now equals the remaining plu.gins to apply to each child + */ +const computeNode = async (node: Node, params: Params): Promise => { + const pipeline = (node.pipeline || params.pipeline) as string[]; + const config = node.config || params.config; + const defaults = node.defaults || params.defaults; + + if (node.children) { + return traverse(node.children, { + ...params, + pipeline, + defaults, + config, + }); + } + + let inputStorage = structuredClone(node.inputs) as PluginParams[]; + inputStorage = mergeDefaults(inputStorage, defaults); + const pipelineCopy = structuredClone(pipeline); + + while (pipelineCopy.length !== 0) { + const pluginName = pipelineCopy.shift() as string; + const plugin = params.pluginStorage.get(pluginName); + const nodeConfig = config && config[pluginName]; + + console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); + debugLogger.setExecutingPluginName(pluginName); + + if (isExecute(plugin)) { + inputStorage = await plugin.execute(inputStorage, nodeConfig); + debugLogger.setExecutingPluginName(); + + node.outputs = inputStorage; + } + + if (isGroupBy(plugin)) { + node.children = await plugin.execute( + inputStorage, + nodeConfig as GroupByConfig + ); + delete node.inputs; + delete node.outputs; + + await traverse(node.children, { + ...params, + pipeline: pipelineCopy, + defaults, + config, + }); + + debugLogger.setExecutingPluginName(); + + break; + } + } +}; + +/** + * Creates copy of existing tree, then applies computing strategy. + */ +export const compute = async (tree: any, params: ComputeParams) => { + const copyOfTree = structuredClone(tree); + + await computeNode(copyOfTree, params); + + return copyOfTree; +}; diff --git a/src/if-run/lib/environment.ts b/src/if-run/lib/environment.ts new file mode 100644 index 000000000..21808cc20 --- /dev/null +++ b/src/if-run/lib/environment.ts @@ -0,0 +1,96 @@ +import {DateTime} from 'luxon'; + +import {osInfo} from '../util/os-checker'; +import {execPromise} from '../../common/util/helpers'; +import {Manifest} from '../../common/types/manifest'; + +import {STRINGS} from '../config/strings'; +import {NpmListResponse, PackageDependency} from '../types/environment'; + +const packageJson = require('../../../package.json'); + +const {CAPTURING_RUNTIME_ENVIRONMENT_DATA} = STRINGS; + +/** + * 1. Gets the high-resolution real time when the application starts. + * 2. Converts the high-resolution time to milliseconds. + * 3. Gets the current DateTime. + * 4. Subtracts the milliseconds from the current DateTime. + */ +const getProcessStartingTimestamp = () => { + const startTime = process.hrtime(); + + const [seconds, nanoseconds] = process.hrtime(startTime); + const milliseconds = seconds * 1000 + nanoseconds / 1e6; + + const currentDateTime = DateTime.local(); + + const applicationStartDateTime = currentDateTime.minus({ + milliseconds: milliseconds, + }); + + return applicationStartDateTime.toUTC().toString(); +}; + +/** + * Goes through the dependencies, converts them into oneliner. + */ +const flattenDependencies = (dependencies: [string, PackageDependency][]) => + dependencies.map(dependency => { + const [packageName, versionInfo] = dependency; + const {version, extraneous, resolved} = versionInfo; + const ifExtraneous = extraneous ? ` extraneous -> ${resolved}` : ''; + const ifFromGithub = + resolved && resolved.startsWith('git') ? ` (${resolved})` : ''; + const formattedString = `${packageName}@${version}${ + ifExtraneous || ifFromGithub + }`; + + return formattedString; + }); + +/** + * 1. Runs `npm list --json`. + * 2. Parses json data and converts to list. + */ +const listDependencies = async () => { + const {stdout} = await execPromise('npm list --json'); + const npmListResponse: NpmListResponse = JSON.parse(stdout); + + if (npmListResponse.dependencies) { + const dependencies = Object.entries(npmListResponse.dependencies); + + return flattenDependencies(dependencies); + } + + return []; +}; + +/** + * Injects execution information (command, environment) to existing manifest. + */ +export const injectEnvironment = async ( + manifest: Manifest +): Promise => { + console.debug(CAPTURING_RUNTIME_ENVIRONMENT_DATA); + + const dependencies = await listDependencies(); + const info = await osInfo(); + const dateTime = `${getProcessStartingTimestamp()} (UTC)`; + + return { + ...manifest, + execution: { + status: 'success', + command: process.argv.join(' '), + environment: { + 'if-version': packageJson.version, + os: info.os, + 'os-version': info['os-version'], + 'node-version': process.versions.node, + 'date-time': dateTime, + dependencies, + }, + }, + }; +}; diff --git a/src/if-run/lib/exhaust.ts b/src/if-run/lib/exhaust.ts new file mode 100644 index 000000000..1ca6d9f1c --- /dev/null +++ b/src/if-run/lib/exhaust.ts @@ -0,0 +1,68 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +/** + * @todo This is temporary solution, will be refactored to support dynamic plugins. + */ +import {ExportCSV} from '../builtins/export-csv'; +import {ExportCSVRaw} from '../builtins/export-csv-raw'; +import {ExportLog} from '../builtins/export-log'; +import {ExportYaml} from '../builtins/export-yaml'; + +import {STRINGS} from '../config'; + +import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; +import {Options} from '../types/process-args'; +import {Context} from '../../common/types/manifest'; + +const {InvalidExhaustPluginError} = ERRORS; +const {INVALID_EXHAUST_PLUGIN, PREPARING_OUTPUT_DATA} = STRINGS; + +/** + * Initialize exhaust plugins based on the provided config + */ +const initializeExhaustPlugins = (plugins: string[]) => + plugins.map(initializeExhaustPlugin); + +/** + * Factory method for exhaust plugins. + */ +const initializeExhaustPlugin = (name: string): ExhaustPluginInterface => { + switch (name) { + case 'yaml': + return ExportYaml(); + case 'csv': + return ExportCSV(); + case 'csv-raw': + return ExportCSVRaw(); + default: + throw new InvalidExhaustPluginError(INVALID_EXHAUST_PLUGIN(name)); + } +}; + +/** + * Output manager - Exhaust. + * Grabs output plugins from context, executes every. + */ +export const exhaust = async ( + tree: any, + context: Context, + outputOptions: Options +) => { + console.debug(PREPARING_OUTPUT_DATA); + + const outputPlugins = context.initialize.outputs; + + if (outputOptions.stdout) { + ExportLog().execute(tree, context); + } + + if (!outputPlugins) { + return; + } + + const exhaustPlugins = initializeExhaustPlugins(outputPlugins); + + for await (const plugin of exhaustPlugins) { + await plugin.execute(tree, context, outputOptions.outputPath); + } +}; diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts new file mode 100644 index 000000000..5833787ba --- /dev/null +++ b/src/if-run/lib/initialize.ts @@ -0,0 +1,115 @@ +import * as path from 'node:path'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {logger} from '../../common/util/logger'; +import {memoizedLog} from '../util/log-memoize'; +import {pluginStorage} from '../util/plugin-storage'; + +import {CONFIG, STRINGS} from '../config'; + +import {PluginInterface} from '../types/interface'; +import {GlobalPlugins, PluginOptions} from '../../common/types/manifest'; +import {PluginStorageInterface} from '../types/plugin-storage'; + +const { + PluginInitializationError, + MissingPluginMethodError, + MissingPluginPathError, +} = ERRORS; + +const {GITHUB_PATH, NATIVE_PLUGIN} = CONFIG; +const { + MISSING_METHOD, + MISSING_PATH, + NOT_NATIVE_PLUGIN, + INVALID_MODULE_PATH, + LOADING_PLUGIN_FROM_PATH, + INITIALIZING_PLUGIN, + INITIALIZING_PLUGINS, +} = STRINGS; + +/** + * Imports module by given `path`. + */ +const importModuleFrom = async (path: string) => { + const module = await import(path).catch(error => { + throw new PluginInitializationError(INVALID_MODULE_PATH(path, error)); + }); + + return module; +}; + +/** + * Imports `module` from given `path`, then checks if it's `ModelPluginInterface` extension. + */ +const importAndVerifyModule = async (method: string, path: string) => { + const pluginModule = await importModuleFrom(path); + + return pluginModule[method]; +}; + +/** + * Checks if plugin is missing then rejects with error. + * Then checks if `path` is starting with github, then grabs the repository name. + * Imports module, then checks if it's a valid plugin. + */ +const handModule = (method: string, pluginPath: string) => { + console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath)); + + if (pluginPath === 'builtin') { + pluginPath = path.normalize(`${__dirname}/../builtins`); + } else { + if (pluginPath?.startsWith(GITHUB_PATH)) { + const parts = pluginPath.split('/'); + pluginPath = parts[parts.length - 1]; + } + + if (!pluginPath.includes(NATIVE_PLUGIN)) { + memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(pluginPath)); + } + } + + return importAndVerifyModule(method, pluginPath); +}; + +/** + * Initializes plugin with global config. + */ +const initPlugin = async ( + initPluginParams: PluginOptions +): Promise => { + const {method, path, 'global-config': globalConfig} = initPluginParams; + + console.debug(INITIALIZING_PLUGIN(method)); + + if (!method) { + throw new MissingPluginMethodError(MISSING_METHOD); + } + + if (!path) { + throw new MissingPluginPathError(MISSING_PATH); + } + + const plugin = await handModule(method, path); + + return plugin(globalConfig); +}; + +/** + * Registers all plugins from `manifest`.`initialize` property. + */ +export const initialize = async ( + plugins: GlobalPlugins +): Promise => { + console.debug(INITIALIZING_PLUGINS); + + const storage = pluginStorage(); + + for await (const pluginName of Object.keys(plugins)) { + const plugin = await initPlugin(plugins[pluginName]); + storage.set(pluginName, plugin); + } + + return storage; +}; diff --git a/src/if-run/lib/parameterize.ts b/src/if-run/lib/parameterize.ts new file mode 100644 index 000000000..1034e1ce2 --- /dev/null +++ b/src/if-run/lib/parameterize.ts @@ -0,0 +1,79 @@ +import {debugLogger} from '../../common/util/debug-logger'; +import {logger} from '../../common/util/logger'; +import {memoizedLog} from '../util/log-memoize'; + +import {STRINGS, PARAMETERS} from '../config'; + +import {Parameters} from '../types/parameters'; +import {ManifestParameter} from '../../common/types/manifest'; + +const { + REJECTING_OVERRIDE, + UNKNOWN_PARAM, + SYNCING_PARAMETERS, + CHECKING_AGGREGATION_METHOD, +} = STRINGS; + +/** + * Parameters manager. Provides get aggregation method and combine functionality. + */ +const Parameterize = () => { + let parametersStorage = PARAMETERS; + + /** + * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. + */ + const getAggregationMethod = (unitName: string) => { + debugLogger.setExecutingPluginName(); + memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); + + if (`${unitName}` in parametersStorage) { + return parametersStorage[unitName as keyof typeof PARAMETERS].aggregation; + } + + memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); + + return 'sum'; + }; + + /** + * Checks if additional parameters are provided in context. + * If so, then checks if they are coincident with default ones and exits with warning message. + * Otherwise appends context based parameters to defaults. + */ + const combine = ( + contextParameters: ManifestParameter[] | null | undefined, + parameters: Parameters + ) => { + console.debug(SYNCING_PARAMETERS); + + if (contextParameters) { + contextParameters.forEach(param => { + if (`${param.name}` in parameters) { + logger.warn(REJECTING_OVERRIDE(param)); + + return; + } + + const {description, unit, aggregation, name} = param; + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + parameters[name] = { + description, + unit, + aggregation, + }; + }); + } + + parametersStorage = parameters; + }; + + return { + combine, + getAggregationMethod, + }; +}; + +export const parameterize = Parameterize(); From 3131bb06c59046c2d6fc3b9cadbef6a7fe910b3f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:14:56 +0400 Subject: [PATCH 302/863] feat(src): init if-run config --- src/if-run/config/config.ts | 62 +++++++++++ src/if-run/config/index.ts | 3 + src/if-run/config/params.ts | 198 +++++++++++++++++++++++++++++++++++ src/if-run/config/strings.ts | 125 ++++++++++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 src/if-run/config/config.ts create mode 100644 src/if-run/config/index.ts create mode 100644 src/if-run/config/params.ts create mode 100644 src/if-run/config/strings.ts diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts new file mode 100644 index 000000000..d3b0b7dfe --- /dev/null +++ b/src/if-run/config/config.ts @@ -0,0 +1,62 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IfRunArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + IF_RUN: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the input file]', + }, + output: { + type: String, + optional: true, + alias: 'o', + description: '[path to the output file]', + }, + 'override-params': { + type: String, + optional: true, + alias: 'p', + description: '[path to a parameter file that overrides our defaults]', + }, + stdout: { + type: Boolean, + optional: true, + alias: 's', + description: '[prints out to the console]', + }, + help: { + type: Boolean, + optional: true, + alias: 'h', + description: '[prints out the above help instruction]', + }, + debug: { + type: Boolean, + optional: true, + alias: 'd', + description: '[prints out debug logs to the console]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + }, + GITHUB_PATH: 'https://github.com', + NATIVE_PLUGIN: 'if-plugins', + AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], +}; diff --git a/src/if-run/config/index.ts b/src/if-run/config/index.ts new file mode 100644 index 000000000..6aa6e0a98 --- /dev/null +++ b/src/if-run/config/index.ts @@ -0,0 +1,3 @@ +export {CONFIG} from './config'; +export {PARAMETERS} from './params'; +export {STRINGS} from './strings'; diff --git a/src/if-run/config/params.ts b/src/if-run/config/params.ts new file mode 100644 index 000000000..76732e57b --- /dev/null +++ b/src/if-run/config/params.ts @@ -0,0 +1,198 @@ +import {Parameters} from '../types/parameters'; + +export const PARAMETERS: Parameters = { + carbon: { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + aggregation: 'sum', + }, + 'cpu/number-cores': { + description: 'number of cores available', + unit: 'cores', + aggregation: 'none', + }, + 'cpu/utilization': { + description: 'refers to CPU utilization.', + unit: 'percentage', + aggregation: 'avg', + }, + 'disk-io': { + description: 'refers to GB of data written/read from disk', + unit: 'GB', + aggregation: 'sum', + }, + duration: { + description: 'refers to the duration of the input', + unit: 'seconds', + aggregation: 'sum', + }, + energy: { + description: 'amount of energy utilised by the component', + unit: 'kWh', + aggregation: 'sum', + }, + 'cpu/energy': { + description: 'Energy consumed by the CPU of the component', + unit: 'kWh', + aggregation: 'sum', + }, + 'device/expected-lifespan': { + description: 'Total Expected Lifespan of the Component in Seconds', + unit: 'seconds', + aggregation: 'sum', + }, + 'memory/energy': { + description: 'Energy consumed by the Memory of the component', + unit: 'kWh', + aggregation: 'sum', + }, + 'carbon-embodied': { + description: 'Embodied Emissions of the component', + unit: 'gCO2e', + aggregation: 'sum', + }, + 'network/energy': { + description: 'Energy consumed by the Network of the component', + unit: 'kWh', + aggregation: 'sum', + }, + 'functional-unit': { + description: + 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', + unit: 'none', + aggregation: 'sum', + }, + 'gpu-util': { + description: 'refers to CPU utilization.', + unit: 'percentage', + aggregation: 'avg', + }, + 'grid/carbon-intensity': { + description: 'Carbon intensity for the grid', + unit: 'gCO2eq/kWh', + aggregation: 'avg', + }, + 'cloud/instance-type': { + description: 'Type of Cloud Instance name used in the cloud provider APIs', + unit: 'None', + aggregation: 'none', + }, + geolocation: { + description: + 'Geographic location of provider as string (for watt-time model it is provided as latitude and longitude, comma separated, in decimal degrees)', + unit: 'None (decimal degrees for watt-time model)', + aggregation: 'none', + }, + 'carbon-operational': { + description: 'Operational Emissions of the component', + unit: 'gCO2e', + aggregation: 'sum', + }, + 'cpu/name': { + description: 'Name of the physical processor', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region': { + description: 'region cloud instance runs in', + unit: 'None', + aggregation: 'none', + }, + 'cloud/vendor': { + description: + 'Name of the cloud service provider in the ccf model. Can be aws, gcp or azure', + unit: 'None', + aggregation: 'none', + }, + name: { + description: 'arbitrary name parameter.', + unit: 'None', + aggregation: 'none', + }, + 'ram-alloc': { + description: 'refers to GB of memory allocated.', + unit: 'GB', + aggregation: 'avg', + }, + 'ram-util': { + description: 'refers to percentage of memory utilized.', + unit: 'percentage', + aggregation: 'avg', + }, + 'resources-reserved': { + description: 'resources reserved for an application', + unit: 'count', + aggregation: 'none', + }, + 'cpu/thermal-design-power': { + description: 'thermal design power for a processor', + unit: 'kwh', + aggregation: 'avg', + }, + 'device/emissions-embodied': { + description: 'total embodied emissions of some component', + unit: 'gCO2e', + aggregation: 'sum', + }, + timestamp: { + description: 'refers to the time of occurrence of the input', + unit: 'RFC3339', + aggregation: 'none', + }, + 'time-reserved': { + description: 'time reserved for a component', + unit: 'seconds', + aggregation: 'avg', + }, + 'resources-total': { + description: 'total resources available', + unit: 'count', + aggregation: 'none', + }, + 'vcpus-allocated': { + description: 'number of vcpus allocated to particular resource', + unit: 'count', + aggregation: 'none', + }, + 'vcpus-total': { + description: 'total number of vcpus available on a particular resource', + unit: 'count', + aggregation: 'none', + }, + 'memory-available': { + description: 'total amount of memory available on a particular resource', + unit: 'GB', + aggregation: 'none', + }, + 'physical-processor': { + description: + 'name of the physical processor being used in a specific instance type', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region-cfe': { + description: 'cloud region name in cfe format', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region-em-zone-id': { + description: 'cloud region name in electricity maps format', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region-wt-id': { + description: 'cloud region name in watt-time format', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region-location': { + description: 'cloud region name in our IF format', + unit: 'None', + aggregation: 'none', + }, + 'cloud/region-geolocation': { + description: 'location expressed as decimal coordinates (lat/lon)', + unit: 'decimal degrees', + aggregation: 'none', + }, +}; diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts new file mode 100644 index 000000000..186b6fb80 --- /dev/null +++ b/src/if-run/config/strings.ts @@ -0,0 +1,125 @@ +import {ManifestParameter} from '../../common/types/manifest'; + +export const STRINGS = { + MISSING_METHOD: "Initalization param 'method' is missing.", + MISSING_PATH: "Initalization param 'path' is missing.", + UNSUPPORTED_PLUGIN: + "Plugin interface doesn't implement 'execute' or 'metadata' methods.", + OVERRIDE_WARNING: + '\n**WARNING**: You are overriding the IF default parameters file. Please be extremely careful of unintended side-effects in your plugin pipeline!\n', + NOT_NATIVE_PLUGIN: (path: string) => + ` + You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, + INVALID_MODULE_PATH: (path: string, error?: any) => + `Provided module \`${path}\` is invalid or not found. ${error ?? ''} +`, + INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', + UNEXPECTED_TIME_CONFIG: + 'Unexpected node-level config provided for time-sync plugin.', + INVALID_TIME_INTERVAL: 'Interval is missing.', + AVOIDING_PADDING: (description: string) => + `Avoiding padding at ${description}`, + AVOIDING_PADDING_BY_EDGES: (start: boolean, end: boolean) => + `Avoiding padding at ${ + start && end ? 'start and end' : start ? 'start' : 'end' + }`, + INVALID_AGGREGATION_METHOD: (metric: string) => + `Aggregation is not possible for given ${metric} since method is 'none'.`, + METRIC_MISSING: (metric: string, index: number) => + `Aggregation metric ${metric} is not found in inputs[${index}].`, + INVALID_GROUP_BY: (type: string) => `Invalid group ${type}.`, + REJECTING_OVERRIDE: (param: ManifestParameter) => + `Rejecting overriding of canonical parameter: ${param.name}.`, + INVALID_EXHAUST_PLUGIN: (pluginName: string) => + `Invalid exhaust plugin: ${pluginName}.`, + UNKNOWN_PARAM: (name: string) => + `Unknown parameter: ${name}. Using 'sum' aggregation method.`, + NOT_INITALIZED_PLUGIN: (name: string) => + `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`, + NO_OUTPUT: ` +You have not selected an output method. To see your output data, you can choose from: +--stdout: this will print your output data to the console +--output : this will save your output data to the given filepath (do not provide file extension) +Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`, + UNSUPPORTED_ERROR: (errorName: string) => + `UnsupportedErrorClass: plugin threw error class: ${errorName} that is not recognized by Impact Framework`, + /** Debugging logs */ + STARTING_IF: 'Starting IF', + EXITING_IF: 'Exiting IF', + LOADING_MANIFEST: 'Loading manifest', + VALIDATING_MANIFEST: 'Validating manifest', + CAPTURING_RUNTIME_ENVIRONMENT_DATA: 'Capturing runtime environment data', + SYNCING_PARAMETERS: 'Syncing parameters', + CHECKING_AGGREGATION_METHOD: (unitName: string) => + `Checking aggregation method for ${unitName}`, + INITIALIZING_PLUGINS: 'Initializing plugins', + INITIALIZING_PLUGIN: (pluginName: string) => `Initializing ${pluginName}`, + LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => + `Loading ${pluginName} from ${path}`, + COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => + `Computing pipeline for \`${nodeName}\``, + MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', + AGGREGATING_OUTPUTS: 'Aggregating outputs', + AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, + PREPARING_OUTPUT_DATA: 'Preparing output data', + EXPORTING_TO_YAML_FILE: (savepath: string) => + `Exporting to yaml file: ${savepath}`, + EXPORTING_TO_CSV_FILE: (savepath: string) => + `Exporting to csv file: ${savepath}`, + EXPORTING_RAW_CSV_FILE: (savepath: string) => + `Exporting raw csv file: ${savepath}`, + /** Exhaust messages */ + OUTPUT_REQUIRED: + 'Output path is required, please make sure output is configured properly.', + CSV_EXPORT: + 'CSV export criteria is not found in output path. Please append it after --output #.', + WRITE_CSV_ERROR: (outputPath: string, error: any) => + `Failed to write CSV file to ${outputPath}: ${error}`, + /** Plugins messages */ + INVALID_NAME: + '`name` global config parameter is empty or contains all spaces', + START_LOWER_END: '`start-time` should be lower than `end-time`', + TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, + INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, + X_Y_EQUAL: 'The length of `x` and `y` should be equal', + ARRAY_LENGTH_NON_EMPTY: + 'the length of the input arrays must be greater than 1', + WITHIN_THE_RANGE: + 'The target x value must be within the range of the given x values', + MISSING_CSV_COLUMN: (columnName: string) => + `There is no column with the name: ${columnName}.`, + NO_QUERY_DATA: + 'One or more of the given query parameters are not found in the target CSV file column headers.', + INVALID_DATE_TYPE: (date: any) => + `Unexpected date datatype: ${typeof date}: ${date}`, + INVALID_OBSERVATION_OVERLAP: + 'Observation timestamps overlap, please check inputs.', + SCI_MISSING_FN_UNIT: (functionalUnit: string) => + `'carbon' and ${functionalUnit} should be present in your input data.`, + MISSING_FUNCTIONAL_UNIT_CONFIG: + '`functional-unit` should be provided in your global config', + MISSING_FUNCTIONAL_UNIT_INPUT: + '`functional-unit` value is missing from input data or it is not a positive integer', + REGEX_MISMATCH: (input: any, match: string) => + `\`${input}\` does not match the ${match} regex expression`, + SCI_EMBODIED_ERROR: (unit: string) => + `invalid number. please provide it as \`${unit}\` to input`, + MISSING_MIN_MAX: 'Config is missing min or max value', + INVALID_MIN_MAX: (name: string) => + `Min value should not be greater than or equal to max value of ${name}`, + FILE_FETCH_FAILED: ( + filepath: string, + message: string + ) => `Failed fetching the file: ${filepath}. +${message}`, + FILE_READ_FAILED: ( + filepath: string, + error: string + ) => `Failed reading the file: ${filepath}. +${error}`, + ZERO_DIVISION: (moduleName: string, index: number) => + `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, + MISSING_GLOBAL_CONFIG: 'Global config is not provided.', + MISSING_INPUT_DATA: (param: string) => + `${param} is missing from the input array, or has nullish value.`, +}; From 2d0cc9a34c23f618d2526424904c00af34dd4157 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:15:12 +0400 Subject: [PATCH 303/863] feat(src): init if-run builtins --- src/if-run/builtins/README.md | 848 ++++++++++++++++++ src/if-run/builtins/coefficient/README.md | 110 +++ src/if-run/builtins/coefficient/index.ts | 86 ++ src/if-run/builtins/copy-param/README.md | 104 +++ src/if-run/builtins/copy-param/index.ts | 90 ++ src/if-run/builtins/csv-lookup/README.md | 180 ++++ src/if-run/builtins/csv-lookup/index.ts | 247 +++++ src/if-run/builtins/divide/README.md | 121 +++ src/if-run/builtins/divide/index.ts | 109 +++ src/if-run/builtins/exponent/README.md | 117 +++ src/if-run/builtins/exponent/index.ts | 81 ++ src/if-run/builtins/export-csv-raw.ts | 156 ++++ src/if-run/builtins/export-csv.ts | 117 +++ src/if-run/builtins/export-log.ts | 21 + src/if-run/builtins/export-yaml.ts | 36 + src/if-run/builtins/group-by.ts | 95 ++ src/if-run/builtins/index.ts | 16 + src/if-run/builtins/interpolation/README.md | 196 ++++ src/if-run/builtins/interpolation/index.ts | 197 ++++ .../builtins/mock-observations/README.md | 97 ++ .../helpers/common-generator.ts | 33 + .../helpers/rand-int-generator.ts | 68 ++ .../builtins/mock-observations/index.ts | 178 ++++ .../mock-observations/interfaces/index.ts | 6 + src/if-run/builtins/multiply/README.md | 109 +++ src/if-run/builtins/multiply/index.ts | 84 ++ src/if-run/builtins/regex/README.md | 121 +++ src/if-run/builtins/regex/index.ts | 96 ++ src/if-run/builtins/sci-embodied/README.md | 124 +++ src/if-run/builtins/sci-embodied/index.ts | 130 +++ src/if-run/builtins/sci/README.md | 112 +++ src/if-run/builtins/sci/config.ts | 40 + src/if-run/builtins/sci/index.ts | 91 ++ src/if-run/builtins/shell/README.md | 141 +++ src/if-run/builtins/shell/index.ts | 65 ++ src/if-run/builtins/subtract/README.md | 105 +++ src/if-run/builtins/subtract/index.ts | 88 ++ src/if-run/builtins/sum/README.md | 118 +++ src/if-run/builtins/sum/index.ts | 88 ++ src/if-run/builtins/time-sync.ts | 459 ++++++++++ 40 files changed, 5280 insertions(+) create mode 100644 src/if-run/builtins/README.md create mode 100644 src/if-run/builtins/coefficient/README.md create mode 100644 src/if-run/builtins/coefficient/index.ts create mode 100644 src/if-run/builtins/copy-param/README.md create mode 100644 src/if-run/builtins/copy-param/index.ts create mode 100644 src/if-run/builtins/csv-lookup/README.md create mode 100644 src/if-run/builtins/csv-lookup/index.ts create mode 100644 src/if-run/builtins/divide/README.md create mode 100644 src/if-run/builtins/divide/index.ts create mode 100644 src/if-run/builtins/exponent/README.md create mode 100644 src/if-run/builtins/exponent/index.ts create mode 100644 src/if-run/builtins/export-csv-raw.ts create mode 100644 src/if-run/builtins/export-csv.ts create mode 100644 src/if-run/builtins/export-log.ts create mode 100644 src/if-run/builtins/export-yaml.ts create mode 100644 src/if-run/builtins/group-by.ts create mode 100644 src/if-run/builtins/index.ts create mode 100644 src/if-run/builtins/interpolation/README.md create mode 100644 src/if-run/builtins/interpolation/index.ts create mode 100644 src/if-run/builtins/mock-observations/README.md create mode 100644 src/if-run/builtins/mock-observations/helpers/common-generator.ts create mode 100644 src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts create mode 100644 src/if-run/builtins/mock-observations/index.ts create mode 100644 src/if-run/builtins/mock-observations/interfaces/index.ts create mode 100644 src/if-run/builtins/multiply/README.md create mode 100644 src/if-run/builtins/multiply/index.ts create mode 100644 src/if-run/builtins/regex/README.md create mode 100644 src/if-run/builtins/regex/index.ts create mode 100644 src/if-run/builtins/sci-embodied/README.md create mode 100644 src/if-run/builtins/sci-embodied/index.ts create mode 100644 src/if-run/builtins/sci/README.md create mode 100644 src/if-run/builtins/sci/config.ts create mode 100644 src/if-run/builtins/sci/index.ts create mode 100644 src/if-run/builtins/shell/README.md create mode 100644 src/if-run/builtins/shell/index.ts create mode 100644 src/if-run/builtins/subtract/README.md create mode 100644 src/if-run/builtins/subtract/index.ts create mode 100644 src/if-run/builtins/sum/README.md create mode 100644 src/if-run/builtins/sum/index.ts create mode 100644 src/if-run/builtins/time-sync.ts diff --git a/src/if-run/builtins/README.md b/src/if-run/builtins/README.md new file mode 100644 index 000000000..c37e143a1 --- /dev/null +++ b/src/if-run/builtins/README.md @@ -0,0 +1,848 @@ +# IF builtins + +There are three built-in features of IF: + +- time-sync +- CSV exporter +- groupby + +On this page, you can find the documentation for each of these three builtins. + +## Time-sync + +Time sync standardizes the start time, end time and temporal resolution of all output data across an entire tree. + +### Parameters + +### Plugin config + +The following should be defined in the plugin initialization: + +- `start-time`: global start time as ISO 8061 string +- `stop`: global end time as ISO 8061 string +- `interval`: temporal resolution in seconds +- `error-on-padding`: avoid zero/'zeroish' padding (if needed) and error out instead. `False` by defult. + +#### Inputs: + +- `inputs`: an array of observations + +#### Returns + +- `inputs`: time-synchronized version of the tree + + + + +#### Overview + +A manifest file for a tree might contain many nodes each representing some different part of an application's stack or even different applications running on different machines. It is therefore common to have time series data in each component that is not directly comparable to other components either because the temporal resolution of the data is different, they cover different periods, or there are gaps in some records (e.g. some apps might burst but then go dormant, while others run continuously). This makes post-hoc visualization, analysis and aggregation of data from groups of nodes difficult to achieve. To address this, we created a time synchronization plugin that takes in non-uniform times series and snaps them all to a regular timeline with uniform start time, end time and temporal resolution. + +We do this by implementing the following logic: + +- Shift readings to nearest whole seconds +- Upsample the time series to a base resolution (1s) +- Resample to desired resolution by batching 1s entries +- Extrapolate or trim to ensure all time series share global start and end dates + +The next section explains each stage in more detail. + +#### Details + +##### Upsampling rules + +A set of `inputs` is naturally a time series because all `observations` include a `timestamp` and a `duration`, measured in seconds. +For each `observation` in `inputs` we check whether the duration is greater than 1 second. If `duration` is greater than 1 second, we create N new `observation` objects, where N is equal to `duration`. This means we have an `observation` for every second between the initial timestamp and the end of the observation period. Each new object receives a timestamp incremented by one second. + +This looks as follows: + +```ts +[{timestamp: '2023-12-12T00:00:00.000Z', duration: 5}] + +# becomes +[ + {timestamp: '2023-12-12T00:00:01.000Z', duration: 1} + {timestamp: '2023-12-12T00:00:02.000Z', duration: 1} + {timestamp: '2023-12-12T00:00:03.000Z', duration: 1} + {timestamp: '2023-12-12T00:00:04.000Z', duration: 1} + {timestamp: '2023-12-12T00:00:05.000Z', duration: 1} +] +``` + +Each `observation` actually includes many key-value pairs. The precise content of the `observation` is not known until runtime because it depends on which plugins have been included in the pipeline. Different values have to be treated differently when we upsample in time. The method we use to upsample depends on the `aggregation-method` defined for each key in `units.yml`. + +If the right way to aggregate a value is to sum it, then the right way to upsample it is to divide by `duration`, effectively spreading the total out evenly across the new, higher resolution, `observations` so that the total across the same bucket of time is unchanged (i.e. if the total for some value is 10 when there is one entry with `duration = 10s`, then the total should still be 10 when there are 10 entries each witch `duration = 1s`). + +On the other hand, if the right way to aggregate a value is to take its average over some time period, the value should be copied unchanged into the newly upsampled `observations`. This is appropriate for values that are proportional or percentages, such as `cpu/utilization`. Treating these values as constants means the average over the `duration` for an observation is identical whether you consider the initial `observation` or the upsampled set of N `observation`s. + +Constants can simply be copied as-is, because they are constants. Examples might be the `grid/carbon-intensity` - this value does not change depending on how frequently you observe it. + +Therefore, we apply this logic and the resulting flow looks as follows (the `aggregation-method` for `carbon` and `energy` is `sum`, `grid/carbon-intensity` is a constant and `cpu/utilization` is expressed as a percentage): + +```ts +[{timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, 'grid/carbon-intensity': 471}] + +# becomes + +[ + {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, + {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, + {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, + {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, + {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, + {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471} +] +``` + +The end result is that for each `observation`, we upsample the time series to yield 1 second resolution data between `timestamp` and `timestamp + duration`. + +##### Gap-filling + +Sometimes there might be discontinuities in the time series between one `observation` and another. For example we might have two `observations` in a set of `inputs` that have timestamps spaced 10 seconds apart, but the `duration` of the first `observation` is only 5 seconds. in this case, 5 seconds of data are unaccounted for and create a discontinuity in the time series. + +To solve this problem, for all but the first `observation` in the `inputs` array, we grab the `timestamp` and `duration` from the previous `observation` and check that `timestamp[N] + duration[N] == timestamp[N+1]`. If this condition is not satisfied, we backfill the missing data with a "zero-observation" which is identical to the surrounding observations except any values whose `aggregation-method` is `sum` are set to zero. This is equivalent to assuming that when there is no data available, the app being monitored is switched off. + +The end result of this gap-filling is that we have continuous 1 second resolution data that can be resampled to a new temporal resolution. + +```ts +[ + {timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:08.000Z', duration: 2, 'cpu/utilization': 12, carbon: 5, energy: 10, grid/carbon-intensity: 471} +] + +# There are 2 seconds of missing data between the end of timestamp[0] + duration, and timestamp[1] +# After expansion and infilling, the array becomes: + +[ + {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:06.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:07.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:08.000Z', duration: 1, 'cpu/utilization': 12, carbon: 2.5, energy: 5, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:09.000Z', duration: 1, 'cpu/utilization': 12, carbon: 2.5, energy: 5, grid/carbon-intensity: 471} +] +``` + +Note that when `error-on-padding` is `true` no gap-filling is performed and the plugin will error out instead. + +##### Trimming and padding + +To ensure parity across all the components in a tree, we need to synchronize the start and end times for all time series. To do this, we pass the `time-sync` plugin plugin some global config: `startTime`, `endTime` and `interval`. The `startTime` is the timestamp where _all_ input arrays across the entire tree should begin, and `endTime` is the timestamp where _all_ input arrays across the entire tree should end. `interval` is the time resolution we ultimately want to resample to. + +To synchronize the time series start and end we check the first element of `inputs` for each node in the tree and determine whether it is earlier, later or equal to the global start time. If it is equal then no action is required. If the `input` start time is earlier than the global start time, we simply discard entries from the front of the array until the start times are aligned. If the `input` start time is after the global start time, then we pad with our "zero-observation" object - one for every second separating the global start time from the `input` start time. The same process is repeated for the end time - we either trim away `input` data or pad it out with "zero-observation" objects. + +For example, for `startTime = 2023-12-12T00:00:00.000Z` and `endTime = 2023-12-12T00:00:15.000Z`: + +```ts +[ + {timestamp: '2023-12-12T00:00:05.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, 'grid/carbon-intensity': 471}, +] + +# There are 5 seconds missing from the start and end. After padding, the array becomes: + +[ + {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:06.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:07.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:08.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:09.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:10.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:11.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:12.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:13.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + {timestamp: '2023-12-12T00:00:14.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, + +] +``` + +Note that when `error-on-padding` is `true` no padding is performed and the plugin will error out instead. + +##### Resampling rules + +Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `intervalk` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `params.ts`. The returned array is the final, synchronized time series at the desired temporal resolution. + + +#### Assumptions and limitations + +To do time synchronization, we assume: + +- There is no environmental impact for an application when there is no data available. +- Evenly distributing the total for a `duration` across higher resolution `observations` is appropriate, as opposed to having some non-uniform distribution. + + +### Typescript implementation + + +To run the plugin, you must first create an instance of `TimeSync`. +Then, you can call `execute()`. + +```typescript +const globalConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:30.000Z', + interval: 10 +} +const timeSync = TimeSync(globalConfig); +const results = timeSync.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z' + duration: 10 + 'cpu/utilization': 10 + carbon: 100 + energy: 100 + requests: 300 + }, + { + timestamp: '2023-12-12T00:00:10.000Z' + duration: 10 + 'cpu/utilization': 20 + carbon: 100, + energy: 100, + requests: 380 + } +]) +``` + +### Example manifest + +IF users will typically call the plugin as part of a pipeline defined in an `manifest` +file. In this case, instantiating and configuring 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 `time-sync`: + +```yaml +name: time-sync-demo +description: impl with 2 levels of nesting with non-uniform timing of observations +tags: +initialize: + plugins: + teads-curve: + method: TeadsCurve + path: '@grnsft/if-unofficial-plugins' + sci-e: + method: SciE + path: '@grnsft/if-plugins' + sci-embodied: + path: 'builtin' + method: SciEmbodied + sci-o: + method: SciO + path: '@grnsft/if-plugins' + time-sync: + method: TimeSync + path: builtin + global-config: + start-time: '2023-12-12T00:00:00.000Z' # ISO timestamp + end-time: '2023-12-12T00:01:00.000Z' # ISO timestamp + interval: 5 # seconds +tree: + children: + child: # an advanced grouping node + pipeline: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync + config: + teads-curve: + cpu/thermal-design-power: 65 + sci-embodied: + device/emissions-embodied: 251000 # gCO2eq + time-reserved: 3600 # 1 hour in s + device/expected-lifespan: 126144000 # 4 years in seconds + resources-reserved: 1 + resources-total: 1 + sci-o: + grid/carbon-intensity: 457 # gCO2/kwh + children: + child-1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 10 + cpu/utilization: 10 + carbon: 100 + energy: 100 + requests: 300 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 10 + cpu/utilization: 20 + carbon: 200 + energy: 200 + requests: 380 +``` + + +## CSV Exporter + +IF supports exporting data to CSV files. This provides users with a data format that enables visualization and data analysis using standard data analysis tools. + +### Manifest config + +To export your data to a CSV file, you have to provide a small piece of config data to your manifest file: + +```yaml +initialize: + outputs: + - csv +``` + +You can also add `- yaml` if you want to export to both `yaml` and `csv` simultaneously. + +### CLI command + +Then, you must select the metric you want to export to CSV. The name of that metric must be added to the savepath provided to the `--output` command in the CLI, after a hashtag. + +For example, to export the `carbon` data from your tree to a CSV file: + +```sh +if-run --manifest example.yml --output example#carbon +``` + +This will save a CSV file called `example.csv`. The contents will look similar to the following: + +| | | | | | +| ---------------------------------------------- | ---------------- | ---------------------------- | ---------------------------- | ---------------------------- | +| **Path** | **Aggregated** | **2024-03-05T00:00:00.000Z** | **2024-03-05T00:05:00.000Z** | **2024-03-05T00:10:00.000Z** | +| tree.carbon | 425.289232008725 | 17.9269877157543 | 8.9024388783018 | 45.6021901509012 | +| tree.children.westus3.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | +| tree.children.westus3.children.server-1.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | +| tree.children.france.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | +| tree.children.france.children.server-2.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | + + +### Comparing CSV to Yaml + +The CSV above is generated from the following yaml. The `carbon` metric is extracted and added to the CSV. Otherwise, the CSV is an exact representation of the following yaml tree. You can see that the CSV representation is *much* easier to understand than the full yaml tree: + +```yaml +tree: + pipeline: + - mock-observations + - group-by + - cloud-metadata + - time-sync + - watttime + - teads-curve + - operational-carbon + defaults: + grid/carbon-intensity: 500 + config: + group-by: + group: + - cloud/region + - name + children: + westus3: + children: + server-1: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 66 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 4 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 54 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 19 + grid/carbon-intensity: 500 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 65.78 + grid/carbon-intensity: 369.4947514218548 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: CAISO + cloud/region-em-zone-id: US-CAL-CISO + cloud/region-wt-id: CAISO_NORTH + cloud/region-location: US West (N. California) + cloud/region-geolocation: 34.0497,-118.1326 + geolocation: 34.0497,-118.1326 + cpu/energy: 0.018934842060004835 + carbon: 6.996324760173567 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 3.986666666666667 + grid/carbon-intensity: 369.38452029076234 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: CAISO + cloud/region-em-zone-id: US-CAL-CISO + cloud/region-wt-id: CAISO_NORTH + cloud/region-location: US West (N. California) + cloud/region-geolocation: 34.0497,-118.1326 + geolocation: 34.0497,-118.1326 + cpu/energy: 0.004545546617763956 + carbon: 1.6790545568620359 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 53.82 + grid/carbon-intensity: 372.58122309244305 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: CAISO + cloud/region-em-zone-id: US-CAL-CISO + cloud/region-wt-id: CAISO_NORTH + cloud/region-location: US West (N. California) + cloud/region-geolocation: 34.0497,-118.1326 + geolocation: 34.0497,-118.1326 + cpu/energy: 0.017357893372978016 + carbon: 6.467225143212361 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 18.936666666666667 + grid/carbon-intensity: 434.20042537311633 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: CAISO + cloud/region-em-zone-id: US-CAL-CISO + cloud/region-wt-id: CAISO_NORTH + cloud/region-location: US West (N. California) + cloud/region-geolocation: 34.0497,-118.1326 + geolocation: 34.0497,-118.1326 + cpu/energy: 0.010385485956624245 + carbon: 4.5093824200727735 + aggregated: + carbon: 19.651986880320734 + outputs: + - carbon: 6.996324760173567 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - carbon: 1.6790545568620359 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - carbon: 6.467225143212361 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - carbon: 4.5093824200727735 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + aggregated: + carbon: 19.651986880320734 + france: + children: + server-2: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 15 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 78 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 16 + grid/carbon-intensity: 500 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 6 + grid/carbon-intensity: 500 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 14.95 + grid/carbon-intensity: 1719.1647205176753 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: France + cloud/region-em-zone-id: FR + cloud/region-wt-id: FR + cloud/region-location: Paris + cloud/region-geolocation: 48.8567,2.3522 + geolocation: 48.8567,2.3522 + cpu/energy: 0.00905914075141129 + carbon: 15.574155178030272 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 77.74 + grid/carbon-intensity: 1719.0544893865829 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: France + cloud/region-em-zone-id: FR + cloud/region-wt-id: FR + cloud/region-location: Paris + cloud/region-geolocation: 48.8567,2.3522 + geolocation: 48.8567,2.3522 + cpu/energy: 0.020379266251888902 + carbon: 35.0330691407141 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 15.946666666666667 + grid/carbon-intensity: 1718.8707708347622 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: France + cloud/region-em-zone-id: FR + cloud/region-wt-id: FR + cloud/region-location: Paris + cloud/region-geolocation: 48.8567,2.3522 + geolocation: 48.8567,2.3522 + cpu/energy: 0.009405866514354337 + carbon: 16.16746902589712 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 5.98 + grid/carbon-intensity: 1718.6686804277592 + vcpus-allocated: 64 + vcpus-total: 64 + memory-available: 432 + physical-processor: >- + Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® + Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz + cpu/thermal-design-power: 269.1 + cloud/region-cfe: France + cloud/region-em-zone-id: FR + cloud/region-wt-id: FR + cloud/region-location: Paris + cloud/region-geolocation: 48.8567,2.3522 + geolocation: 48.8567,2.3522 + cpu/energy: 0.0054492484351820105 + carbon: 9.365452617417297 + aggregated: + carbon: 76.1401459620588 + outputs: + - carbon: 15.574155178030272 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - carbon: 35.0330691407141 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - carbon: 16.16746902589712 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - carbon: 9.365452617417297 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + aggregated: + carbon: 76.1401459620588 + outputs: + - carbon: 22.57047993820384 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - carbon: 36.71212369757613 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - carbon: 22.63469416910948 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - carbon: 13.87483503749007 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + aggregated: + carbon: 95.79213284237952 +``` + +### CSV and aggregation + +The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the *rows* of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the *columns* in the CSV representation (this is not *exactly* accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). + + +## Groupby + +Groupby is an IF plugin that reorganizes a tree according to keys provided by the user. This allows users to regroup their observations according to various properties of their application. For example, the following manifest file contains a flat array of observations. This is how you might expect data to arrive from an importer plugin, maybe one that hits a metrics API for a cloud service. + + +```yaml +name: if-demo +description: demo pipeline +graph: + children: + my-app: + pipeline: + - group-by + - teads-curve + config: + group-by: + - cloud/region + - instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 12 + - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp + duration: 300 + instance-type: B1 + cloud/region: uk-west + cpu-util: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: B1 + cloud/region: uk-west + cpu-util: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: B1 + cloud/region: uk-west + cpu-util: 1 +``` + +However, each observation contains an `instance-type` field that varies between observations. There are two instance types being represented in this array of observations. This means there are duplicate entries for the same timestamp in this array. This is the problem that `group-by` solves. You provide `instance-type` as a key to the `group-by` plugin and it extracts the data belonging to the different instances and separates them into independent arrays. The above example would be restructured so that instance types `A1` and `B1` have their own data, as follows: + +```yaml +graph: + children: + my-app: + pipeline: + # - group-by + - teads-curve + config: + group-by: + groups: + - cloud/region + - instance-type + children: + A1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 12 + B1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 1 +``` + +### Using `group-by` + +To use `group-by`, you have to initialize it as a plugin and invoke it in a pipeline. + +The initialization looks as follows: + +```yaml +initialize: +plugins: +group-by: + path: 'builtin' + method: GroupBy +``` + +You then have to provide config defining which keys to group by in each component. This is done at the component level (i.e. not global config). +For example: + + +```yaml +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: + - cloud/region + - instance-type +``` + +In the example above, the plugin would regroup the input data for the specific component by `cloud/region` and by `instance-type`. + +Assuming the values `A1` and `B1` are found for `instance-type` and the values `uk-east` and `uk-west` are found for `cloud/region`, the result of `group-by` would look similar to the following: + +```yaml +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + groups: + - cloud/region + - instance-type + children: + uk-west: + children: + A1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: A1 + cloud/region: uk-west + cpu-util: 12 + uk-east: + children: + B1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + instance-type: B1 + cloud/region: uk-east + cpu-util: 1 +``` + +This reorganized data can then be used to feed the rest of a computation pipeline. diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md new file mode 100644 index 000000000..4579cd5b8 --- /dev/null +++ b/src/if-run/builtins/coefficient/README.md @@ -0,0 +1,110 @@ +# Coefficient + +`Coefficient` is a generic plugin for multiplying a value in an `input` array by a given coefficient. + +You provide the name of the value you want to multiply, a coefficient value, and a name to use to append the product to the output array. + +For example, you could multiply `cpu/energy` by 10 and name the result `energy-product`. `energy-product` would then be added to every observation in your input array as the product of `cpu/energy` and 10. + +## Parameters + +### Plugin global config + +Three parameters are required in global config: `input-parameter`, `coefficient` and `output-parameter`. + +- `input-parameter`: a string matching an existing key in the `inputs` array +- `coefficient`: the value to multiply `input-parameter` by. +- `output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. + +### Inputs + +All of `input-parameters` must be available in the input array. + +## Returns + +- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input * coefficient +``` + +## Implementation + +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 coeff = Coefficient(config); +const result = coeff.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + }, +]); +``` + +## 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 `coefficient`: + +```yaml +name: coefficient-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + coefficient: + method: Coefficient + path: 'builtin' + global-config: + input-parameter: 'carbon' + coefficient: 3 + output-parameter: 'carbon-product' +tree: + children: + child: + pipeline: + - coefficient + config: + coefficient: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 +``` + +You can run this example by saving it as `./examples/manifests/coefficient.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Coefficient` exposes one of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameter`: this must be a string +- `coefficient`: this must be a number +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts new file mode 100644 index 000000000..4b80be633 --- /dev/null +++ b/src/if-run/builtins/coefficient/index.ts @@ -0,0 +1,86 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + CoefficientConfig, + ExecutePlugin, + PluginParams, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Calculate the product of each input parameter. + */ + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const inputParameter = safeGlobalConfig['input-parameter']; + const outputParameter = safeGlobalConfig['output-parameter']; + const coefficient = safeGlobalConfig['coefficient']; + + return inputs.map(input => { + validateSingleInput(input, inputParameter); + + return { + ...input, + [outputParameter]: calculateProduct(input, inputParameter, coefficient), + }; + }); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); + + return input; + }; + + /** + * Calculates the product of the energy components. + */ + const calculateProduct = ( + input: PluginParams, + inputParameter: string, + coefficient: number + ) => input[inputParameter] * coefficient; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + coefficient: z.number(), + 'input-parameter': z.string().min(1), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md new file mode 100644 index 000000000..78ab5f656 --- /dev/null +++ b/src/if-run/builtins/copy-param/README.md @@ -0,0 +1,104 @@ +# Copy-param + +`copy-param` is a generic plugin that duplicates an existing parameter in the `input` data and assigns it to a new key. You can either keep or delete the original copied parameter. A common use case for this is to rename parameters in the `inputs` array. + +You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or delete the original copied value. + +For example, you could copy `energy` into `energy-copy`, with `keep-existing=true`. In this case your inputs: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 +``` + +would become + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 + energy-copy: 30 +``` + +but with `keep-existing=false`, the same inputs would yield: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy-copy: 30 +``` + +## Parameters + +### Config + +Three parameters are required in config: `from` and `to` and `keep-existing`. + +`from`: an array of strings. Each string should match an existing key in the `inputs` array +`to`: a string defining the name to use to add the result of summing the input parameters to the output array. +`keep-existing`: toggles whether to keep or delete the copied parameter (defined in `to`) + +### Inputs + +As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. + +## Returns + +The plugin adds a new parameter with the name defined in `to` to the `input` data. + + +## Implementation + +To run the plugin, you must first create an instance of `Copy`. Then, you can call `execute()`. + +```typescript +import { Copy } from "."; + +const plugin = Copy({ 'keep-existing': true, from: 'from-param', to: 'to-param' }); + +const result = plugin.execute([{ + timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + 'from-param': 'hello', +}]) + +console.log(result) + +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `copy-param`: + +```yaml +name: copy-param +description: +tags: +initialize: + plugins: + copy-param: + path: builtin + method: Copy + global-config: + keep-existing: true + from: original + to: copy +tree: + children: + child-1: + pipeline: + - copy-param + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + original: 'hello' + +``` + +You can run this example by saving it as `./manifests/examples/copy.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./manifests/examples/copy.yml -s +``` + +The results will be displayed in the console. diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts new file mode 100644 index 000000000..cf21cfb8e --- /dev/null +++ b/src/if-run/builtins/copy-param/index.ts @@ -0,0 +1,90 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +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): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + 'keep-existing': z.boolean(), + from: z.string().min(1), + to: z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.string()); + + validate(validationSchema, inputData); + + return input; + }; + + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const keepExisting = safeGlobalConfig['keep-existing'] === true; + const from = safeGlobalConfig['from']; + const to = safeGlobalConfig['to']; + + return inputs.map(input => { + const safeInput = validateSingleInput(input, [from]); + + const outputValue = safeInput[from]; + if (safeInput[from]) { + if (!keepExisting) { + delete safeInput[from]; + } + } + + return { + ...safeInput, // need to return or what you provide won't be outputted, don't be evil! + [to]: outputValue, + }; + }); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md new file mode 100644 index 000000000..3663f4123 --- /dev/null +++ b/src/if-run/builtins/csv-lookup/README.md @@ -0,0 +1,180 @@ +# CSV Lookup Plugin + +`csv-lookup` is a generic plugin that enables you to select arbitrary data from a given csv file and add it to your manifest file's `input` data. + +You provide path to the target csv file pus some query parameters. The filepath can point to a location on the local filesystem or it can be a URL for an online resource. The query parameters include the column names for the target data you want to return (can be one column name, multiple column names or all column names, indicated using `"*"`), plus the column names and values you want to use as selectors. + +For example, for the following CSV: + +| | | | | | | | | | | | | | | | | | +| ---- | -------------- | --------------- | ---------- | ---------- | ------------ | --------- | ---------------- | ---------- | ---------- | ---------------------- | ---------- | -------------------------- | --------------------------------- | ------------------------------ | -------------------------------- | --------------------- | +| year | cloud-provider | cloud-region | cfe-region | em-zone-id | wt-region-id | location | geolocation | cfe-hourly | cfe-annual | power-usage-efficiency | net-carbon | grid-carbon-intensity-24x7 | grid-carbon-intensity-consumption | grid-carbon-intensity-marginal | grid-carbon-intensity-production | grid-carbon-intensity | +| 2022 | Google Cloud | asia-east1 | Taiwan | TW | TW | Taiwan | 25.0375,121.5625 | 0.18 | | | 0 | 453 | | | | 453 | +| 2022 | Google Cloud | asia-east2 | Hong Kong | HK | HK | Hong Kong | 22.3,114.2 | 0.28 | | | 0 | 453 | | | | 360 | +| 2022 | Google Cloud | asia-northeast1 | Tokyo | JP-TK | JP-TK | Tokyo | 35.6897,139.692 | 0.28 | | | 0 | 463 | | | | 463 | + + +You could select all the data for the cloud provider `Google Cloud` in the region `asia-east2` using the following configuration: + +```yaml +filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv +query: + cloud-provider: "cloud/provider" + cloud-region: "cloud/region" +output: "*" +``` + +Notice that the query parameters are key/value pairs where the key is the column name in the target CSV and the value is a **reference to a value** in your `input` data (*not* an actual value - a reference). This is to enable you to chain CSV lookups together based on information from other plugins in your pipeline. + + +## Parameters + +### Plugin config + +- `filepath` - path to a csv file, either on the local filesystem or on the internet +- `query` - an array of key/value pairs where the key is a column name in the target csv and the value is a parameter from inputs +- `output` - the columns to grab data from and add to output data - should support wildcard or multiple values. + +The plugin also supports data renaming. This means you can grab data from a named column but push it into your manifest file data under another name, for example, maybe we want to grab data from the `processor-name` column int he target csv and add it to the manifest file data as `processor-id` because this is the name expected by some other plugin in your piepline. You can do this by passing comma separated values in arrays. + +```yaml +output: + ["processor-name": "processor-id"] +``` + +You can nest arrays to do this renaming for multiple columns. + +```yaml +output: + [["processor-name", "processor-model-id"],["tdp","thermal-design-power"]] +``` + +All the following values are valid for the `output` field: +- `"*"` +- `"tdp"` +- `["processor-name", "processor-model-id"]` +- `[["processor-name", "processor-model-id"],["tdp","thermal-design-power"]]` + +### 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. + +## Returns + +The input data with the requested csv content appended to it. + +## Plugin logic + +1. Validates global config which contains `filepath`, `query` and `output`. +2. Tries to retrieve given file (with url or local path). +3. Parses given CSV. +4. Filters requested information from CSV. +5. Adds new key-value pairs to the input data +6. Returns enriched input data + +## Implementation + +To run the plugin, you must first create an instance of `CSVLookup`. Then, you can call `execute()`. + +```typescript +const globalConfig = { + filepath: 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', + query: { + 'cloud-provider': 'cloud/provider' + region: 'cloud/region' + 'instance-type': 'cloud/instance-type' + }, + output: ['cpu-tdp', 'tdp'], +}; +const divide = CSVLookup(globalConfig); + +const input = [ + { + timestamp: '2023-08-06T00:00' + duration: 3600 + 'cpu/energy': 0.001 + 'cloud/provider': gcp + 'cloud/region': asia-east + }, +]; +``` + +## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `csv-lookup`: + +```yaml +name: csv-lookup-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + method: CSVLookup + path: 'builtin' + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: "cloud/provider" + cloud-region: "cloud/region" + output: "*" +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: 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: + +```sh +npm i -g @grnsft/if +if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup +``` + +The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +Coefficient exposes six of the IF error classes. + +### FetchingFileError + +This error is caused by problems finding the file at the path provided in the `filepath`. If the file is on your local filesystem, you can check that the file is definitely there. For a remote file, check your internet connection. You can check your connection to the server using a tool such as `ping` or `curl`. if you still experience problems, you could retrieve the remote file onto your local filesystem using a tool such as `wget`. + +### ReadFileError, + +This error is caused by problems reading the CSV file provided in the `filepath`. To fix it, check that the file contains valid CSV data. The file should have a `.csv` file extension and the data inside should be formatted correctly. + +### MissingCSVColumnError, + +This error is caused by `CsvLookup` failing to find a column in the CSV file whose name matches what was provided in `query`. To debug, check that you do not have any typos in your `query` and confirm that the requested column name definitely exists in the target file. + +### QueryDataNotFoundError, + +This error is caused by the `CsvLookup` plugin failing to find data that matches your query. Try revising your query parameters. + +### CSVParseError, + +This error arises due to problems parsing CSV data into IF. This can occur when the CSV data is incorrectly formatted or contains unexpected characters that IF does not recognize. These errors are expected to be unusual edge cases as incorrectly formatted data will usually be identified during file loading and cause a `ReadFileError`. To debug, check your CSV file for any unexpected formatting or unusual characters. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `filepath`: This must be a path to a csv file +- `query`: this must be an array of key-value pairs where the key is a string containing a column name an the value is a string containing the name of a value in `inputs` +- `output`: this must be a string containing a name or a wildcard character (`"*"`) + +You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts new file mode 100644 index 000000000..91e1739b3 --- /dev/null +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -0,0 +1,247 @@ +/* eslint-disable eqeqeq */ +import {readFile} from 'fs/promises'; + +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 {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const { + FILE_FETCH_FAILED, + FILE_READ_FAILED, + MISSING_CSV_COLUMN, + NO_QUERY_DATA, + MISSING_GLOBAL_CONFIG, +} = STRINGS; + +const { + FetchingFileError, + ReadFileError, + MissingCSVColumnError, + QueryDataNotFoundError, + GlobalConfigError, + CSVParseError, +} = ERRORS; + +export const CSVLookup = (globalConfig: any): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks if given string is URL. + */ + const isURL = (filepath: string) => { + try { + new URL(filepath); + return true; + } catch (error) { + return false; + } + }; + + /** + * Checks if given `filepath` is url, then tries to fetch it. + * Otherwise tries to read file. + */ + const retrieveFile = async (filepath: string) => { + if (isURL(filepath)) { + const {data} = await axios.get(filepath).catch(error => { + throw new FetchingFileError( + FILE_FETCH_FAILED(filepath, error.response.message) + ); + }); + + return data; + } + + return readFile(filepath).catch(error => { + throw new ReadFileError(FILE_READ_FAILED(filepath, error)); + }); + }; + + /** + * Checks if value is invalid: `undefined`, `null` or an empty string, then sets `nan` instead. + */ + const setNanValue = (value: any) => + value == null || value === '' ? 'nan' : value; + + /** + * Converts empty values to `nan`. + */ + const nanifyEmptyValues = (object: any) => { + if (typeof object === 'object') { + const keys = Object.keys(object); + + keys.forEach(key => { + const value = object[key]; + object[key] = setNanValue(value); + }); + + return object; + } + + return setNanValue(object); + }; + + /** + * If `field` is missing from `object`, then reject with error. + * Otherwise nanify empty values and return data. + */ + const fieldAccessor = (field: string, object: any) => { + if (!(`${field}` in object)) { + throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); + } + + return nanifyEmptyValues(object[field]); + }; + + /** + * 1. If output is anything, then removes query data from csv record to escape duplicates. + * 2. Otherwise checks if it's a miltidimensional array, then grabs multiple fields (). + * 3. If not, then returns single field. + * 4. In case if it's string, then + */ + const filterOutput = ( + dataFromCSV: any, + params: { + output: string | string[] | string[][]; + query: Record; + } + ) => { + const {output, query} = params; + + if (output === '*') { + const keys = Object.keys(query); + + keys.forEach(key => { + delete dataFromCSV[key]; + }); + + return nanifyEmptyValues(dataFromCSV); + } + + if (Array.isArray(output)) { + /** Check if it's a multidimensional array. */ + if (Array.isArray(output[0])) { + const result: any = {}; + + output.forEach(outputField => { + /** Check if there is no renaming request, then export as is */ + const outputTitle = outputField[1] || outputField[0]; + result[outputTitle] = fieldAccessor(outputField[0], dataFromCSV); + }); + + return result; + } + + const outputTitle = output[1] || output[0]; + + return { + [outputTitle as string]: fieldAccessor(output[0], dataFromCSV), + }; + } + + return { + [output]: fieldAccessor(output, dataFromCSV), + }; + }; + + /** + * Asserts CSV record with query data. + */ + const withCriteria = (queryData: Record) => (csvRecord: any) => { + const ifMatchesCriteria = Object.keys(queryData).map( + (key: string) => csvRecord[key] == queryData[key] + ); + + return ifMatchesCriteria.every(value => value === true); + }; + + /** + * Parses CSV file. + */ + const parseCSVFile = (file: string | Buffer) => { + try { + const parsedCSV: any[] = parse(file, { + columns: true, + skip_empty_lines: true, + cast: true, + }); + + return parsedCSV; + } catch (error: any) { + console.error(error); + throw new CSVParseError(error); + } + }; + + /** + * 1. Validates global config. + * 2. Tries to retrieve given file (with url or local path). + * 3. Parses given CSV. + * 4. Filters requested information from CSV. + */ + const execute = async (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const {filepath, query, output} = safeGlobalConfig; + + const file = await retrieveFile(filepath); + const parsedCSV = parseCSVFile(file); + + return inputs.map(input => { + /** Collects query values from input. */ + const queryData: any = {}; + const queryKeys = Object.keys(query); + queryKeys.forEach(queryKey => { + const queryValue = query[queryKey]; + queryData[queryKey] = input[queryValue]; + }); + + /** Gets related data from CSV. */ + const relatedData = parsedCSV.find(withCriteria(queryData)); + + if (!relatedData) { + throw new QueryDataNotFoundError(NO_QUERY_DATA); + } + + return { + ...input, + ...filterOutput(relatedData, {output, query}), + }; + }); + }; + + /** + * Checks for `filepath`, `query` and `output` fields in global config. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + filepath: z.string(), + query: z.record(z.string(), z.string()), + output: z + .string() + .or(z.array(z.string())) + .or(z.array(z.array(z.string()))), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md new file mode 100644 index 000000000..9a4d04f36 --- /dev/null +++ b/src/if-run/builtins/divide/README.md @@ -0,0 +1,121 @@ +# Divide + +`divide` is a generic plugin for doing arithmetic division of two values in an `input` array. + +You provide the names of the values you want to divide, and a name to use to add the divide to the output array. + +## Parameters + +### Plugin config + +- `numerator` - a parameter by a specific configured number +- `denominator` - a parameter by a specific configured number or the number by which `numerator` is divided +- `output` - the number to a configured output parameter + +### Inputs + +- `numerator` - as input parameter, must be available in the input array +- `denominator` - must be available in the input array if is an input parameter +- `output` - as input parameter, must be available in the input array + +## Returns + +- `output`: the division of `numerator` with the parameter name into `denominator` with the parameter name defined by `output` in global config. + +The plugin throws an exception if the division result is not a number. + +>Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. + +## Calculation + +```pseudocode +output = input0 / input1 +``` + +## Implementation + +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 divide = Divide(globalConfig); + +const input = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, +]; +``` + +## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `divide`: + +```yaml +name: divide-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + divide: + method: Divide + path: 'builtin' + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores +tree: + children: + child: + pipeline: + - divide + config: + divide: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + vcpus-allocated: 24 +``` + +You can run this example by saving it as `./examples/manifests/divide.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs`. + +## Errors + +`Divide` exposes two of IF's error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `numerator`: a string containing the name of the input parameter whose value should be divided by `denominator` +- `denominator`: a number to use as the denominator +- ``output`: a string containing the name to assign the result of the division + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `numerator` + + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts new file mode 100644 index 000000000..328c4ccff --- /dev/null +++ b/src/if-run/builtins/divide/index.ts @@ -0,0 +1,109 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; + +export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Calculate the division of each input parameter. + */ + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const {numerator, denominator, output} = safeGlobalConfig; + + return inputs.map((input, index) => { + const safeInput = Object.assign( + {}, + input, + validateSingleInput(input, {numerator, denominator}) + ); + + return { + ...input, + [output]: calculateDivide(safeInput, index, {numerator, denominator}), + }; + }); + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const schema = z.object({ + numerator: z.string().min(1), + denominator: z.string().or(z.number()), + output: z.string(), + }); + + return validate>(schema, globalConfig); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + params: { + numerator: string; + denominator: number | string; + } + ) => { + const {numerator, denominator} = params; + + const schema = z + .object({ + [numerator]: z.number(), + [denominator]: z.number().optional(), + }) + .refine(() => { + if (typeof denominator === 'string' && !input[denominator]) { + throw new MissingInputDataError(MISSING_INPUT_DATA(denominator)); + } + + return true; + }); + + return validate>(schema, input); + }; + + /** + * Calculates the division of the given parameter. + */ + const calculateDivide = ( + input: PluginParams, + index: number, + params: { + numerator: string; + denominator: number | string; + } + ) => { + const {denominator, numerator} = params; + const finalDenominator = input[denominator] || denominator; + + if (finalDenominator === 0) { + console.warn(ZERO_DIVISION(Divide.name, index)); + return input[numerator]; + } + + return input[numerator] / finalDenominator; + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md new file mode 100644 index 000000000..91d938cef --- /dev/null +++ b/src/if-run/builtins/exponent/README.md @@ -0,0 +1,117 @@ +# Exponent + +`exponent` is a generic plugin for calculating exponent of an input param (as base) and another (as the exponent) in an `input` array. + +You provide the names of the values you want to use for the exponent calculation, and a name to use to add the exponent result to the output array. + +For example, you use `cpu/energy` as base and `network/energy` as and name the result `energy`. `energy` would then be added to every observation in your input array as `cpu/energy` raised by the exponent `network/energy`. + +## Parameters + +### Plugin config + +Three parameters are required in global config: `input-parameter`, `exponent` and `output-parameter`. + +`input-parameter`: a string defining the base. Must match an existing key in the `inputs` array +`exponent`: a number defining the exponent. +`output-parameter`: a string defining the name to use to add the result of the exponent to the output array. + +### Inputs + +`input-parameter` and `exponent` must be available in the input array. + +## Returns + +- `output-parameter`: `input-parameter` raised by `exponent` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input ^ exponent +``` + +## Implementation + +To run the plugin, you must first create an instance of `Exponent`. Then, you can call `execute()`. + +```typescript +import {Exponent} from 'builtins'; + +const config = { + inputParameter: ['cpu/energy'], + exponent: 2 + outputParameter: 'energy', +}; + +const exponent = Exponent(config); +const result = await exponent.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + 'cpu/energy': 0.1, + 'energy': 0.01, + }, +]); +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `exponent`: + +```yaml +name: exponent demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + exponent: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'cpu/energy' + exponent: 2 + output-parameter: 'energy' +tree: + children: + child: + pipeline: + - exponent + config: + exponent: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 +``` + +You can run this example by saving it as `manifests/examples/test/exponent.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml +``` + +The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Exponent` exposes two of IF's error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: + +- `timestamp` +- `duration` +- whatever value you passed to `input-parameter` + + +### `InputValidationError` + +This error arises when an invalid value is passed to `Exponent`. 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 diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts new file mode 100644 index 000000000..800b2295e --- /dev/null +++ b/src/if-run/builtins/exponent/index.ts @@ -0,0 +1,81 @@ +import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + ExponentConfig, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + const globalConfigSchema = z.object({ + 'input-parameter': z.string().min(1), + exponent: z.number(), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); + + return input; + }; + + /** + * Calculate the input param raised by to the power of the given exponent. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => { + const { + 'input-parameter': inputParameter, + exponent, + 'output-parameter': outputParameter, + } = validateGlobalConfig(); + + return inputs.map(input => { + validateSingleInput(input, inputParameter); + + return { + ...input, + [outputParameter]: calculateExponent(input, inputParameter, exponent), + }; + }); + }; + + /** + * Calculates the input param raised by the power of a given exponent. + */ + const calculateExponent = ( + input: PluginParams, + inputParameter: string, + exponent: number + ) => { + const base = input[inputParameter]; + + return Math.pow(base, exponent); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/export-csv-raw.ts b/src/if-run/builtins/export-csv-raw.ts new file mode 100644 index 000000000..1dc637587 --- /dev/null +++ b/src/if-run/builtins/export-csv-raw.ts @@ -0,0 +1,156 @@ +import * as fs from 'fs/promises'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../config'; + +import {Context} from '../../common/types/manifest'; + +const {ExhaustOutputArgError, WriteFileError} = ERRORS; +const {OUTPUT_REQUIRED, WRITE_CSV_ERROR, EXPORTING_RAW_CSV_FILE} = STRINGS; + +export const ExportCSVRaw = () => { + /** + * handle a tree leaf, where there are no child nodes, by adding it as key->value pair to the flat map + * and capturing key as a header + */ + const handleLeafValue = ( + value: any, + fullPath: string, + key: any, + flatMap: {[key: string]: any}, + headers: Set + ) => { + if (fullPath.includes('outputs')) { + headers.add(key); + flatMap[fullPath] = value; + } + }; + + /** + * handle a tree node, recursively traverse the children and append their results to the flat map and captured headers + */ + const handleNodeValue = ( + value: any, + fullPath: string, + flatMap: Record, + headers: Set + ) => { + const [subFlatMap, subHeaders] = extractFlatMapAndHeaders(value, fullPath); + + if (Object.keys(subFlatMap).length > 0) { + Object.entries(subFlatMap).forEach(([subKey, value]) => { + flatMap[subKey] = value; + }); + + subHeaders.forEach(subHeader => { + headers.add(subHeader); + }); + } + }; + + /** + * Handles a key at the top level of the tree + */ + const handleKey = ( + value: any, + key: any, + prefix: string, + flatMap: Record, + headers: Set + ) => { + const fullPath = prefix ? `${prefix}.${key}` : key; + + if (value !== null && typeof value === 'object') { + return handleNodeValue(value, fullPath, flatMap, headers); + } + + return handleLeafValue(value, fullPath, key, flatMap, headers); + }; + + /** + * Recursively extract a flat map and headers from the hierarcial tree. + */ + const extractFlatMapAndHeaders = ( + tree: any, + prefix = '' + ): [Record, Set] => { + const headers: Set = new Set(); + const flatMap: Record = []; + + for (const key in tree) { + if (key in tree) { + handleKey(tree[key], key, prefix, flatMap, headers); + } + } + + return [flatMap, headers]; + }; + + /** + * extract the id of the key, that is removing the last token (which is the index). + * in this manner, multiple keys that identical besides their index share the same id. + */ + const extractIdHelper = (key: string): string => { + const parts = key.split('.'); + parts.pop(); + + return parts.join('.'); + }; + + /** + * generate a CSV formatted string based on a flat key->value map, headers and ids + */ + const getCsvString = ( + map: {[key: string]: any}, + headers: Set, + ids: Set + ): string => { + const csvRows: string[] = []; + csvRows.push(['id', ...headers].join(',')); + + ids.forEach(id => { + const rowData = [id]; + + headers.forEach(header => { + const value = map[`${id}.${header}`] ?? ''; + rowData.push(value.toString()); + }); + csvRows.push(rowData.join(',')); + }); + + return csvRows.join('\n'); + }; + + /** + * write the given string content to a file at the provided path + */ + const writeOutputFile = async (content: string, outputPath: string) => { + try { + await fs.writeFile(`${outputPath}.csv`, content); + } catch (error) { + throw new WriteFileError(WRITE_CSV_ERROR(outputPath, error)); + } + }; + + /** + * export the provided tree content to a CSV file, represented in a flat structure + */ + const execute = async (tree: any, _context: Context, outputPath: string) => { + if (!outputPath) { + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); + } + + console.debug(EXPORTING_RAW_CSV_FILE(outputPath)); + + const [extractredFlatMap, extractedHeaders] = + extractFlatMapAndHeaders(tree); + const ids = new Set( + Object.keys(extractredFlatMap).map(key => extractIdHelper(key)) + ); + const csvString = getCsvString(extractredFlatMap, extractedHeaders, ids); + + await writeOutputFile(csvString, outputPath); + }; + + return {execute}; +}; diff --git a/src/if-run/builtins/export-csv.ts b/src/if-run/builtins/export-csv.ts new file mode 100644 index 000000000..112061e31 --- /dev/null +++ b/src/if-run/builtins/export-csv.ts @@ -0,0 +1,117 @@ +import {writeFile} from 'fs/promises'; + +import {stringify} from 'csv-stringify/sync'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {STRINGS} from '../config'; + +import {Context} from '../../common/types/manifest'; + +const {ExhaustOutputArgError} = ERRORS; +const {CSV_EXPORT, OUTPUT_REQUIRED, EXPORTING_TO_CSV_FILE} = STRINGS; + +/** + * Extension to IF that outputs the tree in a CSV format. + */ +export const ExportCSV = () => { + const parseOutputAndField = (outputPath: string) => { + const validatedPath = validateOutputPath(outputPath); + + const paths = validatedPath.split('#'); + const criteria = paths[paths.length - 1]; + + if (paths.length <= 1 || !criteria) { + throw new ExhaustOutputArgError(CSV_EXPORT); + } + + const output = paths.slice(0, paths.length - 1).join(''); + console.debug(EXPORTING_TO_CSV_FILE(output)); + + return { + output, + criteria, + }; + }; + + /** + * Validates output path. + */ + const validateOutputPath = (outputPath: string) => { + if (!outputPath) { + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); + } + + return outputPath; + }; + + /** + * Grabs output and criteria from cli args, then call tree walker to collect csv data. + */ + const execute = async (tree: any, context: Context, outputPath: string) => { + const columns = ['Path']; + const matrix = [columns]; + const {output, criteria} = parseOutputAndField(outputPath); + const aggregationIsEnabled = !!context.aggregation; + + /** + * Walks through all tree branches and leaves, collecting the data + */ + const treeWalker = (node: any, criteria: string, path = 'tree') => { + /** Hmm aggregated, then checks if it's the first one. If so adds column, pushes the value. */ + if (node.aggregated) { + if (path === 'tree') { + columns.push('Aggregated'); + } + + matrix.push([`${path}.${criteria}`, node.aggregated[criteria]]); + } + + /** So it has outputs, whats then? checks if timestamp is not there, adds one. Then appends values to it. */ + if (node.outputs) { + node.outputs.forEach((output: PluginParams) => { + const {timestamp} = output; + + if (!columns.includes(timestamp)) { + columns.push(output.timestamp); + } + + const lastRow = matrix[matrix.length - 1]; + + if (aggregationIsEnabled) { + lastRow.push(output[criteria]); + } else { + /** Handle without aggregation export strategy. */ + if (matrix.length === 1 || lastRow.length === columns.length) { + matrix.push([`${path}.${criteria}`, output[criteria]]); + } else { + lastRow.push(output[criteria]); + } + } + }); + } + + /** Ohh children? then call every one and execute. */ + if (node.children) { + for (const child in node.children) { + treeWalker( + node.children[child], + criteria, + `${path}.children.${child}` + ); + } + } + }; + + treeWalker(tree, criteria); + + await writeFile(`${output}.csv`, stringify(matrix, {columns})); + }; + + return { + execute, + metadata: { + kind: 'exhaust', + }, + }; +}; diff --git a/src/if-run/builtins/export-log.ts b/src/if-run/builtins/export-log.ts new file mode 100644 index 000000000..0f1dad33a --- /dev/null +++ b/src/if-run/builtins/export-log.ts @@ -0,0 +1,21 @@ +import * as YAML from 'js-yaml'; + +import {Context} from '../../common/types/manifest'; + +export const ExportLog = () => { + /** + * Logs output manifest in console. + */ + const execute = async (tree: any, context: Context) => { + const outputFile = { + ...context, + tree, + }; + + console.log(`# start +${YAML.dump(outputFile, {noRefs: true})} +# end`); + }; + + return {execute}; +}; diff --git a/src/if-run/builtins/export-yaml.ts b/src/if-run/builtins/export-yaml.ts new file mode 100644 index 000000000..456ca6aa6 --- /dev/null +++ b/src/if-run/builtins/export-yaml.ts @@ -0,0 +1,36 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {saveYamlFileAs} from '../../common/util/yaml'; + +import {STRINGS} from '../config'; + +import {Context} from '../../common/types/manifest'; + +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED, EXPORTING_TO_YAML_FILE} = STRINGS; + +export const ExportYaml = () => { + /** Takes string before hashtag. */ + const stripHashtag = (path: string) => path.split('#')[0]; + + /** + * Saves output file in YAML format. + */ + const execute = async (tree: any, context: Context, outputPath: string) => { + if (!outputPath) { + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); + } + + const outputFile = { + ...context, + tree, + }; + const path = stripHashtag(outputPath); + + console.debug(EXPORTING_TO_YAML_FILE(path)); + + await saveYamlFileAs(outputFile, `${path}.yaml`); + }; + + return {execute}; +}; diff --git a/src/if-run/builtins/group-by.ts b/src/if-run/builtins/group-by.ts new file mode 100644 index 000000000..c8694d4cc --- /dev/null +++ b/src/if-run/builtins/group-by.ts @@ -0,0 +1,95 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + GroupByPlugin, + PluginParams, + GroupByConfig, +} from '@grnsft/if-core/types'; + +import {STRINGS} from '../config'; + +import {validate} from '../../common/util/validations'; + +const {InvalidGroupingError, GlobalConfigError} = ERRORS; + +const {INVALID_GROUP_BY, MISSING_GLOBAL_CONFIG} = STRINGS; + +/** + * Plugin for inputs grouping. + */ +export const GroupBy = (): GroupByPlugin => { + const metadata = { + kind: 'groupby', + }; + + /** + * Creates structure to insert inputs by groups. + */ + const appendGroup = ( + value: PluginParams, + object: any, + groups: string[] + ): any => { + if (groups.length > 0) { + const group = groups.shift() as string; + + object.children = object.children ?? {}; + object.children[group] = object.children[group] ?? {}; + + if (groups.length === 0) { + if ( + object.children[group].inputs && + object.children[group].inputs.length > 0 + ) { + object.children[group].inputs.push(value); + } else { + object.children[group].inputs = [value]; + } + } + + appendGroup(value, object.children[group], groups); + } + + return object; + }; + + /** + * Interates over inputs, grabs config-group types values for each one. + * Based on grouping types, initializes the structure grouped structure. + */ + const execute = (inputs: PluginParams[], config: GroupByConfig) => + inputs.reduce((acc, input) => { + const validatedConfig = validateConfig(config); + const groups = validatedConfig.group.map(groupType => { + if (!input[groupType]) { + throw new InvalidGroupingError(INVALID_GROUP_BY(groupType)); + } + + return input[groupType]; + }); + + acc = { + ...acc, + ...appendGroup(input, acc, groups), + }; + + return acc; + }, {} as any).children; + + /** + * Validates config parameter. + */ + const validateConfig = (config: GroupByConfig) => { + if (!config) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const schema = z.object({ + group: z.array(z.string()).min(1), + }); + + return validate>(schema, config); + }; + + return {metadata, execute}; +}; diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts new file mode 100644 index 000000000..d22491aca --- /dev/null +++ b/src/if-run/builtins/index.ts @@ -0,0 +1,16 @@ +export {GroupBy} from './group-by'; +export {TimeSync} from './time-sync'; +export {Interpolation} from './interpolation'; +export {MockObservations} from './mock-observations'; +export {Divide} from './divide'; +export {Subtract} from './subtract'; +export {Coefficient} from './coefficient'; +export {Multiply} from './multiply'; +export {Sum} from './sum'; +export {SciEmbodied} from './sci-embodied'; +export {Sci} from './sci'; +export {Exponent} from './exponent'; +export {CSVLookup} from './csv-lookup'; +export {Shell} from './shell'; +export {Regex} from './regex'; +export {Copy} from './copy-param'; diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md new file mode 100644 index 000000000..498c26c6e --- /dev/null +++ b/src/if-run/builtins/interpolation/README.md @@ -0,0 +1,196 @@ +# Interpolation Plugin + +## Overview + +Interpolation is a way to infer new data points from a previously known set of points. +This plugin provides the `y` value at a given `x` by interpolating between known points. You provide a set of known `x`s and `y`s and a target `x`, the plugin returns the `y` for your `x`. + +## Usage + +To employ the `Interpolation` plugin, adhere to these steps: + +1. **Initialize Plugin**: Import the `Interpolation` function and initialize it with global configuration parameters `method`, `x`, `y`, `input-parameter` and `output-parameter`. + +2. **Execute Plugin**: Invoke the `execute` method of the initialized plugin instance with an array of input parameters. Each input parameter should include a `timestamp`, `duration` and `[input-parameter]` information. + +3. **Result**: The plugin will return an array of plugin parameters enriched with the calculated average carbon intensity for each input. + +## Global Config + +- `method`: specifies the interpolation method for the data. Acceptable values are 'linear', 'spline', or 'polynomial'. The default method is linear. (optional) +- `x`: array of x points. Numbers should be in ascending order (required). +- `y`: array of y points. Numbers should be in ascending order (required). +- `input-parameter`: a string defining the name to use its value to calculate the interpolation. It should match an existing key in the inputs array (required). +- `output-parameter`: a string defining the name to use to add the result of interpolation with additional calculation (required). + +`x` and `y` arrays must be equal lengths. + +## Input Parameters + +The plugin expects the following input parameters: + +- `timestamp`: a timestamp for the input (required) +- `duration`: the amount of time, in seconds, that the input covers. (required) +- `[input-parameter]` - a field whose name matches the string provided to input-parameter in global config (i.e. if the input-parameter in global config is cpu/utilisation then cpu-utilisation must exist in the input data) + +## Output + +The plugin outputs a value `z` that is the result of looking up the `y` value at `x = 'input-parameter'` using the user-defined interpolation method in `kWh` units. `z` is assigned to a field with a name defined by `output-parameter` in the output data. + +## Error Handling + +The plugin conducts input validation using the `zod` library and may throw errors if the provided parameters are invalid. + +## Plugin Algorithm + +1. **Execution**: + + - Validate Global config + + - `method` - validates if the method is one of these methods: `linear`, `spline`, or `polynomial`. If the method isn’t provided, it sets to `linear`. + - `x` and `y` should be arrays of numbers, the length should be equal, and elements should be ordered in the ascendant order. + - `input-parameter` - validates if the parameter is string. + - `output-parameter` - validates if the parameter is string. + + - Iterate through each input, and do corresponding validation and calculation. + + - Validate input parameters + + - `duration` - validate if the duration is a number + - `timestamp` - should be in string or date format + - `[input-parameter]` - validates whether the parameter name is included in the input, and if its value should be a number within the range of x points. + + - Calculation + + - If the `method` is provided, choose the right way to calculate. For the `linear` and `polynomial` methods, calculate according to their formulas. For spline interpolation, use the npm module `typescript-cubic-spline`. + +2. **Output**: Output the provided input along with the calculated `cpu/energy` + +### 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 interpolationPlugin = Interpolation(globalConfig); + +const inputs = [ + { + timestamp: '2024-04-16T12:00:00Z', + duration: 3600, + 'cpu/utilization': 45 + }, +]; + +const results = interpolationPlugin.execute(inputs); + +console.log(results); +``` + +### Manifest Usage + +#### Input + +```yaml +name: interpolation-demo +description: simple demo of interpolation plugin +tags: +initialize: + outputs: + - yaml + 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: 'cpu/energy' +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 +``` + +#### Output + +```yaml +name: interpolation-demo +description: simple demo of interpolation plugin +tags: +initialize: + outputs: + - yaml + 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: 'cpu/energy' +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + cpu/energy: 0.00069625 +``` + +You can execute this by passing it to `ie`. Run the impact using the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml +``` + +## Errors + +`Interpolation` exposes one of IF's error classes. + +## `GlobalConfigError` + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `method`: a string containing either `linear`, `spline` or `polynomial` +- `x`: an array of numbers +- `y`: an array of numbers +- `input-parameter`: a string containing the name of a value present in the `inputs` array' +- `output-parameter`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### Validation errors + +There are also several validation errors that can arise, including: +- if the lengths of `x` and `y` are not equal +- if `x` or `y` are empty +- if the requested point to interpolate at is outside the range of `x` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts new file mode 100644 index 000000000..03239a004 --- /dev/null +++ b/src/if-run/builtins/interpolation/index.ts @@ -0,0 +1,197 @@ +import Spline from 'typescript-cubic-spline'; +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + Method, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + X_Y_EQUAL, + ARRAY_LENGTH_NON_EMPTY, + WITHIN_THE_RANGE, +} = STRINGS; + +export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { + /** + * Executes the energy consumption calculation for an array of input parameters. + */ + const execute = (inputs: PluginParams[]) => { + const validatedConfig = validateConfig(); + + return inputs.map((input, index) => { + const safeInput = validateInput(input, index); + const result = calculateResult(validatedConfig, safeInput); + + return { + ...input, + [validatedConfig['output-parameter']]: result, + }; + }); + }; + + /** + * Calculates the appropriate interpolation value based on the specified method type in the config and input parameters. + */ + const calculateResult = (config: ConfigParams, input: PluginParams) => { + const methodType: {[key: string]: number} = { + linear: getLinearInterpolation(config, input), + spline: getSplineInterpolation(config, input), + polynomial: getPolynomialInterpolation(config, input), + }; + + return methodType[config.method]; + }; + + /** + * Calculates the interpolation when the method is linear. + */ + const getLinearInterpolation = ( + config: ConfigParams, + input: PluginParams + ) => { + const parameter = input[globalConfig['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + + const result = xPoints.reduce( + (acc, xPoint, i) => { + if (parameter === xPoint) { + acc.baseCpu = xPoint; + acc.baseRate = yPoints[i]; + } else if (parameter > xPoint && parameter < xPoints[i + 1]) { + acc.baseCpu = xPoint; + acc.baseRate = yPoints[i]; + acc.ratio = (yPoints[i + 1] - yPoints[i]) / (xPoints[i + 1] - xPoint); + } + + return acc; + }, + {baseRate: 0, baseCpu: 0, ratio: 0} + ); + + return result.baseRate + (parameter - result.baseCpu) * result.ratio; + }; + + /** + * Calculates the interpolation when the method is spline. + */ + const getSplineInterpolation = ( + config: ConfigParams, + input: PluginParams + ) => { + const parameter = input[globalConfig['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + const spline: any = new Spline(xPoints, yPoints); + + return spline.at(parameter); + }; + + /** + * Calculates the interpolation when the method is polynomial. + */ + const getPolynomialInterpolation = ( + config: ConfigParams, + input: PluginParams + ) => { + const parameter = input[globalConfig['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + + const result = xPoints.reduce((acc, x, i) => { + const term = + yPoints[i] * + xPoints.reduce((prod, xPoint, j) => { + if (j !== i) { + return (prod * (parameter - xPoint)) / (x - xPoint); + } + return prod; + }, 1); + return acc + term; + }, 0); + + return result; + }; + + /** + * Validates global config parameters. + * Sorts elements of `x` and `y`. + */ + const validateConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const schema = z + .object({ + method: z.nativeEnum(Method), + x: z.array(z.number()), + y: z.array(z.number()), + 'input-parameter': z.string(), + 'output-parameter': z.string(), + }) + .refine(data => data.x && data.y && data.x.length === data.y.length, { + message: X_Y_EQUAL, + }) + .refine(data => data.x.length > 1 && data.y.length > 1, { + message: ARRAY_LENGTH_NON_EMPTY, + }); + + const defaultMethod = globalConfig.method ?? Method.LINEAR; + const updatedConfig = Object.assign( + {}, + {method: defaultMethod}, + globalConfig, + { + x: sortPoints(globalConfig.x), + y: sortPoints(globalConfig.y), + } + ); + + return validate>(schema, updatedConfig); + }; + + const sortPoints = (items: number[]) => + items.sort((a: number, b: number) => { + return a - b; + }); + + /** + * Validates inputes parameters. + */ + const validateInput = (input: PluginParams, index: number) => { + const inputParameter = globalConfig['input-parameter']; + const schema = z + .object({ + timestamp: z.string().or(z.date()), + duration: z.number(), + [inputParameter]: z.number().gt(0), + }) + .refine( + data => + data[inputParameter] >= globalConfig.x[0] && + data[inputParameter] <= globalConfig.x[globalConfig.x.length - 1], + { + message: WITHIN_THE_RANGE, + } + ); + + return validate>(schema, input, index); + }; + + return { + metadata: { + kind: 'execute', + }, + execute, + }; +}; diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md new file mode 100644 index 000000000..1af4cd6d6 --- /dev/null +++ b/src/if-run/builtins/mock-observations/README.md @@ -0,0 +1,97 @@ +# Mock Observations Plugin + +## Introduction + +A plugin for mocking observations (inputs) for testing and demo purposes + +## Scope + +The mode currently mocks 2 types of observation data: + +- Common key-value pairs, that are generated statically and are the same for each generated observation/input (see 'helpers/CommonGenerator.ts') +- Randomly generated integer values for predefined keys (see 'helpers/RandIntGenerator.ts') + +### Plugin global config + +- `timestamp-from`, `timestamp-to` and `duration` define time buckets for which to generate observations. +- `generators` define which fields to generate for each observation +- `components` define the components for which to generate observations. The observations generated according to `timestamp-from`, `timestamp-to`, `duration` and `generators` will be duplicated for each component. + +### Authentication + +N/A + +### Inputs + +The plugin's `global-config` section in the manifest file determines its behaviour. +'inputs' section is ignored. + +### 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 result = await mockObservations.execute([]); +``` + +### manifest Example + +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 `mock-observation`: + +```yaml +name: mock-observation-demo +description: example invoking mock-observation plugin +tags: +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: 'builtin' + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - instance-type: A1 + - instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +tree: + children: + child: + pipeline: + - mock-observations + inputs: +``` + +You can run this example `manifest` by saving it as `manifests/plugins/mock-observation.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation +``` + +The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/if-run/builtins/mock-observations/helpers/common-generator.ts b/src/if-run/builtins/mock-observations/helpers/common-generator.ts new file mode 100644 index 000000000..8283cf1bd --- /dev/null +++ b/src/if-run/builtins/mock-observations/helpers/common-generator.ts @@ -0,0 +1,33 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {ConfigParams} from '@grnsft/if-core/types'; + +import {STRINGS} from '../../../config'; + +import {Generator} from '../interfaces'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +export const CommonGenerator = (config: ConfigParams): Generator => { + /** + * Generates next value by copying the validated config. + * Validates the provided config is not null or empty. + * Returns a copy of the validated config, otherwise throws an GlobalConfigError. + */ + const validateConfig = (config: object) => { + if (!config || Object.keys(config).length === 0) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + return structuredClone(config); + }; + + /** + * Generates next value by copying the validated config. + */ + const next = (): Object => validateConfig(config); + + return { + next, + }; +}; diff --git a/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts new file mode 100644 index 000000000..1cb4d161f --- /dev/null +++ b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts @@ -0,0 +1,68 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {RandIntGeneratorParams, ConfigParams} from '@grnsft/if-core/types'; + +import {STRINGS} from '../../../config'; + +import {Generator} from '../interfaces'; + +const {GlobalConfigError} = ERRORS; + +const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = + STRINGS; + +export const RandIntGenerator = ( + name: string, + config: ConfigParams +): Generator => { + const next = () => ({ + [validatedName]: generateRandInt(getFieldToPopulate()), + }); + + const validateName = (name: string | null): string => { + if (!name || name.trim() === '') { + throw new GlobalConfigError(INVALID_NAME); + } + + return name; + }; + + const validateConfig = (config: ConfigParams): {min: number; max: number} => { + if (!config || Object.keys(config).length === 0) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + if (!config.min || !config.max) { + throw new GlobalConfigError(MISSING_MIN_MAX); + } + + if (config.min >= config.max) { + throw new GlobalConfigError(INVALID_MIN_MAX(validatedName)); + } + + return {min: config.min, max: config.max}; + }; + + const validatedName = validateName(name); + const validatedConfig = validateConfig(config); + + const getFieldToPopulate = () => ({ + name: validatedName, + min: validatedConfig.min, + max: validatedConfig.max, + }); + + const generateRandInt = ( + randIntGenerator: RandIntGeneratorParams + ): number => { + const randomNumber = Math.random(); + const scaledNumber = + randomNumber * (randIntGenerator.max - randIntGenerator.min) + + randIntGenerator.min; + + return Math.trunc(scaledNumber); + }; + + return { + next, + }; +}; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts new file mode 100644 index 000000000..d947e7d7c --- /dev/null +++ b/src/if-run/builtins/mock-observations/index.ts @@ -0,0 +1,178 @@ +import {DateTime, Duration} from 'luxon'; +import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + ObservationParams, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {CommonGenerator} from './helpers/common-generator'; +import {RandIntGenerator} from './helpers/rand-int-generator'; + +import {Generator} from './interfaces/index'; + +export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Generate sets of mocked observations based on config. + */ + const execute = (inputs: PluginParams[]) => { + const {duration, timeBuckets, components, generators} = + generateParamsFromConfig(); + const generatorToHistory = new Map(); + + generators.forEach(generator => { + generatorToHistory.set(generator, []); + }); + + 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)); + }); + + return acc; + }, []); + }; + + /** + * Validates global config parameters. + */ + const validateGlobalConfig = () => { + const schema = z.object({ + 'timestamp-from': z.string(), + 'timestamp-to': z.string(), + duration: z.number(), + components: z.array(z.record(z.string())), + generators: z.object({ + common: z.record(z.string().or(z.number())), + randint: z.record(z.object({min: z.number(), max: z.number()})), + }), + }); + + return validate>(schema, globalConfig); + }; + + /** + * Configures the MockObservations Plugin for IF + */ + const generateParamsFromConfig = () => { + const { + 'timestamp-from': timestampFrom, + 'timestamp-to': timestampTo, + duration, + generators, + components, + } = validateGlobalConfig(); + const convertedTimestampFrom = DateTime.fromISO(timestampFrom, { + zone: 'UTC', + }); + const convertedTimestampTo = DateTime.fromISO(timestampTo, {zone: 'UTC'}); + + return { + duration, + timeBuckets: createTimeBuckets( + convertedTimestampFrom, + convertedTimestampTo, + duration + ), + generators: createGenerators(generators), + components, + }; + }; + + /* + * create time buckets based on start time, end time and duration of each bucket. + */ + const createTimeBuckets = ( + timestampFrom: DateTime, + timestampTo: DateTime, + duration: number, + timeBuckets: DateTime[] = [] + ): DateTime[] => { + if ( + timestampFrom < timestampTo || + timestampFrom.plus(Duration.fromObject({seconds: duration})) < timestampTo + ) { + return createTimeBuckets( + timestampFrom.plus(Duration.fromObject({seconds: duration})), + timestampTo, + duration, + [...timeBuckets, timestampFrom] + ); + } + return timeBuckets; + }; + + /* + * create generators based on a given config + */ + const createGenerators = (generatorsConfig: object): Generator[] => { + const createCommonGenerator = (config: any): Generator[] => [ + CommonGenerator(config), + ]; + + const createRandIntGenerators = (config: any): Generator[] => + Object.entries(config).map(([fieldToPopulate, value]) => + RandIntGenerator(fieldToPopulate, value as Record) + ); + + return Object.entries(generatorsConfig).flatMap(([key, value]) => + key === 'randint' + ? createRandIntGenerators(value).flat() + : createCommonGenerator(value) + ); + }; + + /* + * Creates time buckets based on start time, end time and duration of each bucket. + */ + const createObservation = ( + observationParams: ObservationParams, + generatorToHistory: Map + ): PluginParams => { + const {duration, component, timeBucket, generators} = observationParams; + const timestamp = timeBucket.toISO(); + + const generateObservation = (generator: Generator) => { + const history = generatorToHistory.get(generator) || []; + const generated: Record = generator.next(history); + + generatorToHistory.set(generator, [...history, generated.value]); + + return generated; + }; + + const generateObservations = (gen: Generator) => generateObservation(gen); + const generatedValues = generators.map(generateObservations); + const initialObservation: PluginParams = { + timestamp, + duration, + ...component, + }; + const generatedObservation = generatedValues.reduce( + (observation, generated) => Object.assign(observation, generated), + initialObservation + ); + + return generatedObservation as PluginParams; + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/mock-observations/interfaces/index.ts b/src/if-run/builtins/mock-observations/interfaces/index.ts new file mode 100644 index 000000000..4efae5f59 --- /dev/null +++ b/src/if-run/builtins/mock-observations/interfaces/index.ts @@ -0,0 +1,6 @@ +export type Generator = { + /** + * generate the next value, optionally based on historical values + */ + next: (historical: Object[] | undefined) => Object; +}; diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md new file mode 100644 index 000000000..7e9c2dfbd --- /dev/null +++ b/src/if-run/builtins/multiply/README.md @@ -0,0 +1,109 @@ +# Multiply + +`multiply` is a generic plugin for multiplying two or more values in an `input` array. + +You provide the names of the values you want to multiply, and a name to use to append the product to the output array. + +For example, you could multiply `cpu/energy` and `network/energy` and name the result `energy-product`. `energy-product` would then be added to every observation in your input array as the product of `cpu/energy` and `network/energy`. + +## Parameters + +### Plugin config + +Two parameters are required in global config: `input-parameters` and `output-parameter`. + +`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array +`output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. + +### Inputs + +All of `input-parameters` must be available in the input array. + +## Returns + +- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input0 * input1 * input2 ... inputN +``` + +## Implementation + +To run the plugin, you must first create an instance of `Multiply`. Then, you can call `execute()`. + +```typescript +import {Multiply} from 'builtins'; + +const config = { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'energy-product', +}; + +const mult = Multiply(config); +const result = await mult.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + 'cpu/energy': 0.001, + 'memory/energy': 0.0005, + }, +]); +``` + +## 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`: + +```yaml +name: multiply-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + multiply: + method: Multiply + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy-product' +tree: + children: + child: + pipeline: + - multiply + config: + multiply: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 +``` + +You can run this example by saving it as `./examples/manifests/test/multiply.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Multiply` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts new file mode 100644 index 000000000..706e190ec --- /dev/null +++ b/src/if-run/builtins/multiply/index.ts @@ -0,0 +1,84 @@ +import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + MultiplyConfig, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + const globalConfigSchema = z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.number()); + + validate(validationSchema, inputData); + + return input; + }; + + /** + * Calculate the product of each input parameter. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => { + const safeGlobalConfig = validateGlobalConfig(); + const inputParameters = safeGlobalConfig['input-parameters']; + const outputParameter = safeGlobalConfig['output-parameter']; + + return inputs.map(input => { + validateSingleInput(input, inputParameters); + + return { + ...input, + [outputParameter]: calculateProduct(input, inputParameters), + }; + }); + }; + + /** + * Calculates the product of the components. + */ + const calculateProduct = (input: PluginParams, inputParameters: string[]) => + inputParameters.reduce( + (accumulator, metricToMultiply) => accumulator * input[metricToMultiply], + 1 + ); + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md new file mode 100644 index 000000000..a0fa5d624 --- /dev/null +++ b/src/if-run/builtins/regex/README.md @@ -0,0 +1,121 @@ +# Regex + +`regex` is a generic plugin to match part of one string in an `input` and extract it into an output. + +You provide the name of the value you want to match, and a name to use to add the regex to the output array. + +``` +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 +``` + +## Parameters + +### Plugin config + +- `parameter` - a parameter by a specific configured string +- `match` - a regex by which needs to match the `parameter` +- `output` - output parameter name in the input + +### Inputs + +- `parameter` - as input parameter, must be available in the input array + +## Returns + +- `output`: the first match of `parameter` with the parameter name with `match` defined in global config. + +## 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 regex = Regex(globalConfig); + +const input = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': + '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', + }, +]; +``` + +## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `regex`: + +```yaml +name: regex-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + regex: + method: Regex + path: 'builtin' + global-config: + parameter: physical-processor + match: ^[^,]+ + output: cpu/name +tree: + children: + child: + pipeline: + - regex + config: + regex: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: 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 +``` + +You can run this example by saving it as `manifests/plugins/regex.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if --manifest manifests/examples/regex.yml --output manifests/outputs/regex.yml +``` + +The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Regex` uses three of IF's error classes: + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `parameter` + + +### `GlobalConfigError` + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: + +- `parameter`: a string containing the name of a value in the inputs array +- `match`: a valid regex pattern +- `output`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + + +### `RegexMismatchError` + +This error arises when the requested regex cannot find any matches in the given data. If there are multiple matches, the plugin returns the first, but if there are none, it throws this error. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts new file mode 100644 index 000000000..45c65d6f6 --- /dev/null +++ b/src/if-run/builtins/regex/index.ts @@ -0,0 +1,96 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; + +export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const schema = z.object({ + parameter: z.string().min(1), + match: z.string().min(1), + output: z.string(), + }); + + return validate>(schema, globalConfig); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, parameter: string) => { + if (!input[parameter]) { + throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); + } + + return input; + }; + + /** + * Executes the regex of the given parameter. + */ + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const {parameter: parameter, match, output} = safeGlobalConfig; + + return inputs.map(input => { + const safeInput = Object.assign( + {}, + input, + validateSingleInput(input, parameter) + ); + + return { + ...input, + [output]: extractMatching(safeInput, parameter, match), + }; + }); + }; + + /** + * Extracts a substring from the given input parameter that matches the provided regular expression pattern. + */ + const extractMatching = ( + input: PluginParams, + parameter: string, + match: string + ) => { + if (!match.startsWith('/')) { + match = '/' + match; + } + + if (!match.endsWith('/g') && !match.endsWith('/')) { + match += '/'; + } + + const regex = eval(match); + const matchedItem = input[parameter].match(regex); + + if (!matchedItem || !matchedItem[0]) { + throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); + } + + return matchedItem[0]; + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md new file mode 100644 index 000000000..97b6ce4af --- /dev/null +++ b/src/if-run/builtins/sci-embodied/README.md @@ -0,0 +1,124 @@ +# SCI-Embodied + +Software systems cause emissions through the hardware that they operate on, both through the energy that the physical hardware consumes and the emissions associated with manufacturing the hardware. Embodied carbon refers to the carbon emitted during the manufacture and eventual disposal of a component. It is added to the operational carbon (carbon emitted when a component is used) to give an overall SCI score. + +Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions) + +## Parameters + +### Plugin config + +Not Needed + +### Inputs + +- `device/emissions-embodied`: the sum of Life Cycle Assessment (LCA) emissions for the component +- `device/expected-lifespan`: the length of time, in seconds, between a component's manufacture and its disposal +- `resources-reserved`: the number of resources reserved for use by the software +- `resources-total`: the total number of resources available +- `duration`: the amount of time covered by an observation, in this context it is used as the share of the total life span of the hardware reserved for use by an application, in seconds. + +> Note that if you have a plugin pipeline that adds `vcpus-allocated` and `vcpus-total` to each observation, such as the `cloud-metadata` plugin, those values will be used **in preference** to the given `resources-reserved` and `resources-total` fields. + +## Returns + +- `carbon-embodied`: the carbon emitted in manufacturing and disposing of a component, in gCO2eq + +## Calculation + +To calculate the embodied carbon, `m` for a software application, use the equation: + +``` +m = te * ts * rs +``` + +Where: + +- `device/emissions-embodied` = Total embodied emissions; the sum of Life Cycle Assessment (LCA) emissions for the component. + +- `timeShare` = Time-share; the share of the total life span of the hardware reserved for use by an application. + + - `timeShare` is calculated as `duration/'device/expected-lifespan'`, where: + - `duration` = the length of time the hardware is reserved for use by the software. + - `device/expected-lifespan` = Expected lifespan: the length of time, in seconds, between a component's manufacture and its disposal. + +- `resourceShare` = Resource-share; the share of the total available resources of the hardware reserved for use by an application. + - `resourceShare` is calculated as `resources-reserved/resources-total`, where: + - `resources-reserved` = Resources reserved; the number of resources reserved for use by the software. + - `resources-total` = Total Resources; the total number of resources available. + +## Implementation + +IF implements the plugin based on the logic described above. To run the plugin, you must first create an instance of `SciEmbodied`. Then, you can call `execute()` to return `m`. + +## Usage + +The following snippet demonstrates how to call the `sci-embodied` plugin from Typescript. + +```typescript +import {SciEmbodied} from 'builtins'; + +const sciEmbodied = SciEmbodied(); +const results = await sciEmbodied.execute([ + { + 'device/emissions-embodied': 200, // in gCO2e for total resource units + duration: 60 * 60 * 24 * 30, // time reserved in seconds, can point to another field "duration" + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, // lifespan in seconds (4 years) + 'resources-reserved': 1, // resource units reserved / used + 'resources-total': 1, // total resource units available + }, +]); +``` + +## 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`: + +```yaml +name: sci-embodied +description: simple demo invoking sci-embodied +tags: +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: 'builtins' +tree: + children: + child: + pipeline: + - sci-embodied # duration & config -> embodied + defaults: + device/emissions-embodied: 1533.120 # gCO2eq + device/expected-lifespan: 3 # 3 years in seconds + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 +``` + +You can run this example `manifest` by executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`SciEmbodied` uses one of IF's error classes + +### `SciEmbodiedError` + +This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. + +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 diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts new file mode 100644 index 000000000..2fffc09ed --- /dev/null +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -0,0 +1,130 @@ +import {z} from 'zod'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; + +import {validate, allDefined} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {SCI_EMBODIED_ERROR} = STRINGS; + +export const SciEmbodied = (): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + const METRICS = [ + 'device/emissions-embodied', + 'device/expected-lifespan', + 'resources-reserved', + 'vcpus-allocated', + 'resources-total', + 'vcpus-total', + ]; + + /** + * Calculate the Embodied carbon for a list of inputs. + */ + const execute = (inputs: PluginParams[]) => + inputs.map(input => { + const safeInput = validateInput(input); + + return { + ...input, + 'carbon-embodied': calculateEmbodiedCarbon(safeInput), + }; + }); + + /** + * Calculate the Embodied carbon for the input. + * M = totalEmissions * (duration/ExpectedLifespan) * (resourcesReserved/totalResources) + */ + const calculateEmbodiedCarbon = (input: PluginParams) => { + const totalEmissions = input['device/emissions-embodied']; + const duration = input['duration']; + const expectedLifespan = input['device/expected-lifespan']; + const resourcesReserved = + input['vcpus-allocated'] || input['resources-reserved']; + const totalResources = input['vcpus-total'] || input['resources-total']; + + return ( + totalEmissions * + (duration / expectedLifespan) * + (resourcesReserved / totalResources) + ); + }; + + /** + * Checks for required fields in input. + */ + const validateInput = (input: PluginParams) => { + const commonSchemaPart = (errorMessage: (unit: string) => string) => ({ + 'device/emissions-embodied': z + .number({ + invalid_type_error: errorMessage('gCO2e'), + }) + .gte(0) + .min(0), + 'device/expected-lifespan': z + .number({ + invalid_type_error: errorMessage('gCO2e'), + }) + .gte(0) + .min(0), + duration: z + .number({ + invalid_type_error: errorMessage('seconds'), + }) + .gte(1), + }); + + const vcpusSchemaPart = { + 'vcpus-allocated': z + .number({ + invalid_type_error: SCI_EMBODIED_ERROR('count'), + }) + .gte(0) + .min(0), + 'vcpus-total': z + .number({ + invalid_type_error: SCI_EMBODIED_ERROR('count'), + }) + .gte(0) + .min(0), + }; + + const resourcesSchemaPart = { + 'resources-reserved': z + .number({ + invalid_type_error: SCI_EMBODIED_ERROR('count'), + }) + .gte(0) + .min(0), + 'resources-total': z + .number({ + invalid_type_error: SCI_EMBODIED_ERROR('count'), + }) + .gte(0) + .min(0), + }; + + const schemaWithVcpus = z.object({ + ...commonSchemaPart(SCI_EMBODIED_ERROR), + ...vcpusSchemaPart, + }); + const schemaWithResources = z.object({ + ...commonSchemaPart(SCI_EMBODIED_ERROR), + ...resourcesSchemaPart, + }); + + const schema = schemaWithVcpus.or(schemaWithResources).refine(allDefined, { + message: `All ${METRICS} should be present.`, + }); + + return validate>(schema, input); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md new file mode 100644 index 000000000..592bd1ed0 --- /dev/null +++ b/src/if-run/builtins/sci/README.md @@ -0,0 +1,112 @@ +# SCI (software carbon intensity) + +[SCI](https://sci-guide.greensoftware.foundation/) represents the amount of carbon emitted per [functional unit](https://sci-guide.greensoftware.foundation/R/). + +## Parameters + +### Plugin global config + +- `functional-unit`: the name of the functional unit in which to express the carbon impact (required) + + +### Inputs + + +- `carbon`: total carbon in gCO2eq (required) +- `functional-unit`: whatever `functional-unit` you define in global config also has to be present in each input, for example if you provide `functional-unit: requests` in global config, `requests` must be present in your input data. + +## Returns + +- `sci`: carbon expressed in terms of the given functional unit + +>Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. + +## Calculation + +SCI is calculated as: + +```pseudocode +sci = carbon / functional unit +``` + + +## IF Implementation + +To run the plugin, you must first create an instance of `Sci`. Then, you can call `execute()` to return `sci`. + +```typescript +import {Sci} from 'builtins'; + +const sci = Sci({'functional-unit': 'requests'}); +const results = await sci.execute( + [ + { + 'carbon': 5' + duration: 1, + requests: 100, + }, + ] +); +``` + +## 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`: + +```yaml +name: sci-demo +description: example invoking sci plugin +tags: +initialize: + outputs: + - yaml + plugins: + sci: + method: Sci + path: 'builtin' + global-config: + functional-unit: 'requests' +tree: + children: + child: + pipeline: + - sci + config: + inputs: + - timestamp: 2023-07-06T00:00 + carbon: 5 + duration: 1 + requests: 100 +``` + +You can run this example `manifest` by saving it as `./manifests/plugins/sci.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml +``` + +The results will be saved to a new `yaml` file. + +## Errors + +`SCI` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. + +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- `carbon`: a numeric value named `carbon` must exist in the inputs array +- whatever value you passed to `functional-unit` + + +### Validation errors + +There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. + +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/config.ts b/src/if-run/builtins/sci/config.ts new file mode 100644 index 000000000..edbf8881e --- /dev/null +++ b/src/if-run/builtins/sci/config.ts @@ -0,0 +1,40 @@ +export const TIME_UNITS_IN_SECONDS: Record = { + s: 1, + second: 1, + sec: 1, + secs: 1, + seconds: 1, + min: 60, + mins: 60, + minute: 60, + minutes: 60, + h: 3600, + hs: 3600, + hr: 3600, + hrs: 3600, + hour: 3600, + hours: 3600, + d: 86400, + ds: 86400, + day: 86400, + days: 86400, + w: 604800, + ws: 604800, + wk: 604800, + wks: 604800, + week: 604800, + weeks: 604800, + m: 2419200, + mnth: 2419200, + mth: 2419200, + mnths: 2419200, + mths: 2419200, + month: 2419200, + months: 2419200, + y: 31536000, + ys: 31536000, + yr: 31536000, + yrs: 31536000, + year: 31536000, + years: 31536000, +}; diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts new file mode 100644 index 000000000..f11f6c2b8 --- /dev/null +++ b/src/if-run/builtins/sci/index.ts @@ -0,0 +1,91 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; + +import {validate, allDefined} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {MissingInputDataError} = ERRORS; +const { + MISSING_FUNCTIONAL_UNIT_CONFIG, + MISSING_FUNCTIONAL_UNIT_INPUT, + SCI_MISSING_FN_UNIT, + ZERO_DIVISION, +} = STRINGS; + +export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Validates node and gloabl configs. + */ + const validateConfig = (config?: ConfigParams) => { + const schema = z + .object({ + 'functional-unit': z.string(), + }) + .refine(data => data['functional-unit'], { + message: MISSING_FUNCTIONAL_UNIT_CONFIG, + }); + + return validate>(schema, config); + }; + + /** + * Calculate the total emissions for a list of inputs. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => + inputs.map((input, index) => { + const safeInput = validateInput(input); + const functionalUnit = input[globalConfig['functional-unit']]; + + if (functionalUnit === 0) { + console.warn(ZERO_DIVISION(Sci.name, index)); + + return { + ...input, + sci: safeInput['carbon'], + }; + } + + return { + ...input, + sci: safeInput['carbon'] / functionalUnit, + }; + }); + + /** + * Checks for fields in input. + */ + const validateInput = (input: PluginParams) => { + const validatedConfig = validateConfig(globalConfig); + + if ( + !( + validatedConfig['functional-unit'] in input && + input[validatedConfig['functional-unit']] >= 0 + ) + ) { + throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); + } + + const schema = z + .object({ + carbon: z.number().gte(0), + duration: z.number().gte(1), + }) + .refine(allDefined, { + message: SCI_MISSING_FN_UNIT(globalConfig['functional-unit']), + }); + + return validate>(schema, input); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md new file mode 100644 index 000000000..bacba1255 --- /dev/null +++ b/src/if-run/builtins/shell/README.md @@ -0,0 +1,141 @@ +# Shell Plugin + +The `shell` is a wrapper enabling plugins implemented in any other programming language to be executed as a part of IF pipeline. For example, you might have a standalone plugin written in Python. `shell` spawns a subprocess to execute that Python plugin in a dedicated shell and pipes the results back into IF's Typescript process. + +## Parameters + +### Plugin global config + +The plugin should be initialized as follows: + +``` +initialize: + plugins: + shell: + method: Shell + path: 'builtin' + global-config: + command: python3 /usr/local/bin/sampler +``` + +The `shell` plugin interface requires a path to the plugin command. This path is provided in the plugin configuration with the name command. The path should be appended by the execution command, for example, if the executable is a binary, the path would be prepended with `./` on a Linux system. If the plugin is a Python script, you can prepend `python`. + +- `command`: the path to the plugin executable along with the execution command as it would be entered into a shell. + +### Inputs + +The parameters included in the `inputs` field in the `manifest` depend entirely on the plugin itself. A typical plugin might expect the following common data to be provided as `inputs`: + +- `timestamp`: A timestamp for the specific input +- `duration`: The length of time these specific inputs cover + +## 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. + +## Implementation + +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 result = await output.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 0.002, + 'memory/energy': 0.000005, + }, +]); +``` + +## Considerations + +The `shell` is designed to run arbitrary external plugins. This means IF does not necessarily know what calculations are being executed in the external plugin. There is no strict requirement on the return type, as this depends upon the calculations and the position of the external plugin in a plugin pipeline. For example, one external plugin might carry out the entire end-to-end SCI calculation, taking in usage inputs and returning `sci`. In this case, the plugin is expected to return `sci` and it would be the only plugin invoked in the `manifest`. + +However, it is also entirely possible to have external plugins that only deliver some small part of the overall pipeline, and rely on IF other plugins to do the rest. + +Since the design space for external plugins is so large, it is up to external plugin developers to ensure compatibility with IF built-ins. + +## Example manifest + +IF users will typically call the shell plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating and configuring the plugin is handled by and does not have to be done explicitly by the user. The following is an example `manifest` that calls an external plugin via `shell`. It assumes the plugin takes `cpu/energy` and `memory/energy` as inputs and returns `energy`: + +```yaml +name: shell-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + sampler: + method: Shell + path: 'builtin' + global-config: + command: python3 /usr/local/bin/sampler +tree: + children: + child: + pipeline: + - sampler + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 # Secs + cpu/energy: 0.002 + memory/energy: 0.000005 +``` + +In this hypothetical example, the plugin is written in Python and invoked by executing `python3 /usr/local/bin/sampler` in a shell. +The plugin should return an `output` looking as follows: + +```yaml +name: shell-demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + sampler: + method: Shell + path: 'builtin' + global-config: + command: python3 /usr/local/bin/sampler +tree: + children: + child: + pipeline: + - sampler + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 # Secs + cpu/energy: 0.002 + memory/energy: 0.000005 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 1 # Secs + cpu/energy: 0.002 + memory/energy: 0.000005 + energy: 0.02 # added by plugin +``` + +You can run this example `manifest` by saving it as `manifests/plugins/shell.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml +``` + +The results will be saved to a new `yaml` file. + + +## Errors + +`Shell` uses one of the error classes provided by IF + +### `ProcessExecutionError` + +This error is thrown when the program invoked in the spawned shell fails for some reason that is not known to IF. Since the shell executes arbitrary code, it is difficult for IF to provide specific errors - this is delegated to the developers of the executed program. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts new file mode 100644 index 000000000..5fbea5f28 --- /dev/null +++ b/src/if-run/builtins/shell/index.ts @@ -0,0 +1,65 @@ +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 {validate} from '../../../common/util/validations'; + +const {ProcessExecutionError} = ERRORS; + +export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Calculate the total emissions for a list of inputs. + */ + const execute = (inputs: PluginParams[]): any[] => { + const inputWithConfig = Object.assign({}, inputs[0], validateConfig()); + const command = inputWithConfig.command; + const inputAsString: string = dump(inputs, {indent: 2}); + const results = runModelInShell(inputAsString, command); + + return results?.outputs?.flat(); + }; + + /** + * Checks for required fields in input. + */ + const validateConfig = () => { + const schema = z.object({ + command: z.string(), + }); + + return validate>(schema, globalConfig); + }; + + /** + * Runs the model in a shell. Spawns a child process to run an external IMP, + * an executable with a CLI exposing two methods: `--execute` and `--manifest`. + * The shell command then calls the `--command` method passing var manifest as the path to the desired manifest file. + */ + const runModelInShell = (input: string, command: string) => { + try { + const [executable, ...args] = command.split(' '); + + const result: SpawnSyncReturns = spawnSync(executable, args, { + input, + encoding: 'utf8', + }); + const outputs = loadAll(result.stdout); + + return {outputs}; + } catch (error: any) { + throw new ProcessExecutionError(error.message); + } + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md new file mode 100644 index 000000000..8ff9a922f --- /dev/null +++ b/src/if-run/builtins/subtract/README.md @@ -0,0 +1,105 @@ +# Subtract + +`subtract` is a generic plugin for doing arithmetic subtractions of two or more values in an `input` array. + +You provide the names of the values you want to subtract, and a name to use to add the subtraction to the output array. + +For example, you could subtract `cpu/energy` and `network/energy` and name the result `offset/energy`. `offset/energy` would then be added to every observation in your input array as the diff of `cpu/energy` and `network/energy`. + +## Parameters + +### Plugin config + +Two parameters are required in global config: `input-parameters` and `output-parameter`. + +`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array +`output-parameter`: a string defining the name to use to add the result of the diff to the output array. + +### Inputs + +All of `input-parameters` must be available in the input array. + +## Returns + +- `output-parameter`: the subtraction of all `input-parameters` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input0 - input1 - input2 ... - inputN +``` + +## Implementation + +To run the plugin, you must first create an instance of `Subtract`. Then, you can call `execute()`. + +```typescript +import {Subtract} from 'builtins'; + +const config = { + inputParameters: ['cpu/energy', 'network/energy'], + outputParameter: 'offset/energy', +}; + +const subtract = Subtract(config); +const result = subtract subtract.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + 'cpu/energy': 0.005, + 'memory/energy': 0.0001, + }, +]); +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `subtract`: + +```yaml +name: subtract demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + subtract: + method: Subtract + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy/diff' +tree: + children: + child: + pipeline: + - subtract + config: + subtract: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 +``` + +You can run this example by saving it as `./examples/manifests/test/subrtact.yml` and executing the following command from the project root: + +```sh +npm i -g @grnsft/if +if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml +``` + +The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +`Subtract` uses one of IF's error classes: + +### `InputValidationError` + +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 diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts new file mode 100644 index 000000000..bd5af0603 --- /dev/null +++ b/src/if-run/builtins/subtract/index.ts @@ -0,0 +1,88 @@ +import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + SubtractConfig, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + const globalConfigSchema = z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.number()); + + validate(validationSchema, inputData); + + return input; + }; + + /** + * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => { + const { + 'input-parameters': inputParameters, + 'output-parameter': outputParameter, + } = validateGlobalConfig(); + + return inputs.map(input => { + validateSingleInput(input, inputParameters); + + return { + ...input, + [outputParameter]: calculateDiff(input, inputParameters), + }; + }); + }; + + /** + * Calculates the diff between the 1st item in the inputs nad the rest of the items + */ + const calculateDiff = (input: PluginParams, inputParameters: string[]) => { + const [firstItem, ...restItems] = inputParameters; + + return restItems.reduce( + (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], + input[firstItem] // Starting accumulator with the value of the first item + ); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md new file mode 100644 index 000000000..ea0f0113d --- /dev/null +++ b/src/if-run/builtins/sum/README.md @@ -0,0 +1,118 @@ +# Sum + +`sum` is a generic plugin for doing arithmetic sums of two or more values in an `input` array. + +You provide the names of the values you want to sum, and a name to use to add the sum to the output array. + +For example, you could add `cpu/energy` and `network/energy` and name the result `energy`. `energy` would then be added to every observation in your input array as the sum of `cpu/energy` and `network/energy`. + +## Parameters + +### Plugin config + +Two parameters are required in global config: `input-parameters` and `output-parameter`. + +`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array +`output-parameter`: a string defining the name to use to add the result of summing the input parameters to the output array. + +### Inputs + +All of `input-parameters` must be available in the input array. + +## Returns + +- `output-parameter`: the sum of all `input-parameters` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input0 + input1 + input2 ... inputN +``` + +## Implementation + +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 sum = Sum(config); +const result = sum.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 0.001, + 'memory/energy': 0.0005, + }, +]); +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `sum`: + +```yaml +name: sum demo +description: +tags: +initialize: + outputs: + - yaml + plugins: + sum: + method: Sum + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy' +tree: + children: + child: + pipeline: + - sum + config: + sum: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 +``` + +You can run this example by saving it as `./examples/manifests/sum.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`Sum` exposes two of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameters`: this must be an array of strings, each being the name of a value in the `inputs` array +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: + +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` + + +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/index.ts b/src/if-run/builtins/sum/index.ts new file mode 100644 index 000000000..62ba479e6 --- /dev/null +++ b/src/if-run/builtins/sum/index.ts @@ -0,0 +1,88 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, SumConfig} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +export const Sum = (globalConfig: SumConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Calculate the sum of each input-paramters. + */ + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const inputParameters = safeGlobalConfig['input-parameters']; + const outputParameter = safeGlobalConfig['output-parameter']; + + return inputs.map(input => { + validateSingleInput(input, inputParameters); + + return { + ...input, + [outputParameter]: calculateSum(input, inputParameters), + }; + }); + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); + + return input; + }; + + /** + * Calculates the sum of the energy components. + */ + const calculateSum = (input: PluginParams, inputParameters: string[]) => + inputParameters.reduce( + (accumulator, metricToSum) => accumulator + input[metricToSum], + 0 + ); + + return { + metadata, + execute, + }; +}; diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts new file mode 100644 index 000000000..78b293e75 --- /dev/null +++ b/src/if-run/builtins/time-sync.ts @@ -0,0 +1,459 @@ +import {isDate} from 'node:util/types'; + +import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + PaddingReceipt, + TimeNormalizerConfig, + TimeParams, +} from '@grnsft/if-core/types'; + +import {parameterize} from '../lib/parameterize'; + +import {validate} from '../../common/util/validations'; + +import {STRINGS} from '../config'; + +Settings.defaultZone = 'utc'; + +const { + GlobalConfigError, + InvalidDateInInputError, + InvalidPaddingError, + InvalidInputError, +} = ERRORS; + +const { + INVALID_TIME_NORMALIZATION, + INVALID_OBSERVATION_OVERLAP, + AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, + START_LOWER_END, + TIMESTAMP_REQUIRED, + INVALID_DATETIME, +} = STRINGS; + +export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Take input array and return time-synchronized input array. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => { + const validatedConfig = validateGlobalConfig(); + const timeParams = { + startTime: DateTime.fromISO(validatedConfig['start-time']), + endTime: DateTime.fromISO(validatedConfig['end-time']), + interval: validatedConfig.interval, + allowPadding: validatedConfig['allow-padding'], + }; + + const pad = checkForPadding(inputs, timeParams); + validatePadding(pad, timeParams); + + const paddedInputs = padInputs(inputs, pad, timeParams); + + const flattenInputs = paddedInputs.reduce( + (acc: PluginParams[], input, index) => { + const safeInput = Object.assign({}, input, validateInput(input, index)); + const currentMoment = parseDate(safeInput.timestamp); + + /** Checks if not the first input, then check consistency with previous ones. */ + if (index > 0) { + const previousInput = paddedInputs[index - 1]; + const previousInputTimestamp = parseDate(previousInput.timestamp); + + /** Checks for timestamps overlap. */ + if ( + parseDate(previousInput.timestamp).plus({ + seconds: previousInput.duration, + }) > currentMoment + ) { + throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); + } + + const compareableTime = previousInputTimestamp.plus({ + seconds: previousInput.duration, + }); + + const timelineGapSize = currentMoment + .diff(compareableTime) + .as('seconds'); + + /** Checks if there is gap in timeline. */ + if (timelineGapSize > 1) { + acc.push( + ...getZeroishInputPerSecondBetweenRange( + compareableTime, + currentMoment, + safeInput + ) + ); + } + } + /** Break down current observation. */ + for (let i = 0; i < safeInput.duration; i++) { + const normalizedInput = breakDownInput(safeInput, i); + + acc.push(normalizedInput); + } + + return trimInputsByGlobalTimeline(acc, timeParams); + }, + [] as PluginParams[] + ); + + const sortedInputs = flattenInputs.sort((a, b) => + parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') + ); + + return resampleInputs(sortedInputs, timeParams) as PluginParams[]; + }; + + const parseDate = (date: Date | string) => { + if (!date) { + return DateTime.invalid('Invalid date'); + } + + // dates are passed to time-sync.ts both in ISO 8601 format + // and as a Date object (from the deserialization of a YAML file) + // if the YAML parser fails to identify as a date, it passes as a string + if (isDate(date)) { + return DateTime.fromJSDate(date); + } + + if (typeof date === 'string') { + return DateTime.fromISO(date); + } + + throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); + }; + + /** + * Validates input parameters. + */ + const validateInput = (input: PluginParams, index: number) => { + const schema = z.object({ + timestamp: z + .string({ + required_error: TIMESTAMP_REQUIRED(index), + }) + .datetime({ + message: INVALID_DATETIME(index), + }) + .or(z.date()), + duration: z.number(), + }); + + return validate>(schema, input); + }; + + /** + * Validates global config parameters. + */ + const validateGlobalConfig = () => { + if (globalConfig === undefined) { + throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); + } + + const schema = z + .object({ + 'start-time': z.string().datetime(), + 'end-time': z.string().datetime(), + interval: z.number(), + 'allow-padding': z.boolean(), + }) + .refine(data => data['start-time'] < data['end-time'], { + message: START_LOWER_END, + }); + + return validate>(schema, globalConfig); + }; + + /** + * Calculates minimal factor. + */ + const convertPerInterval = (value: number, duration: number) => + value / duration; + + /** + * Normalize time per given second. + */ + const normalizeTimePerSecond = ( + currentRoundMoment: Date | string, + i: number + ) => { + const thisMoment = parseDate(currentRoundMoment).startOf('second'); + + return thisMoment.plus({seconds: i}); + }; + + /** + * Breaks down input per minimal time unit. + */ + const breakDownInput = (input: PluginParams, i: number) => { + const inputKeys = Object.keys(input); + + return inputKeys.reduce((acc, key) => { + const method = parameterize.getAggregationMethod(key); + + if (key === 'timestamp') { + const perSecond = normalizeTimePerSecond(input.timestamp, i); + acc[key] = perSecond.toUTC().toISO() ?? ''; + + return acc; + } + + /** @todo use user defined resolution later */ + if (key === 'duration') { + acc[key] = 1; + + return acc; + } + + acc[key] = + method === 'sum' + ? convertPerInterval(input[key], input['duration']) + : input[key]; + + return acc; + }, {} as PluginParams); + }; + + /** + * Populates object to fill the gaps in observational timeline using zeroish values. + */ + const fillWithZeroishInput = ( + input: PluginParams, + missingTimestamp: DateTimeMaybeValid + ) => { + const metrics = Object.keys(input); + + return metrics.reduce((acc, metric) => { + if (metric === 'timestamp') { + acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; + + return acc; + } + + /** @todo later will be changed to user defined interval */ + if (metric === 'duration') { + acc[metric] = 1; + + return acc; + } + + if (metric === 'time-reserved') { + acc[metric] = acc['duration']; + + return acc; + } + + const method = parameterize.getAggregationMethod(metric); + + if (method === 'avg' || method === 'sum') { + acc[metric] = 0; + + return acc; + } + + acc[metric] = input[metric]; + + return acc; + }, {} as PluginParams); + }; + + /** + * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. + */ + const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { + const {start, end} = pad; + const isPaddingNeeded = start || end; + + if (!params.allowPadding && isPaddingNeeded) { + throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); + } + }; + + /** + * Checks if padding is needed either at start of the timeline or the end and returns status. + */ + const checkForPadding = ( + inputs: PluginParams[], + params: TimeParams + ): PaddingReceipt => { + const startDiffInSeconds = parseDate(inputs[0].timestamp) + .diff(params.startTime) + .as('seconds'); + + const lastInput = inputs[inputs.length - 1]; + + const endDiffInSeconds = parseDate(lastInput.timestamp) + .plus({second: lastInput.duration}) + .diff(params.endTime) + .as('seconds'); + + return { + start: startDiffInSeconds > 0, + end: endDiffInSeconds < 0, + }; + }; + + /** + * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. + * For methods is `avg` and `none` calculating average of the frame. + */ + const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => + inputsInTimeslot.reduce((acc, input, index, inputs) => { + const metrics = Object.keys(input); + + metrics.forEach(metric => { + const method = parameterize.getAggregationMethod(metric); + acc[metric] = acc[metric] ?? 0; + + if (metric === 'timestamp') { + acc[metric] = inputs[0][metric]; + + return; + } + + if (method === 'sum') { + acc[metric] += input[metric]; + + return; + } + + if (method === 'none') { + acc[metric] = input[metric]; + + return; + } + + /** + * If timeslot contains records more than one, then divide each metric by the timeslot length, + * so that their sum yields the timeslot average. + */ + if ( + inputsInTimeslot.length > 1 && + index === inputsInTimeslot.length - 1 + ) { + acc[metric] /= inputsInTimeslot.length; + + return; + } + + acc[metric] += input[metric]; + }); + + return acc; + }, {} as PluginParams); + + /** + * Takes each array frame with interval length, then aggregating them together as from units.yaml file. + */ + const resampleInputs = (inputs: PluginParams[], params: TimeParams) => + inputs.reduce((acc: PluginParams[], _input, index, inputs) => { + const frameStart = index * params.interval; + const frameEnd = (index + 1) * params.interval; + const inputsFrame = inputs.slice(frameStart, frameEnd); + + const resampledInput = resampleInputFrame(inputsFrame); + + /** Checks if resampled input is not empty, then includes in result. */ + if (Object.keys(resampledInput).length > 0) { + acc.push(resampledInput); + } + + return acc; + }, [] as PluginParams[]); + + /** + * Pads zeroish inputs from the beginning or at the end of the inputs if needed. + */ + const padInputs = ( + inputs: PluginParams[], + pad: PaddingReceipt, + params: TimeParams + ): PluginParams[] => { + const {start, end} = pad; + const paddedFromBeginning = []; + + if (start) { + paddedFromBeginning.push( + ...getZeroishInputPerSecondBetweenRange( + params.startTime, + parseDate(inputs[0].timestamp), + inputs[0] + ) + ); + } + + const paddedArray = paddedFromBeginning.concat(inputs); + + if (end) { + const lastInput = inputs[inputs.length - 1]; + const lastInputEnd = parseDate(lastInput.timestamp).plus({ + seconds: lastInput.duration, + }); + paddedArray.push( + ...getZeroishInputPerSecondBetweenRange( + lastInputEnd, + params.endTime.plus({seconds: 1}), + lastInput + ) + ); + } + + return paddedArray; + }; + + const getZeroishInputPerSecondBetweenRange = ( + startDate: DateTimeMaybeValid, + endDate: DateTimeMaybeValid, + templateInput: PluginParams + ) => { + const array: PluginParams[] = []; + const dateRange = Interval.fromDateTimes(startDate, endDate); + + for (const interval of dateRange.splitBy({second: 1})) { + array.push( + fillWithZeroishInput( + templateInput, + // as far as I can tell, start will never be null + // because if we pass an invalid start/endDate to + // Interval, we get a zero length array as the range + interval.start || DateTime.invalid('not expected - start is null') + ) + ); + } + + return array; + }; + + /* + * Checks if input's timestamp is included in global specified period then leaves it, otherwise. + */ + const trimInputsByGlobalTimeline = ( + inputs: PluginParams[], + params: TimeParams + ): PluginParams[] => + inputs.reduce((acc: PluginParams[], item) => { + const {timestamp} = item; + + if ( + parseDate(timestamp) >= params.startTime && + parseDate(timestamp) <= params.endTime + ) { + acc.push(item); + } + + return acc; + }, [] as PluginParams[]); + + return {metadata, execute}; +}; From 903bf07d12b4a4174632575df33c8ddfb5149c28 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:15:25 +0400 Subject: [PATCH 304/863] feat(src): init if-run index file --- src/if-run/index.ts | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/if-run/index.ts diff --git a/src/if-run/index.ts b/src/if-run/index.ts new file mode 100644 index 000000000..fa5d17fa2 --- /dev/null +++ b/src/if-run/index.ts @@ -0,0 +1,56 @@ +#!/usr/bin/env node +import {aggregate} from './lib/aggregate'; +import {compute} from './lib/compute'; +import {injectEnvironment} from './lib/environment'; +import {exhaust} from './lib/exhaust'; +import {initialize} from './lib/initialize'; +import {parameterize} from './lib/parameterize'; +import {load} from '../common/lib/load'; + +import {parseIfRunProcessArgs} from './util/args'; +import {andHandle} from './util/helpers'; +import {logger} from '../common/util/logger'; +import {validateManifest} from '../common/util/validations'; +import {debugLogger} from '../common/util/debug-logger'; + +import {STRINGS} from './config'; +import {STRINGS as COMMON_STRINGS} from '../common/config'; + +const {EXITING_IF, STARTING_IF} = STRINGS; +const {DISCLAIMER_MESSAGE} = COMMON_STRINGS; + +const impactEngine = async () => { + const options = parseIfRunProcessArgs(); + const {inputPath, paramPath, outputOptions, debug} = options; + + debugLogger.overrideConsoleMethods(!!debug); + + logger.info(DISCLAIMER_MESSAGE); + console.info(STARTING_IF); + + const {rawManifest, parameters} = await load(inputPath, paramPath); + const envManifest = await injectEnvironment(rawManifest); + + try { + const {tree, ...context} = validateManifest(envManifest); + parameterize.combine(context.params, parameters); + const pluginStorage = await initialize(context.initialize.plugins); + const computedTree = await compute(tree, {context, pluginStorage}); + const aggregatedTree = aggregate(computedTree, context.aggregation); + await exhaust(aggregatedTree, context, outputOptions); + } catch (error) { + if (error instanceof Error) { + envManifest.execution!.status = 'fail'; + envManifest.execution!.error = error.toString(); + logger.error(error); + const {tree, ...context} = envManifest; + + if (error.name !== 'ExhaustError') { + exhaust(tree, context, outputOptions); + } + } + } + console.info(EXITING_IF); +}; + +impactEngine().catch(andHandle); From 73e0c584af1eb227c8645c5f3aa33c8964908bec Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:15:39 +0400 Subject: [PATCH 305/863] feat(src): init if-env utils --- src/if-env/util/args.ts | 55 ++++++++++++++ src/if-env/util/helpers.ts | 92 +++++++++++++++++++++++ src/if-env/util/npm.ts | 146 +++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 src/if-env/util/args.ts create mode 100644 src/if-env/util/helpers.ts create mode 100644 src/if-env/util/npm.ts diff --git a/src/if-env/util/args.ts b/src/if-env/util/args.ts new file mode 100644 index 000000000..940fa7b7a --- /dev/null +++ b/src/if-env/util/args.ts @@ -0,0 +1,55 @@ +import {parse} from 'ts-command-line-args'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {isFileExists} from '../../common/util/fs'; +import {prependFullFilePath} from '../../common/util/helpers'; +import {checkIfFileIsYaml} from '../../common/util/yaml'; + +import {CONFIG} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFEnvArgs} from '../types/process-args'; + +const {ParseCliParamsError, CliSourceFileError} = ERRORS; +const {IF_ENV} = CONFIG; +const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; + +/** + * Parses `if-env` process arguments. + */ +const validateAndParseIfEnvArgs = () => { + try { + return parse(IF_ENV.ARGS, IF_ENV.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if the `manifest` command is provided and it is valid manifest file. + */ +export const parseIfEnvArgs = async () => { + const {manifest, install, cwd} = validateAndParseIfEnvArgs(); + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest: response, install, cwd}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + return {install, cwd}; +}; diff --git a/src/if-env/util/helpers.ts b/src/if-env/util/helpers.ts new file mode 100644 index 000000000..17827f58a --- /dev/null +++ b/src/if-env/util/helpers.ts @@ -0,0 +1,92 @@ +/* eslint-disable no-process-exit */ +import * as path from 'path'; +import * as fs from 'fs/promises'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import { + extractPathsWithVersion, + initPackageJsonIfNotExists, + installDependencies, + updatePackageJsonDependencies, + updatePackageJsonProperties, +} from './npm'; +import {load} from '../../common/lib/load'; + +import {STRINGS} from '../config'; + +import {EnvironmentOptions} from '../types/if-env'; + +const {MissingPluginDependenciesError} = ERRORS; +const { + FAILURE_MESSAGE_DEPENDENCIES, + FAILURE_MESSAGE, + FAILURE_MESSAGE_TEMPLATE, +} = STRINGS; + +/** + * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + */ +export const getOptionsFromArgs = async (commandArgs: { + manifest: string; + install: boolean | undefined; +}) => { + const {manifest, install} = commandArgs; + const folderPath = path.dirname(manifest); + const loadedManifest = await load(manifest); + const rawManifest = loadedManifest.rawManifest; + const plugins = rawManifest?.initialize?.plugins || {}; + const dependencies = rawManifest?.execution?.environment.dependencies || []; + + if (!dependencies.length) { + throw new MissingPluginDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); + } + + const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); + + return { + folderPath, + dependencies: pathsWithVersion, + install, + }; +}; + +/** + * Creates folder if not exists, installs dependencies if required, update depenedencies. + */ +export const initializeAndInstallLibs = async (options: EnvironmentOptions) => { + try { + const {folderPath, install, cwd, dependencies} = options; + const packageJsonPath = await initPackageJsonIfNotExists(folderPath); + + await updatePackageJsonProperties(packageJsonPath, cwd); + + if (install) { + await installDependencies(folderPath, dependencies); + } else { + await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); + } + } catch (error) { + console.log(FAILURE_MESSAGE); + process.exit(2); + } +}; + +/** + * Adds a manifest template to the folder where the if-env CLI command runs. + */ +export const addTemplateManifest = async (destinationDir: string) => { + try { + const templateManifest = path.resolve( + __dirname, + '../config/env-template.yml' + ); + + const destinationPath = path.resolve(destinationDir, 'manifest.yml'); + const data = await fs.readFile(templateManifest, 'utf-8'); + + await fs.writeFile(destinationPath, data, 'utf-8'); + } catch (error) { + console.log(FAILURE_MESSAGE_TEMPLATE); + process.exit(1); + } +}; diff --git a/src/if-env/util/npm.ts b/src/if-env/util/npm.ts new file mode 100644 index 000000000..f029bcdf2 --- /dev/null +++ b/src/if-env/util/npm.ts @@ -0,0 +1,146 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {execPromise} from '../../common/util/helpers'; +import {isDirectoryExists, isFileExists} from '../../common/util/fs'; +import {logger} from '../../common/util/logger'; + +import {STRINGS} from '../config'; +import {ManifestPlugin, PathWithVersion} from '../types/npm'; + +const packageJson = require('../../../package.json'); + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; + +/** + * Checks if the package.json is exists, if not, initializes it. + */ +export const initPackageJsonIfNotExists = async (folderPath: string) => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + const isPackageJsonExists = await isFileExists(packageJsonPath); + + if (!isPackageJsonExists) { + logger.info(INITIALIZING_PACKAGE_JSON); + + const nodeModulesPath = path.resolve(folderPath, 'node_modules'); + const isNodeModulesExists = await isDirectoryExists(nodeModulesPath); + + if (isNodeModulesExists) { + await fs.rm(nodeModulesPath, {recursive: true}); + } + + await execPromise('npm init -y', {cwd: folderPath}); + } + + return packageJsonPath; +}; + +/** + * Installs packages from the specified dependencies in the specified folder. + */ +export const installDependencies = async ( + folderPath: string, + dependencies: {[path: string]: string} +) => { + const packages = Object.entries(dependencies).map( + ([dependency, version]) => `${dependency}@${version.replace('^', '')}` + ); + + logger.info(INSTALLING_NPM_PACKAGES); + await execPromise(`npm install ${packages.join(' ')}`, { + cwd: folderPath, + }); +}; + +/** + * Updates package.json dependencies. + */ +export const updatePackageJsonDependencies = async ( + packageJsonPath: string, + dependencies: PathWithVersion, + cwd: boolean +) => { + const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); + + const parsedPackageJson = JSON.parse(packageJsonContent); + + if (cwd) { + parsedPackageJson.dependencies = { + ...parsedPackageJson.dependencies, + ...dependencies, + }; + } else { + parsedPackageJson.dependencies = {...dependencies}; + } + + await fs.writeFile( + packageJsonPath, + JSON.stringify(parsedPackageJson, null, 2) + ); +}; + +/** + * Gets depencecies with versions. + */ +export const extractPathsWithVersion = ( + plugins: ManifestPlugin, + dependencies: string[] +) => { + const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); + const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); + const pathsWithVersion: PathWithVersion = {}; + + uniquePaths.forEach(pluginPath => { + const dependency = dependencies.find((dependency: string) => + dependency.startsWith(pluginPath) + ); + + if (dependency) { + const splittedDependency = dependency.split('@'); + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[pluginPath] = `^${version}`; + } + }); + + return pathsWithVersion; +}; + +/** + * Update the package.json properties. + */ +export const updatePackageJsonProperties = async ( + newPackageJsonPath: string, + appendDependencies: boolean +) => { + const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); + const parsedPackageJsonContent = JSON.parse(packageJsonContent); + + const properties = { + name: 'if-environment', + description: packageJson.description, + author: packageJson.author, + bugs: packageJson.bugs, + engines: packageJson.engines, + homepage: packageJson.homepage, + dependencies: appendDependencies + ? parsedPackageJsonContent.dependencies + : {}, + }; + + const newPackageJson = Object.assign( + {}, + parsedPackageJsonContent, + properties + ); + + await fs.writeFile( + newPackageJsonPath, + JSON.stringify(newPackageJson, null, 2) + ); +}; From a378df631f2483db061b6e6060da209818dc854e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:15:50 +0400 Subject: [PATCH 306/863] feat(src): init if-env types --- src/if-env/types/if-env.ts | 6 ++++++ src/if-env/types/npm.ts | 3 +++ src/if-env/types/process-args.ts | 5 +++++ 3 files changed, 14 insertions(+) create mode 100644 src/if-env/types/if-env.ts create mode 100644 src/if-env/types/npm.ts create mode 100644 src/if-env/types/process-args.ts diff --git a/src/if-env/types/if-env.ts b/src/if-env/types/if-env.ts new file mode 100644 index 000000000..03ace8ec9 --- /dev/null +++ b/src/if-env/types/if-env.ts @@ -0,0 +1,6 @@ +export type EnvironmentOptions = { + folderPath: string; + install: boolean; + cwd: boolean; + dependencies: {[path: string]: string}; +}; diff --git a/src/if-env/types/npm.ts b/src/if-env/types/npm.ts new file mode 100644 index 000000000..cbb3e0680 --- /dev/null +++ b/src/if-env/types/npm.ts @@ -0,0 +1,3 @@ +export type PathWithVersion = {[path: string]: string}; + +export type ManifestPlugin = {[key: string]: {path: string; method: string}}; diff --git a/src/if-env/types/process-args.ts b/src/if-env/types/process-args.ts new file mode 100644 index 000000000..7db2117a8 --- /dev/null +++ b/src/if-env/types/process-args.ts @@ -0,0 +1,5 @@ +export interface IFEnvArgs { + manifest?: string; + install?: boolean; + cwd?: boolean; +} From c118e8eb5a6839040c739839d6c76e77dca8e783 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:01 +0400 Subject: [PATCH 307/863] feat(src): init if-env config --- src/if-env/config/config.ts | 42 ++++++++++++++++++++++++++++++ src/if-env/config/env-template.yml | 24 +++++++++++++++++ src/if-env/config/index.ts | 2 ++ src/if-env/config/strings.ts | 8 ++++++ 4 files changed, 76 insertions(+) create mode 100644 src/if-env/config/config.ts create mode 100644 src/if-env/config/env-template.yml create mode 100644 src/if-env/config/index.ts create mode 100644 src/if-env/config/strings.ts diff --git a/src/if-env/config/config.ts b/src/if-env/config/config.ts new file mode 100644 index 000000000..cc603d6de --- /dev/null +++ b/src/if-env/config/config.ts @@ -0,0 +1,42 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {IFEnvArgs} from '../types/process-args'; + +import {STRINGS} from '../../common/config'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + IF_ENV: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + install: { + type: Boolean, + optional: true, + alias: 'i', + description: '[command to install package.json]', + }, + cwd: { + type: Boolean, + optional: true, + alias: 'c', + description: + '[command to generate the package.json in the command working directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + }, +}; diff --git a/src/if-env/config/env-template.yml b/src/if-env/config/env-template.yml new file mode 100644 index 000000000..f5fd65a6a --- /dev/null +++ b/src/if-env/config/env-template.yml @@ -0,0 +1,24 @@ +name: template manifest # rename me! +description: auto-generated template # update description! +tags: # add any tags that will help you to track your manifests +initialize: + outputs: + - yaml # you can add - csv to export to csv + plugins: # add more plugins for your use-case + memory-energy-from-memory-util: # you can name this any way you like! + method: Coefficient # the name of the function exported from the plugin + path: "builtin" # the import path + global-config: # anmy config required by the plugin + input-parameter: "memory/utilization" + coefficient: 0.0001 #kwH/GB + output-parameter: "memory/energy" +tree: + children: # add a chile for each distinct component you want to measure + child: + pipeline: # the pipeline is an ordered list of plugins you want to execute + - memory-energy-from-memory-util # must match the name in initialize! + config: # any plugin specific, node-level config + inputs: + - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string + duration: 3600 # units of seconds + memory/utilization: 10 diff --git a/src/if-env/config/index.ts b/src/if-env/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-env/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-env/config/strings.ts b/src/if-env/config/strings.ts new file mode 100644 index 000000000..047ba89c0 --- /dev/null +++ b/src/if-env/config/strings.ts @@ -0,0 +1,8 @@ +export const STRINGS = { + FAILURE_MESSAGE: 'Faied to create the environment!', + FAILURE_MESSAGE_TEMPLATE: + 'Faied to create the environment with the template manifest!', + FAILURE_MESSAGE_DEPENDENCIES: 'Manifest dependencies are not available!', + INITIALIZING_PACKAGE_JSON: 'Initializing package.json.', + INSTALLING_NPM_PACKAGES: 'Installing npm packages...', +}; From b2f7fc24c1028b2d96a3f9a8bcc860ca0cdcf4d9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:10 +0400 Subject: [PATCH 308/863] feat(src): init if-env index file --- src/if-env/index.ts | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/if-env/index.ts diff --git a/src/if-env/index.ts b/src/if-env/index.ts new file mode 100644 index 000000000..98fe6cc6e --- /dev/null +++ b/src/if-env/index.ts @@ -0,0 +1,50 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import {parseIfEnvArgs} from './util/args'; + +import {STRINGS} from '../common/config'; + +import { + addTemplateManifest, + getOptionsFromArgs, + initializeAndInstallLibs, +} from './util/helpers'; +import {logger} from '../common/util/logger'; + +import {EnvironmentOptions} from './types/if-env'; + +const {SUCCESS_MESSAGE} = STRINGS; + +const IfEnv = async () => { + const commandArgs = await parseIfEnvArgs(); + const options: EnvironmentOptions = { + folderPath: process.env.CURRENT_DIR || process.cwd(), + install: !!commandArgs.install, + dependencies: {}, + cwd: !!commandArgs.cwd, + }; + + if (commandArgs && commandArgs.manifest) { + const {folderPath, install, dependencies} = + await getOptionsFromArgs(commandArgs); + options.folderPath = commandArgs.cwd ? options.folderPath : folderPath; + options.install = !!install; + options.dependencies = {...dependencies}; + } + + await initializeAndInstallLibs(options); + + if (!commandArgs || !commandArgs.manifest) { + await addTemplateManifest(options.folderPath); + } + + console.log(SUCCESS_MESSAGE); + process.exit(0); +}; + +IfEnv().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 6c8a7d552f446c992c93ee04a39bb08133f5d503 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:24 +0400 Subject: [PATCH 309/863] feat(src): init if-diff utils --- src/if-diff/util/args.ts | 61 +++++++++++++++++ src/if-diff/util/helpers.ts | 128 ++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/if-diff/util/args.ts create mode 100644 src/if-diff/util/helpers.ts diff --git a/src/if-diff/util/args.ts b/src/if-diff/util/args.ts new file mode 100644 index 000000000..e87dc540c --- /dev/null +++ b/src/if-diff/util/args.ts @@ -0,0 +1,61 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {checkIfFileIsYaml} from '../../common/util/yaml'; +import {prependFullFilePath} from '../../common/util/helpers'; + +import {CONFIG, STRINGS} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFDiffArgs} from '../types/process-args'; +import {LoadDiffParams} from '../types/args'; + +const {ParseCliParamsError, CliTargetFileError, CliSourceFileError} = ERRORS; + +const {ARGS, HELP} = CONFIG; +const {INVALID_TARGET} = STRINGS; +const {SOURCE_IS_NOT_YAML, TARGET_IS_NOT_YAML} = COMMON_STRINGS; + +/** + * Parses `if-diff` process arguments. + */ +const validateAndParseIfDiffArgs = () => { + try { + return parse(ARGS, HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks for `source` and `target` flags to be present. + */ +export const parseIfDiffArgs = () => { + const {source, target} = validateAndParseIfDiffArgs(); + + if (target) { + if (source && !checkIfFileIsYaml(source)) { + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + if (checkIfFileIsYaml(target)) { + const response: LoadDiffParams = { + targetPath: prependFullFilePath(target), + }; + + if (source && checkIfFileIsYaml(source)) { + response.sourcePath = prependFullFilePath(source); + } + + return response; + } + + throw new CliTargetFileError(TARGET_IS_NOT_YAML); + } + + throw new ParseCliParamsError(INVALID_TARGET); +}; diff --git a/src/if-diff/util/helpers.ts b/src/if-diff/util/helpers.ts new file mode 100644 index 000000000..858d5333c --- /dev/null +++ b/src/if-diff/util/helpers.ts @@ -0,0 +1,128 @@ +import {createInterface} from 'node:readline/promises'; +import {Difference} from '../types/compare'; + +/** + * `If-diff` equality checker. + */ +export const checkIfEqual = (source: any, target: any) => { + if (source === target) { + return true; + } + + if (source === '*' || target === '*') { + return true; + } + + return false; +}; + +/** + * Checks if objects are primitive types. + */ +export const oneIsPrimitive = (source: any, target: any) => { + // eslint-disable-next-line eqeqeq + if (source == null || target == null) { + return true; + } + + return source !== Object(source) && target !== Object(target); +}; + +/** + * Converts given `value` to either `1` or `0`. + */ +const convertToXorable = (value: any) => { + if (typeof value === 'number') { + return value !== 0 ? 1 : 0; + } + + if (typeof value === 'boolean') { + return value ? 1 : 0; + } + + if (typeof value === 'string') { + return value.length > 0 ? 1 : 0; + } + + if (typeof value === 'object') { + return 1; + } + + return 0; +}; + +/** + * If one of the `valuesToCheck` values is undefined, then set `missing`, otherwise `exists`. + */ +const setValuesIfMissing = (response: Difference) => { + const source = convertToXorable(response.source); + const target = convertToXorable(response.target); + + if (source ^ target) { + ['source', 'target'].forEach(value => { + response[value] = response[value] ? 'exists' : 'missing'; + }); + + return response; + } + + return response; +}; + +/** + * Format not matching message for CLI logging. + */ +export const formatNotMatchingLog = (message: Difference) => { + const flattenMessage = setValuesIfMissing(message); + + Object.keys(flattenMessage).forEach(key => { + if (key === 'message' || key === 'path') { + console.log(message[key]); + } else { + console.log(`${key}: ${message[key]}`); + } + }); +}; + +/** + * Checks if there is data piped, then collects it. + * Otherwise returns empty string. + */ +const collectPipedData = async () => { + if (process.stdin.isTTY) { + return ''; + } + + const readline = createInterface({ + input: process.stdin, + }); + + const data: string[] = []; + + for await (const line of readline) { + data.push(line); + } + + return data.join('\n'); +}; + +/** + * Checks if there is piped data, tries to parse yaml from it. + * Returns empty string if haven't found anything. + */ +export const parseManifestFromStdin = async () => { + const pipedSourceManifest = await collectPipedData(); + + if (!pipedSourceManifest) { + return ''; + } + + const regex = /# start((?:.*\n)+?)# end/; + const match = regex.exec(pipedSourceManifest); + + if (!match) { + return ''; + } + + return match![1]; +}; From 8848d0cecddaf8faaee99e9fe1821c087e53a812 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:32 +0400 Subject: [PATCH 310/863] feat(src): init if-diff types --- src/if-diff/types/args.ts | 5 +++++ src/if-diff/types/compare.ts | 7 +++++++ src/if-diff/types/process-args.ts | 4 ++++ 3 files changed, 16 insertions(+) create mode 100644 src/if-diff/types/args.ts create mode 100644 src/if-diff/types/compare.ts create mode 100644 src/if-diff/types/process-args.ts diff --git a/src/if-diff/types/args.ts b/src/if-diff/types/args.ts new file mode 100644 index 000000000..ae78fa4d0 --- /dev/null +++ b/src/if-diff/types/args.ts @@ -0,0 +1,5 @@ +export type LoadDiffParams = { + sourcePath?: string; + targetPath: string; + pipedSourceManifest?: string; +}; diff --git a/src/if-diff/types/compare.ts b/src/if-diff/types/compare.ts new file mode 100644 index 000000000..0f0cae8cf --- /dev/null +++ b/src/if-diff/types/compare.ts @@ -0,0 +1,7 @@ +export type Difference = { + path?: string; + source?: any; + target?: any; + message?: string; + [key: string]: any; +}; diff --git a/src/if-diff/types/process-args.ts b/src/if-diff/types/process-args.ts new file mode 100644 index 000000000..88bb6eb90 --- /dev/null +++ b/src/if-diff/types/process-args.ts @@ -0,0 +1,4 @@ +export interface IFDiffArgs { + source?: string; + target: string; +} From f8cf02a24677b33b217844ae1f14593f5c6e2b1c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:40 +0400 Subject: [PATCH 311/863] feat(src): init if-diff lib --- src/if-diff/lib/compare.ts | 67 ++++++++++++++++++++++++++++++++++++++ src/if-diff/lib/load.ts | 38 +++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/if-diff/lib/compare.ts create mode 100644 src/if-diff/lib/load.ts diff --git a/src/if-diff/lib/compare.ts b/src/if-diff/lib/compare.ts new file mode 100644 index 000000000..2f4e9d442 --- /dev/null +++ b/src/if-diff/lib/compare.ts @@ -0,0 +1,67 @@ +import {checkIfEqual, oneIsPrimitive} from '../util/helpers'; + +import {Difference} from '../types/compare'; + +/** + * 1. If objects are not of the same type or are primitive types, compares directly. + * 2. Gets the keys from both objects. + * 3. If both are arrays, checks their elements. + * 4. Checks for keys present in both objects. + * If key is `execution`, omit unnecessary params. + * 5. If all keys are checked and no differences are found, return empty object. + */ +export const compare = (source: any, target: any, path = ''): Difference => { + if (oneIsPrimitive(source, target)) { + return checkIfEqual(source, target) + ? {} + : { + path, + source, + target, + }; + } + + const keys1 = Object.keys(source); + const keys2 = Object.keys(target); + + const allKeys = new Set([...keys1, ...keys2]); + + if (path === '') { + allKeys.delete('name'); + allKeys.delete('description'); + allKeys.delete('tags'); + } + + if (path === 'initialize') { + allKeys.delete('outputs'); + } + + if (path === 'execution') { + const whitelist = ['status', 'error']; + allKeys.forEach(value => { + if (!whitelist.includes(value)) { + allKeys.delete(value); + } + }); + } + + if (Array.isArray(source) && Array.isArray(target)) { + source.forEach((_record, i) => { + compare(source[i], target[i], path ? `${path}[${i}]` : `${i}`); + }); + } + + for (const key of allKeys) { + const result = compare( + source[key], + target[key], + path ? `${path}.${key}` : key + ); + + if (Object.keys(result).length) { + return result; + } + } + + return {}; +}; diff --git a/src/if-diff/lib/load.ts b/src/if-diff/lib/load.ts new file mode 100644 index 000000000..d11cd40e6 --- /dev/null +++ b/src/if-diff/lib/load.ts @@ -0,0 +1,38 @@ +import * as YAML from 'js-yaml'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {openYamlFileAsObject} from '../../common/util/yaml'; + +import {STRINGS} from '../config'; + +import {LoadDiffParams} from '../types/args'; +import {Manifest} from '../../common/types/manifest'; + +const {CliSourceFileError} = ERRORS; + +const {INVALID_SOURCE} = STRINGS; + +/** + * Loads files to compare. As a source file checks if data is piped and then decides which one to take. + */ +export const loadIfDiffFiles = async (params: LoadDiffParams) => { + const {sourcePath, targetPath, pipedSourceManifest} = params; + + if (!sourcePath && !pipedSourceManifest) { + throw new CliSourceFileError(INVALID_SOURCE); + } + + const loadFromSource = + sourcePath && (await openYamlFileAsObject(sourcePath!)); + const loadFromSTDIN = + pipedSourceManifest && (await YAML.load(pipedSourceManifest!)); + + const rawSourceManifest = loadFromSource || loadFromSTDIN; + const rawTargetManifest = await openYamlFileAsObject(targetPath); + + return { + rawSourceManifest, + rawTargetManifest, + }; +}; From 25170e650e4f62e92a344aa4abc8308d0e5e89ee Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:48 +0400 Subject: [PATCH 312/863] feat(src): init if-diff config --- src/if-diff/config/config.ts | 33 +++++++++++++++++++++++++++++++++ src/if-diff/config/index.ts | 2 ++ src/if-diff/config/strings.ts | 5 +++++ 3 files changed, 40 insertions(+) create mode 100644 src/if-diff/config/config.ts create mode 100644 src/if-diff/config/index.ts create mode 100644 src/if-diff/config/strings.ts diff --git a/src/if-diff/config/config.ts b/src/if-diff/config/config.ts new file mode 100644 index 000000000..12f5ade09 --- /dev/null +++ b/src/if-diff/config/config.ts @@ -0,0 +1,33 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IFDiffArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + ARGS: { + source: { + type: String, + optional: true, + alias: 's', + description: '[path to the source file]', + }, + target: { + type: String, + optional: false, + alias: 't', + description: '[path to the target file', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Diff Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, +}; diff --git a/src/if-diff/config/index.ts b/src/if-diff/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-diff/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-diff/config/strings.ts b/src/if-diff/config/strings.ts new file mode 100644 index 000000000..19154d8dd --- /dev/null +++ b/src/if-diff/config/strings.ts @@ -0,0 +1,5 @@ +export const STRINGS = { + INVALID_TARGET: 'Target is invalid.', + INVALID_SOURCE: 'Source is invalid.', + FAILURE_MESSAGE: 'Files do not match!', +}; From e058f2691f7ce1d1ba8d44c4d1230b86985b1a98 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:16:57 +0400 Subject: [PATCH 313/863] feat(src): init if-diff index file --- src/if-diff/index.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/if-diff/index.ts diff --git a/src/if-diff/index.ts b/src/if-diff/index.ts new file mode 100644 index 000000000..fc367330b --- /dev/null +++ b/src/if-diff/index.ts @@ -0,0 +1,55 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import {loadIfDiffFiles} from './lib/load'; +import {compare} from './lib/compare'; + +import {parseIfDiffArgs} from './util/args'; +import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; +import {validateManifest} from '../common/util/validations'; + +import {logger} from '../common/util/logger'; +import {debugLogger} from '../common/util/debug-logger'; + +import {STRINGS} from './config'; +import {STRINGS as COMMON_STRINGS} from '../common/config'; + +const {FAILURE_MESSAGE} = STRINGS; +const {SUCCESS_MESSAGE} = COMMON_STRINGS; + +const IfDiff = async () => { + const pipedSourceManifest = await parseManifestFromStdin(); + const {sourcePath, targetPath} = parseIfDiffArgs(); + + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + + const {rawSourceManifest, rawTargetManifest} = await loadIfDiffFiles({ + targetPath, + sourcePath, + pipedSourceManifest, + }); + const [sourceManifest, targetManifest] = [ + rawSourceManifest, + rawTargetManifest, + ].map(validateManifest); + const result = compare(sourceManifest, targetManifest); + + if (Object.keys(result).length) { + formatNotMatchingLog({ + message: FAILURE_MESSAGE, + ...result, + }); + + process.exit(1); + } + + console.log(SUCCESS_MESSAGE); + process.exit(0); +}; + +IfDiff().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From a8a5a5c9356d8a1646f5c3d3f2f86ea9fa858945 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:07 +0400 Subject: [PATCH 314/863] feat(src): init if-check utils --- src/if-check/util/args.ts | 72 ++++++++++++++++++++++++++++++++++++ src/if-check/util/helpers.ts | 17 +++++++++ src/if-check/util/npm.ts | 49 ++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 src/if-check/util/args.ts create mode 100644 src/if-check/util/helpers.ts create mode 100644 src/if-check/util/npm.ts diff --git a/src/if-check/util/args.ts b/src/if-check/util/args.ts new file mode 100644 index 000000000..ab6e3fd93 --- /dev/null +++ b/src/if-check/util/args.ts @@ -0,0 +1,72 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {isDirectoryExists, isFileExists} from '../../common/util/fs'; +import {prependFullFilePath} from '../../common/util/helpers'; +import {checkIfFileIsYaml} from '../../common/util/yaml'; + +import {CONFIG, STRINGS} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFCheckArgs} from '../types/process-args'; + +const { + ParseCliParamsError, + CliSourceFileError, + InvalidDirectoryError, + MissingCliFlagsError, +} = ERRORS; + +const {ARGS, HELP} = CONFIG; + +const {IF_CHECK_FLAGS_MISSING, DIRECTORY_NOT_FOUND} = STRINGS; +const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; + +/** + * Parses `if-check` process arguments. + */ +const validateAndParseIfCheckArgs = () => { + try { + return parse(ARGS, HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if either `manifest` or `directory` command is provided. + */ +export const parseIfCheckArgs = async () => { + const {manifest, directory} = validateAndParseIfCheckArgs(); + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } else if (directory) { + const isDirExists = await isDirectoryExists(directory); + + if (!isDirExists) { + throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); + } + + const response = prependFullFilePath(directory); + + return {directory: response}; + } + + throw new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING); +}; diff --git a/src/if-check/util/helpers.ts b/src/if-check/util/helpers.ts new file mode 100644 index 000000000..d94b99477 --- /dev/null +++ b/src/if-check/util/helpers.ts @@ -0,0 +1,17 @@ +import {STRINGS} from '../config'; + +const {IF_CHECK_FAILED, IF_CHECK_SUMMARY_ERROR_MESSAGE} = STRINGS; + +/** + * Logs the failure message from the stdout of an error. + */ +export const logStdoutFailMessage = (error: any, fileName: string) => { + console.log(IF_CHECK_FAILED(fileName)); + + const stdout = error.stdout; + const logs = stdout.split('\n\n'); + const failMessage = logs[logs.length - 1]; + + console.log(failMessage); + return IF_CHECK_SUMMARY_ERROR_MESSAGE(fileName, failMessage); +}; diff --git a/src/if-check/util/npm.ts b/src/if-check/util/npm.ts new file mode 100644 index 000000000..a6137a9d3 --- /dev/null +++ b/src/if-check/util/npm.ts @@ -0,0 +1,49 @@ +import * as path from 'node:path'; + +import {execPromise} from '../../common/util/helpers'; +import {getFileName, removeFileIfExists} from '../../common/util/fs'; + +import {STRINGS} from '../config'; + +const {IF_CHECK_VERIFIED} = STRINGS; + +/** + * Executes a series of npm commands based on the provided manifest file. + */ +export const executeCommands = async (manifest: string, cwd: boolean) => { + // TODO: After release remove isGlobal and appropriate checks + const isGlobal = !!process.env.npm_config_global; + const manifestDirPath = path.dirname(manifest); + const manifestFileName = getFileName(manifest); + const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); + const prefixFlag = + process.env.CURRENT_DIR && process.env.CURRENT_DIR !== process.cwd() + ? `--prefix=${path.relative(process.env.CURRENT_DIR!, process.cwd())}` + : ''; + const ifEnv = `${ + isGlobal ? `if-env ${prefixFlag}` : `npm run if-env ${prefixFlag} --` + } -m ${manifest}`; + const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; + const ifRunCommand = `${ + isGlobal ? `if-run ${prefixFlag}` : `npm run if-run ${prefixFlag} --` + } -m ${manifest} -o ${executedManifest}`; + const ifDiffCommand = `${ + isGlobal ? `if-diff ${prefixFlag}` : `npm run if-diff ${prefixFlag} --` + } -s ${executedManifest}.yaml -t ${manifest}`; + const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; + + await execPromise( + `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, + { + cwd: process.env.CURRENT_DIR || process.cwd(), + } + ); + + if (!cwd) { + await removeFileIfExists(`${manifestDirPath}/package.json`); + } + + await removeFileIfExists(`${executedManifest}.yaml`); + + console.log(IF_CHECK_VERIFIED(path.basename(manifest))); +}; From 99308f46072205185706d25b1f68183acc1a0da2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:14 +0400 Subject: [PATCH 315/863] feat(src): init if-check types --- src/if-check/types/process-args.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/if-check/types/process-args.ts diff --git a/src/if-check/types/process-args.ts b/src/if-check/types/process-args.ts new file mode 100644 index 000000000..72dd2305c --- /dev/null +++ b/src/if-check/types/process-args.ts @@ -0,0 +1,4 @@ +export interface IFCheckArgs { + manifest?: string; + directory?: string; +} From bb99e85316e32d9497f85a436cfc00a391502c3b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:23 +0400 Subject: [PATCH 316/863] feat(src): init if-check config --- src/if-check/config/config.ts | 33 +++++++++++++++++++++++++++++++++ src/if-check/config/index.ts | 2 ++ src/if-check/config/strings.ts | 19 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 src/if-check/config/config.ts create mode 100644 src/if-check/config/index.ts create mode 100644 src/if-check/config/strings.ts diff --git a/src/if-check/config/config.ts b/src/if-check/config/config.ts new file mode 100644 index 000000000..8d21da9f3 --- /dev/null +++ b/src/if-check/config/config.ts @@ -0,0 +1,33 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IFCheckArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + directory: { + type: String, + optional: true, + alias: 'd', + description: '[path to the manifests directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Check Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, +}; diff --git a/src/if-check/config/index.ts b/src/if-check/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-check/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-check/config/strings.ts b/src/if-check/config/strings.ts new file mode 100644 index 000000000..1b6f1c3ef --- /dev/null +++ b/src/if-check/config/strings.ts @@ -0,0 +1,19 @@ +export const STRINGS = { + CHECKING: 'Checking...', + IF_CHECK_FLAGS_MISSING: + 'Either the `--manifest` or `--directory` command should be provided with a path', + DIRECTORY_NOT_FOUND: 'Directory not found.', + DIRECTORY_YAML_FILES_NOT_FOUND: + 'The directory does not contain any YAML/YML files.\n', + IF_CHECK_EXECUTING: (filename: string) => `Executing \`${filename}\``, + IF_CHECK_VERIFICATION_FAILURES: + '---------\nif-check verification failures:\n', + IF_CHECK_FAILED: (filename: string) => + `✖ if-check could not verify ${filename}. The re-executed file does not match the original.\n`, + IF_CHECK_VERIFIED: (filename: string) => + `✔ if-check successfully verified ${filename}\n`, + IF_CHECK_SUMMARY_ERROR_MESSAGE: (filename: string, message: string) => + `Executing \`${filename}\`\n✖ ${message}`, + IF_CHECK_SUMMARY_LOG: (passedCount: number, totalCount: number) => + `---------\nCheck summary:\n${passedCount} of ${totalCount} files are passed.\n`, +}; From cd3677d06e04d86703d8ddf8be16589a6a2b71c9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:31 +0400 Subject: [PATCH 317/863] feat(src): init if-check index file --- src/if-check/index.ts | 89 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/if-check/index.ts diff --git a/src/if-check/index.ts b/src/if-check/index.ts new file mode 100644 index 000000000..8e79131d2 --- /dev/null +++ b/src/if-check/index.ts @@ -0,0 +1,89 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as path from 'path'; + +import {parseIfCheckArgs} from './util/args'; +import {logStdoutFailMessage} from './util/helpers'; +import {getYamlFiles, removeFileIfExists} from '../common/util/fs'; +import {logger} from '../common/util/logger'; + +import {STRINGS} from './config'; +import {executeCommands} from './util/npm'; + +const { + CHECKING, + DIRECTORY_YAML_FILES_NOT_FOUND, + IF_CHECK_VERIFICATION_FAILURES, + IF_CHECK_SUMMARY_LOG, + IF_CHECK_EXECUTING, +} = STRINGS; + +const IfCheck = async () => { + const commandArgs = await parseIfCheckArgs(); + + console.log(`${CHECKING}\n`); + + if (commandArgs.manifest) { + const manifest = commandArgs.manifest; + + try { + await executeCommands(manifest, false); + } catch (error: any) { + const fileName = path.basename(manifest); + const executedFile = manifest + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); + const manifestDirPath = path.dirname(manifest); + + logStdoutFailMessage(error, fileName); + + await removeFileIfExists(`${manifestDirPath}/package.json`); + await removeFileIfExists(executedFile); + } + } else { + const failedLogs = {count: 0, message: ''}; + const directory = commandArgs.directory; + const files = await getYamlFiles(directory!); + + if (files.length === 0) { + console.log(DIRECTORY_YAML_FILES_NOT_FOUND); + process.exit(1); + } + + for await (const file of files) { + const fileName = path.basename(file); + console.log(IF_CHECK_EXECUTING(fileName)); + + try { + await executeCommands(file, true); + } catch (error: any) { + const fileName = path.basename(file); + const executedFile = file + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); + + const failedFilesLog = logStdoutFailMessage(error, fileName); + failedLogs.message = failedLogs.message.concat(failedFilesLog); + failedLogs.count++; + + await removeFileIfExists(executedFile); + } + } + + if (failedLogs.count > 0) { + const passedFilesCount = files.length - failedLogs.count; + + console.log(IF_CHECK_VERIFICATION_FAILURES); + console.log(failedLogs.message); + console.log(IF_CHECK_SUMMARY_LOG(passedFilesCount, files.length)); + process.exit(1); + } + } +}; + +IfCheck().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 8ce1eb56ccbf721981b7c1534f4c934b3055bd6a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:45 +0400 Subject: [PATCH 318/863] revert(src): drop old config folder --- src/config/config.ts | 156 ---------------------------- src/config/env-template.yml | 24 ----- src/config/index.ts | 3 - src/config/params.ts | 198 ------------------------------------ src/config/strings.ts | 156 ---------------------------- 5 files changed, 537 deletions(-) delete mode 100644 src/config/config.ts delete mode 100644 src/config/env-template.yml delete mode 100644 src/config/index.ts delete mode 100644 src/config/params.ts delete mode 100644 src/config/strings.ts diff --git a/src/config/config.ts b/src/config/config.ts deleted file mode 100644 index b8f676924..000000000 --- a/src/config/config.ts +++ /dev/null @@ -1,156 +0,0 @@ -import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; - -import {STRINGS} from './strings'; - -import { - IFDiffArgs, - IEArgs, - IFEnvArgs, - IFCheckArgs, -} from '../types/process-args'; - -const {DISCLAIMER_MESSAGE} = STRINGS; - -export const CONFIG = { - IE: { - ARGS: { - manifest: { - type: String, - optional: true, - alias: 'm', - description: '[path to the input file]', - }, - output: { - type: String, - optional: true, - alias: 'o', - description: '[path to the output file]', - }, - 'override-params': { - type: String, - optional: true, - alias: 'p', - description: '[path to a parameter file that overrides our defaults]', - }, - stdout: { - type: Boolean, - optional: true, - alias: 's', - description: '[prints out to the console]', - }, - help: { - type: Boolean, - optional: true, - alias: 'h', - description: '[prints out the above help instruction]', - }, - debug: { - type: Boolean, - optional: true, - alias: 'd', - description: '[prints out debug logs to the console]', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - }, - IF_DIFF: { - ARGS: { - source: { - type: String, - optional: true, - alias: 's', - description: '[path to the source file]', - }, - target: { - type: String, - optional: false, - alias: 't', - description: '[path to the target file', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'IF-Diff Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - SUCCESS_MESSAGE: 'Files match!', - FAILURE_MESSAGE: 'Files do not match!', - }, - IF_ENV: { - ARGS: { - manifest: { - type: String, - optional: true, - alias: 'm', - description: '[path to the manifest file]', - }, - install: { - type: Boolean, - optional: true, - alias: 'i', - description: '[command to install package.json]', - }, - cwd: { - type: Boolean, - optional: true, - alias: 'c', - description: - '[command to generate the package.json in the command working directory]', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - SUCCESS_MESSAGE: 'The environment is successfully setup!', - FAILURE_MESSAGE: 'Faied to create the environment!', - FAILURE_MESSAGE_TEMPLATE: - 'Faied to create the environment with the template manifest!', - FAILURE_MESSAGE_DEPENDENCIES: 'Manifest dependencies are not available!', - }, - IF_CHECK: { - ARGS: { - manifest: { - type: String, - optional: true, - alias: 'm', - description: '[path to the manifest file]', - }, - directory: { - type: String, - optional: true, - alias: 'd', - description: '[path to the manifests directory]', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'IF-Check Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - }, - GITHUB_PATH: 'https://github.com', - NATIVE_PLUGIN: 'if-plugins', - AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], -}; diff --git a/src/config/env-template.yml b/src/config/env-template.yml deleted file mode 100644 index f5fd65a6a..000000000 --- a/src/config/env-template.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: template manifest # rename me! -description: auto-generated template # update description! -tags: # add any tags that will help you to track your manifests -initialize: - outputs: - - yaml # you can add - csv to export to csv - plugins: # add more plugins for your use-case - memory-energy-from-memory-util: # you can name this any way you like! - method: Coefficient # the name of the function exported from the plugin - path: "builtin" # the import path - global-config: # anmy config required by the plugin - input-parameter: "memory/utilization" - coefficient: 0.0001 #kwH/GB - output-parameter: "memory/energy" -tree: - children: # add a chile for each distinct component you want to measure - child: - pipeline: # the pipeline is an ordered list of plugins you want to execute - - memory-energy-from-memory-util # must match the name in initialize! - config: # any plugin specific, node-level config - inputs: - - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string - duration: 3600 # units of seconds - memory/utilization: 10 diff --git a/src/config/index.ts b/src/config/index.ts deleted file mode 100644 index 03ec3e587..000000000 --- a/src/config/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export {CONFIG} from './config'; -export {STRINGS} from './strings'; -export {PARAMETERS} from './params'; diff --git a/src/config/params.ts b/src/config/params.ts deleted file mode 100644 index 76732e57b..000000000 --- a/src/config/params.ts +++ /dev/null @@ -1,198 +0,0 @@ -import {Parameters} from '../types/parameters'; - -export const PARAMETERS: Parameters = { - carbon: { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'cpu/number-cores': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - 'cpu/utilization': { - description: 'refers to CPU utilization.', - unit: 'percentage', - aggregation: 'avg', - }, - 'disk-io': { - description: 'refers to GB of data written/read from disk', - unit: 'GB', - aggregation: 'sum', - }, - duration: { - description: 'refers to the duration of the input', - unit: 'seconds', - aggregation: 'sum', - }, - energy: { - description: 'amount of energy utilised by the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'cpu/energy': { - description: 'Energy consumed by the CPU of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'device/expected-lifespan': { - description: 'Total Expected Lifespan of the Component in Seconds', - unit: 'seconds', - aggregation: 'sum', - }, - 'memory/energy': { - description: 'Energy consumed by the Memory of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'carbon-embodied': { - description: 'Embodied Emissions of the component', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'network/energy': { - description: 'Energy consumed by the Network of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'functional-unit': { - description: - 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', - unit: 'none', - aggregation: 'sum', - }, - 'gpu-util': { - description: 'refers to CPU utilization.', - unit: 'percentage', - aggregation: 'avg', - }, - 'grid/carbon-intensity': { - description: 'Carbon intensity for the grid', - unit: 'gCO2eq/kWh', - aggregation: 'avg', - }, - 'cloud/instance-type': { - description: 'Type of Cloud Instance name used in the cloud provider APIs', - unit: 'None', - aggregation: 'none', - }, - geolocation: { - description: - 'Geographic location of provider as string (for watt-time model it is provided as latitude and longitude, comma separated, in decimal degrees)', - unit: 'None (decimal degrees for watt-time model)', - aggregation: 'none', - }, - 'carbon-operational': { - description: 'Operational Emissions of the component', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'cpu/name': { - description: 'Name of the physical processor', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region': { - description: 'region cloud instance runs in', - unit: 'None', - aggregation: 'none', - }, - 'cloud/vendor': { - description: - 'Name of the cloud service provider in the ccf model. Can be aws, gcp or azure', - unit: 'None', - aggregation: 'none', - }, - name: { - description: 'arbitrary name parameter.', - unit: 'None', - aggregation: 'none', - }, - 'ram-alloc': { - description: 'refers to GB of memory allocated.', - unit: 'GB', - aggregation: 'avg', - }, - 'ram-util': { - description: 'refers to percentage of memory utilized.', - unit: 'percentage', - aggregation: 'avg', - }, - 'resources-reserved': { - description: 'resources reserved for an application', - unit: 'count', - aggregation: 'none', - }, - 'cpu/thermal-design-power': { - description: 'thermal design power for a processor', - unit: 'kwh', - aggregation: 'avg', - }, - 'device/emissions-embodied': { - description: 'total embodied emissions of some component', - unit: 'gCO2e', - aggregation: 'sum', - }, - timestamp: { - description: 'refers to the time of occurrence of the input', - unit: 'RFC3339', - aggregation: 'none', - }, - 'time-reserved': { - description: 'time reserved for a component', - unit: 'seconds', - aggregation: 'avg', - }, - 'resources-total': { - description: 'total resources available', - unit: 'count', - aggregation: 'none', - }, - 'vcpus-allocated': { - description: 'number of vcpus allocated to particular resource', - unit: 'count', - aggregation: 'none', - }, - 'vcpus-total': { - description: 'total number of vcpus available on a particular resource', - unit: 'count', - aggregation: 'none', - }, - 'memory-available': { - description: 'total amount of memory available on a particular resource', - unit: 'GB', - aggregation: 'none', - }, - 'physical-processor': { - description: - 'name of the physical processor being used in a specific instance type', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-cfe': { - description: 'cloud region name in cfe format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-em-zone-id': { - description: 'cloud region name in electricity maps format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-wt-id': { - description: 'cloud region name in watt-time format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-location': { - description: 'cloud region name in our IF format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-geolocation': { - description: 'location expressed as decimal coordinates (lat/lon)', - unit: 'decimal degrees', - aggregation: 'none', - }, -}; diff --git a/src/config/strings.ts b/src/config/strings.ts deleted file mode 100644 index b6f3410b4..000000000 --- a/src/config/strings.ts +++ /dev/null @@ -1,156 +0,0 @@ -import {ManifestParameter} from '../types/manifest'; - -export const STRINGS = { - MANIFEST_IS_MISSING: 'Manifest is missing.', - MISSING_METHOD: "Initalization param 'method' is missing.", - MISSING_PATH: "Initalization param 'path' is missing.", - UNSUPPORTED_PLUGIN: - "Plugin interface doesn't implement 'execute' or 'metadata' methods.", - OVERRIDE_WARNING: - '\n**WARNING**: You are overriding the IF default parameters file. Please be extremely careful of unintended side-effects in your plugin pipeline!\n', - DISCLAIMER_MESSAGE: ` -Incubation Project - -This project is an incubation project being run inside the Green Software Foundation; as such, we DON’T recommend using it in any critical use case. -Incubation projects are experimental, offer no support guarantee, have minimal governance and process, and may be retired at any moment. This project may one day graduate, in which case this disclaimer will be removed.`, - NOT_NATIVE_PLUGIN: (path: string) => - ` -You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, - INVALID_MODULE_PATH: (path: string, error?: any) => - `Provided module \`${path}\` is invalid or not found. ${error ?? ''} -`, - INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', - UNEXPECTED_TIME_CONFIG: - 'Unexpected node-level config provided for time-sync plugin.', - INVALID_TIME_INTERVAL: 'Interval is missing.', - AVOIDING_PADDING: (description: string) => - `Avoiding padding at ${description}`, - AVOIDING_PADDING_BY_EDGES: (start: boolean, end: boolean) => - `Avoiding padding at ${ - start && end ? 'start and end' : start ? 'start' : 'end' - }`, - INVALID_AGGREGATION_METHOD: (metric: string) => - `Aggregation is not possible for given ${metric} since method is 'none'.`, - METRIC_MISSING: (metric: string, index: number) => - `Aggregation metric ${metric} is not found in inputs[${index}].`, - INVALID_GROUP_BY: (type: string) => `Invalid group ${type}.`, - REJECTING_OVERRIDE: (param: ManifestParameter) => - `Rejecting overriding of canonical parameter: ${param.name}.`, - INVALID_EXHAUST_PLUGIN: (pluginName: string) => - `Invalid exhaust plugin: ${pluginName}.`, - UNKNOWN_PARAM: (name: string) => - `Unknown parameter: ${name}. Using 'sum' aggregation method.`, - NOT_INITALIZED_PLUGIN: (name: string) => - `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`, - NO_OUTPUT: ` -You have not selected an output method. To see your output data, you can choose from: ---stdout: this will print your output data to the console ---output : this will save your output data to the given filepath (do not provide file extension) -Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`, - SOURCE_IS_NOT_YAML: 'Given source file is not in yaml format.', - TARGET_IS_NOT_YAML: 'Given target file is not in yaml format.', - INVALID_TARGET: 'Target is invalid.', - INVALID_SOURCE: 'Source is invalid.', - UNSUPPORTED_ERROR: (errorName: string) => - `UnsupportedErrorClass: plugin threw error class: ${errorName} that is not recognized by Impact Framework`, - /** Plugin messages */ - MISSING_GLOBAL_CONFIG: 'Global config is not provided.', - MISSING_INPUT_DATA: (param: string) => - `${param} is missing from the input array, or has nullish value.`, - MANIFEST_NOT_FOUND: 'Manifest file not found.', - INITIALIZING_PACKAGE_JSON: 'Initializing package.json.', - INSTALLING_NPM_PACKAGES: 'Installing npm packages...', - NOT_NUMERIC_VALUE: (str: any) => `${str} is not numberic.`, - MISSING_FUNCTIONAL_UNIT_CONFIG: - '`functional-unit` should be provided in your global config', - MISSING_FUNCTIONAL_UNIT_INPUT: - '`functional-unit` value is missing from input data or it is not a positive integer', - REGEX_MISMATCH: (input: any, match: string) => - `\`${input}\` does not match the ${match} regex expression`, - SCI_EMBODIED_ERROR: (unit: string) => - `invalid number. please provide it as \`${unit}\` to input`, - MISSING_MIN_MAX: 'Config is missing min or max value', - INVALID_MIN_MAX: (name: string) => - `Min value should not be greater than or equal to max value of ${name}`, - FILE_FETCH_FAILED: ( - filepath: string, - message: string - ) => `Failed fetching the file: ${filepath}. -${message}`, - FILE_READ_FAILED: ( - filepath: string, - error: string - ) => `Failed reading the file: ${filepath}. -${error}`, - MISSING_CSV_COLUMN: (columnName: string) => - `There is no column with the name: ${columnName}.`, - NO_QUERY_DATA: - 'One or more of the given query parameters are not found in the target CSV file column headers.', - INVALID_DATE_TYPE: (date: any) => - `Unexpected date datatype: ${typeof date}: ${date}`, - INVALID_OBSERVATION_OVERLAP: - 'Observation timestamps overlap, please check inputs.', - SCI_MISSING_FN_UNIT: (functionalUnit: string) => - `'carbon' and ${functionalUnit} should be present in your input data.`, - /** Exhaust messages */ - OUTPUT_REQUIRED: - 'Output path is required, please make sure output is configured properly.', - CSV_EXPORT: - 'CSV export criteria is not found in output path. Please append it after --output #.', - WRITE_CSV_ERROR: (outputPath: string, error: any) => - `Failed to write CSV file to ${outputPath}: ${error}`, - INVALID_NAME: - '`name` global config parameter is empty or contains all spaces', - START_LOWER_END: '`start-time` should be lower than `end-time`', - TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, - INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, - X_Y_EQUAL: 'The length of `x` and `y` should be equal', - ARRAY_LENGTH_NON_EMPTY: - 'the length of the input arrays must be greater than 1', - WITHIN_THE_RANGE: - 'The target x value must be within the range of the given x values', - /** Debugging logs */ - STARTING_IF: 'Starting IF', - EXITING_IF: 'Exiting IF', - LOADING_MANIFEST: 'Loading manifest', - VALIDATING_MANIFEST: 'Validating manifest', - CAPTURING_RUNTIME_ENVIRONMENT_DATA: 'Capturing runtime environment data', - SYNCING_PARAMETERS: 'Syncing parameters', - CHECKING_AGGREGATION_METHOD: (unitName: string) => - `Checking aggregation method for ${unitName}`, - INITIALIZING_PLUGINS: 'Initializing plugins', - INITIALIZING_PLUGIN: (pluginName: string) => `Initializing ${pluginName}`, - LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => - `Loading ${pluginName} from ${path}`, - COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => - `Computing pipeline for \`${nodeName}\``, - MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', - AGGREGATING_OUTPUTS: 'Aggregating outputs', - AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, - PREPARING_OUTPUT_DATA: 'Preparing output data', - EXPORTING_TO_YAML_FILE: (savepath: string) => - `Exporting to yaml file: ${savepath}`, - EXPORTING_TO_CSV_FILE: (savepath: string) => - `Exporting to csv file: ${savepath}`, - EXPORTING_RAW_CSV_FILE: (savepath: string) => - `Exporting raw csv file: ${savepath}`, - CHECKING: 'Checking...', - IF_CHECK_FLAGS_MISSING: - 'Either the `--manifest` or `--directory` command should be provided with a path', - DIRECTORY_NOT_FOUND: 'Directory not found.', - DIRECTORY_YAML_FILES_NOT_FOUND: - 'The directory does not contain any YAML/YML files.\n', - IF_CHECK_EXECUTING: (filename: string) => `Executing \`${filename}\``, - IF_CHECK_VERIFICATION_FAILURES: - '---------\nif-check verification failures:\n', - IF_CHECK_FAILED: (filename: string) => - `✖ if-check could not verify ${filename}. The re-executed file does not match the original.\n`, - IF_CHECK_VERIFIED: (filename: string) => - `✔ if-check successfully verified ${filename}\n`, - IF_CHECK_SUMMARY_ERROR_MESSAGE: (filename: string, message: string) => - `Executing \`${filename}\`\n✖ ${message}`, - IF_CHECK_SUMMARY_LOG: (passedCount: number, totalCount: number) => - `---------\nCheck summary:\n${passedCount} of ${totalCount} files are passed.\n`, - ZERO_DIVISION: (moduleName: string, index: number) => - `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, -}; From bf875dcee5a92ee4253eff6d6d3472aaee4a16bb Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:17:56 +0400 Subject: [PATCH 319/863] feat(src): init common utils --- src/common/util/debug-logger.ts | 134 ++++++++++++++++++++++++++++ src/common/util/fs.ts | 68 ++++++++++++++ src/common/util/helpers.ts | 21 +++++ src/common/util/logger.ts | 22 +++++ src/common/util/validations.ts | 153 ++++++++++++++++++++++++++++++++ src/common/util/yaml.ts | 36 ++++++++ 6 files changed, 434 insertions(+) create mode 100644 src/common/util/debug-logger.ts create mode 100644 src/common/util/fs.ts create mode 100644 src/common/util/helpers.ts create mode 100644 src/common/util/logger.ts create mode 100644 src/common/util/validations.ts create mode 100644 src/common/util/yaml.ts diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts new file mode 100644 index 000000000..f91f0e9c9 --- /dev/null +++ b/src/common/util/debug-logger.ts @@ -0,0 +1,134 @@ +import {STRINGS} from '../../if-run/config'; + +const logMessagesKeys: (keyof typeof STRINGS)[] = [ + 'STARTING_IF', + 'EXITING_IF', + 'LOADING_MANIFEST', + 'VALIDATING_MANIFEST', + 'CAPTURING_RUNTIME_ENVIRONMENT_DATA', + 'SYNCING_PARAMETERS', + 'CHECKING_AGGREGATION_METHOD', + 'INITIALIZING_PLUGINS', + 'INITIALIZING_PLUGIN', + 'LOADING_PLUGIN_FROM_PATH', + 'COMPUTING_PIPELINE_FOR_NODE', + 'MERGING_DEFAULTS_WITH_INPUT_DATA', + 'AGGREGATING_OUTPUTS', + 'AGGREGATING_NODE', + 'PREPARING_OUTPUT_DATA', + 'EXPORTING_TO_YAML_FILE', + 'EXPORTING_TO_CSV_FILE', + 'EXPORTING_RAW_CSV_FILE', +]; + +enum LogLevel { + Info = 'INFO', + Warn = 'WARN', + Error = 'ERROR', + Debug = 'DEBUG', +} + +const originalConsole = { + log: console.log, + info: console.info, + warn: console.warn, + error: console.error, + debug: console.debug, +}; + +/** + * Overrides console methods with custom debug logging. + */ +const overrideConsoleMethods = (debugMode: boolean) => { + console.log = (...args: any[]) => debugLog(LogLevel.Info, args, debugMode); + console.info = (...args: any[]) => debugLog(LogLevel.Info, args, debugMode); + console.warn = (...args: any[]) => debugLog(LogLevel.Warn, args, debugMode); + console.error = (...args: any[]) => debugLog(LogLevel.Error, args, debugMode); + console.debug = (...args: any[]) => debugLog(LogLevel.Debug, args, debugMode); +}; + +/** + * Creates an encapsulated object to retrieve the plugin name. + */ +const pluginNameManager = (() => { + let pluginName: string | undefined = ''; + + const manager = { + get currentPluginName() { + return pluginName; + }, + set currentPluginName(value: string | undefined) { + pluginName = value; + }, + }; + + return manager; +})(); + +/** + * Sets the name of the currently executing plugin. + */ +const setExecutingPluginName = (pluginName?: string) => { + pluginNameManager.currentPluginName = pluginName; +}; + +/** + * Logs messages with the specified log level and format. + */ +const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { + if (!debugMode) { + if (level === LogLevel.Debug) { + return; + } + + const isDebugLog = + typeof args[0] === 'string' && + logMessagesKeys.some(key => { + const message = + typeof STRINGS[key] === 'function' + ? (STRINGS[key] as Function).call(null, '') + : (STRINGS[key] as string); + + return args[0].includes(message); + }); + + if (!isDebugLog) { + originalConsole.log(...args); + } + + return; + } + + if (args[0].includes('# start')) { + originalConsole.log(...args); + return; + } + + const date = new Date().toISOString(); + const plugin = pluginNameManager.currentPluginName; + const formattedMessage = `${level}: ${date}: ${ + plugin ? plugin + ': ' : '' + }${args.join(', ')}`; + + if (debugMode) { + switch (level) { + case LogLevel.Info: + originalConsole.info(formattedMessage); + break; + case LogLevel.Warn: + originalConsole.warn(formattedMessage); + break; + case LogLevel.Error: + originalConsole.error(formattedMessage); + break; + case LogLevel.Debug: + originalConsole.debug(formattedMessage); + break; + } + } +}; + +export const debugLogger = { + overrideConsoleMethods, + setExecutingPluginName, +}; diff --git a/src/common/util/fs.ts b/src/common/util/fs.ts new file mode 100644 index 000000000..bf10af9ba --- /dev/null +++ b/src/common/util/fs.ts @@ -0,0 +1,68 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +/** + * Checks if file exists with the given `filePath`. + */ +export const isFileExists = async (filePath: string) => { + try { + await fs.stat(filePath); + return true; + } catch (error) { + return false; + } +}; + +/** + * Checks if the directory exists with the given `filePath`. + */ +export const isDirectoryExists = async (directoryPath: string) => { + try { + await fs.access(directoryPath); + return true; + } catch (error) { + return false; + } +}; + +/** + * Gets all files that have either .yml or .yaml extension in the given directory. + */ +export const getYamlFiles = async (directory: string) => { + let yamlFiles: string[] = []; + + const files = await fs.readdir(directory); + + for (const file of files) { + const fullPath = path.join(directory, file); + const stat = await fs.lstat(fullPath); + + if (stat.isDirectory()) { + yamlFiles = yamlFiles.concat(await getYamlFiles(fullPath)); + } else { + if (file.endsWith('.yml') || file.endsWith('.yaml')) { + yamlFiles.push(fullPath); + } + } + } + + return yamlFiles; +}; + +/** + * Gets fileName from the given path without an extension. + */ +export const getFileName = (filePath: string) => { + const baseName = path.basename(filePath); + const extension = path.extname(filePath); + return baseName.replace(extension, ''); +}; + +/** + * Removes the given file if exists. + */ +export const removeFileIfExists = async (filePath: string) => { + if (await isFileExists(filePath)) { + await fs.unlink(filePath); + } +}; diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts new file mode 100644 index 000000000..8399e5b3e --- /dev/null +++ b/src/common/util/helpers.ts @@ -0,0 +1,21 @@ +import {exec} from 'child_process'; +import * as path from 'path'; +import {promisify} from 'util'; + +/** + * Promise version of Node's `exec` from `child-process`. + */ +export const execPromise = promisify(exec); + +/** + * Prepends process path to given `filePath`. + */ +export const prependFullFilePath = (filePath: string) => { + const processRunningPath = process.cwd(); + + if (path.isAbsolute(filePath)) { + return filePath; + } + + return path.normalize(`${processRunningPath}/${filePath}`); +}; diff --git a/src/common/util/logger.ts b/src/common/util/logger.ts new file mode 100644 index 000000000..4d01d5960 --- /dev/null +++ b/src/common/util/logger.ts @@ -0,0 +1,22 @@ +import * as winston from 'winston'; + +const {combine, timestamp, printf, colorize, align} = winston.format; + +/** + * Winston logger instance. + */ +export const logger = winston.createLogger({ + format: combine( + colorize({all: true}), + timestamp({ + format: 'YYYY-MM-DD hh:mm:ss.SSS A', + }), + align(), + printf( + (info: any) => + `[${info.timestamp}] ${info.level}: ${info.message} +${info.stack || ''}` + ) + ), + transports: [new winston.transports.Console()], +}); diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts new file mode 100644 index 000000000..cb92e974f --- /dev/null +++ b/src/common/util/validations.ts @@ -0,0 +1,153 @@ +import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../if-run/config'; + +import {AGGREGATION_METHODS} from '../../if-run/types/aggregation'; +import {AGGREGATION_TYPES} from '../../if-run/types/parameters'; + +const {ManifestValidationError, InputValidationError} = ERRORS; +const {VALIDATING_MANIFEST} = STRINGS; + +/** + * At least one property defined handler. + */ +export const atLeastOneDefined = ( + obj: Record +) => Object.values(obj).some(v => v !== undefined); + +/** + * All properties are defined handler. + */ +export const allDefined = (obj: Record) => + Object.values(obj).every(v => v !== undefined); + +/** + * Validation schema for manifests. + */ +export const manifestSchema = z.object({ + name: z.string(), + description: z.string().optional().nullable(), + tags: z + .object({ + kind: z.string().optional().nullable(), + complexity: z.string().optional().nullable(), + category: z.string().optional().nullable(), + }) + .optional() + .nullable(), + aggregation: z + .object({ + metrics: z.array(z.string()), + type: z.enum(AGGREGATION_METHODS), + }) + .optional() + .nullable(), + params: z + .array( + z.object({ + name: z.string(), + description: z.string(), + aggregation: z.enum(AGGREGATION_TYPES), + unit: z.string(), + }) + ) + .optional() + .nullable(), + initialize: z.object({ + plugins: z.record( + z.string(), + z.object({ + path: z.string(), + method: z.string(), + 'global-config': z.record(z.string(), z.any()).optional(), + }) + ), + outputs: z.array(z.string()).optional(), + }), + execution: z + .object({ + command: z.string().optional(), + environment: z + .object({ + 'if-version': z.string(), + os: z.string(), + 'os-version': z.string(), + 'node-version': z.string(), + 'date-time': z.string(), + dependencies: z.array(z.string()), + }) + .optional(), + status: z.string(), + error: z.string().optional(), + }) + .optional(), + tree: z.record(z.string(), z.any()), +}); + +/** + * Validates given `manifest` object to match pattern. + */ +export const validateManifest = (manifest: any) => { + console.debug(VALIDATING_MANIFEST); + + return validate(manifestSchema, manifest, undefined, ManifestValidationError); +}; + +/** + * Validates given `object` with given `schema`. + */ +export const validate = ( + schema: ZodSchema, + object: any, + index?: number, + errorConstructor: ErrorConstructor = InputValidationError +) => { + const validationResult = schema.safeParse(object); + + if (!validationResult.success) { + throw new errorConstructor( + prettifyErrorMessage(validationResult.error.message, index) + ); + } + + return validationResult.data; +}; + +/** + * Error message formatter for zod issues. + */ +const prettifyErrorMessage = (issues: string, index?: number) => { + const issuesArray = JSON.parse(issues); + + return issuesArray.map((issue: ZodIssue) => { + const code = issue.code; + let {path, message} = issue; + + const indexErrorMessage = index !== undefined ? ` at index ${index}` : ''; + + if (issue.code === ZodIssueCode.invalid_union) { + message = issue.unionErrors[0].issues[0].message; + path = issue.unionErrors[0].issues[0].path; + } + + const fullPath = flattenPath(path); + + if (!fullPath) { + return message; + } + + return `"${fullPath}" parameter is ${message.toLowerCase()}${indexErrorMessage}. Error code: ${code}.`; + }); +}; + +/** + * Flattens an array representing a nested path into a string. + */ +const flattenPath = (path: (string | number)[]): string => { + const flattenPath = path.map(part => + typeof part === 'number' ? `[${part}]` : part + ); + + return flattenPath.join('.'); +}; diff --git a/src/common/util/yaml.ts b/src/common/util/yaml.ts new file mode 100644 index 000000000..beaedd71f --- /dev/null +++ b/src/common/util/yaml.ts @@ -0,0 +1,36 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import * as YAML from 'js-yaml'; + +/** + * Reads and parses `yaml` file to object. + */ +export const openYamlFileAsObject = async (filePath: string): Promise => { + const yamlFileBuffer = await fs.readFile(filePath, 'utf8'); + + return YAML.load(yamlFileBuffer) as T; +}; + +/** + * Saves given `yaml` dump as a file. + */ +export const saveYamlFileAs = async (object: any, pathToFile: string) => { + const dirPath = path.dirname(pathToFile); + await fs.mkdir(dirPath, {recursive: true}); + const yamlString = YAML.dump(object, {noRefs: true}); + + return fs.writeFile(pathToFile, yamlString); +}; + +/** + * Checks if given `fileName` is yaml. + */ +export const checkIfFileIsYaml = (fileName: string) => { + const yamlFileTypes = ['yaml', 'yml']; + const splittedParts = fileName.split('.'); + const lastIndex = splittedParts.length - 1; + const extension = splittedParts[lastIndex]; + + return yamlFileTypes.includes(extension); +}; From 08cb44c3978a8eed947b1ce3e65ce7c903b3f6a0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:18:04 +0400 Subject: [PATCH 320/863] feat(src): init common types --- src/common/types/manifest.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/common/types/manifest.ts diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts new file mode 100644 index 000000000..2359a3433 --- /dev/null +++ b/src/common/types/manifest.ts @@ -0,0 +1,18 @@ +import {z} from 'zod'; + +import {manifestSchema} from '../util/validations'; + +export type Manifest = z.infer; + +export type GlobalPlugins = Manifest['initialize']['plugins']; + +export type PluginOptions = GlobalPlugins[string]; + +export type AggregationParams = Manifest['aggregation']; +export type AggregationParamsSure = Extract; + +export type Context = Omit; + +export type ContextWithExec = Omit; + +export type ManifestParameter = Extract[number]; From c3a56edd51cb64f6496c5aeb51af372b85f3956e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:18:10 +0400 Subject: [PATCH 321/863] feat(src): init common lib --- src/common/lib/load.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/common/lib/load.ts diff --git a/src/common/lib/load.ts b/src/common/lib/load.ts new file mode 100644 index 000000000..02b44aef1 --- /dev/null +++ b/src/common/lib/load.ts @@ -0,0 +1,30 @@ +import {openYamlFileAsObject} from '../util/yaml'; +import {readAndParseJson} from '../../if-run/util/json'; + +import {PARAMETERS} from '../../if-run/config'; +import {STRINGS} from '../../if-run/config'; + +import {Parameters} from '../../if-run/types/parameters'; + +const {LOADING_MANIFEST} = STRINGS; + +/** + * Parses manifest file as an object. Checks if parameter file is passed via CLI, then loads it too. + * Returns context, tree and parameters (either the default one, or from CLI). + */ +export const load = async (inputPath: string, paramPath?: string) => { + console.debug(LOADING_MANIFEST); + + const rawManifest = await openYamlFileAsObject(inputPath); + const parametersFromCli = + paramPath && + (await readAndParseJson(paramPath)); /** @todo validate json */ + const parameters = + parametersFromCli || + PARAMETERS; /** @todo PARAMETERS should be specified in parameterize only */ + + return { + rawManifest, + parameters, + }; +}; From 10e4655a3762b5fd406f58892f2b6e0561b08f10 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:18:17 +0400 Subject: [PATCH 322/863] feat(src): init common config --- src/common/config/index.ts | 1 + src/common/config/strings.ts | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/common/config/index.ts create mode 100644 src/common/config/strings.ts diff --git a/src/common/config/index.ts b/src/common/config/index.ts new file mode 100644 index 000000000..3ee9fecbb --- /dev/null +++ b/src/common/config/index.ts @@ -0,0 +1 @@ +export {STRINGS} from './strings'; diff --git a/src/common/config/strings.ts b/src/common/config/strings.ts new file mode 100644 index 000000000..b68d5ce7c --- /dev/null +++ b/src/common/config/strings.ts @@ -0,0 +1,12 @@ +export const STRINGS = { + DISCLAIMER_MESSAGE: ` +Incubation Project + +This project is an incubation project being run inside the Green Software Foundation; as such, we DON’T recommend using it in any critical use case. +Incubation projects are experimental, offer no support guarantee, have minimal governance and process, and may be retired at any moment. This project may one day graduate, in which case this disclaimer will be removed.`, + SOURCE_IS_NOT_YAML: 'Given source file is not in yaml format.', + TARGET_IS_NOT_YAML: 'Given target file is not in yaml format.', + MANIFEST_NOT_FOUND: 'Manifest file not found.', + SUCCESS_MESSAGE: 'The environment is successfully setup!', + MANIFEST_IS_MISSING: 'Manifest is missing.', +}; From 6e2f94761df1a43b89e04ae9f4a896093f27e74e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:19:34 +0400 Subject: [PATCH 323/863] revert(src): drop old builtins folder --- src/builtins/README.md | 848 ------------------ src/builtins/coefficient/README.md | 110 --- src/builtins/coefficient/index.ts | 86 -- src/builtins/copy-param/README.md | 104 --- src/builtins/copy-param/index.ts | 90 -- src/builtins/csv-lookup/README.md | 180 ---- src/builtins/csv-lookup/index.ts | 247 ----- src/builtins/divide/README.md | 121 --- src/builtins/divide/index.ts | 109 --- src/builtins/exponent/README.md | 117 --- src/builtins/exponent/index.ts | 81 -- src/builtins/export-csv-raw.ts | 156 ---- src/builtins/export-csv.ts | 117 --- src/builtins/export-log.ts | 21 - src/builtins/export-yaml.ts | 36 - src/builtins/group-by.ts | 95 -- src/builtins/index.ts | 16 - src/builtins/interpolation/README.md | 196 ---- src/builtins/interpolation/index.ts | 197 ---- src/builtins/mock-observations/README.md | 97 -- .../helpers/common-generator.ts | 33 - .../helpers/rand-int-generator.ts | 68 -- src/builtins/mock-observations/index.ts | 178 ---- .../mock-observations/interfaces/index.ts | 6 - src/builtins/multiply/README.md | 109 --- src/builtins/multiply/index.ts | 84 -- src/builtins/regex/README.md | 121 --- src/builtins/regex/index.ts | 96 -- src/builtins/sci-embodied/README.md | 124 --- src/builtins/sci-embodied/index.ts | 130 --- src/builtins/sci/README.md | 112 --- src/builtins/sci/config.ts | 40 - src/builtins/sci/index.ts | 91 -- src/builtins/shell/README.md | 141 --- src/builtins/shell/index.ts | 65 -- src/builtins/subtract/README.md | 105 --- src/builtins/subtract/index.ts | 88 -- src/builtins/sum/README.md | 118 --- src/builtins/sum/index.ts | 88 -- src/builtins/time-sync.ts | 459 ---------- 40 files changed, 5280 deletions(-) delete mode 100644 src/builtins/README.md delete mode 100644 src/builtins/coefficient/README.md delete mode 100644 src/builtins/coefficient/index.ts delete mode 100644 src/builtins/copy-param/README.md delete mode 100644 src/builtins/copy-param/index.ts delete mode 100644 src/builtins/csv-lookup/README.md delete mode 100644 src/builtins/csv-lookup/index.ts delete mode 100644 src/builtins/divide/README.md delete mode 100644 src/builtins/divide/index.ts delete mode 100644 src/builtins/exponent/README.md delete mode 100644 src/builtins/exponent/index.ts delete mode 100644 src/builtins/export-csv-raw.ts delete mode 100644 src/builtins/export-csv.ts delete mode 100644 src/builtins/export-log.ts delete mode 100644 src/builtins/export-yaml.ts delete mode 100644 src/builtins/group-by.ts delete mode 100644 src/builtins/index.ts delete mode 100644 src/builtins/interpolation/README.md delete mode 100644 src/builtins/interpolation/index.ts delete mode 100644 src/builtins/mock-observations/README.md delete mode 100644 src/builtins/mock-observations/helpers/common-generator.ts delete mode 100644 src/builtins/mock-observations/helpers/rand-int-generator.ts delete mode 100644 src/builtins/mock-observations/index.ts delete mode 100644 src/builtins/mock-observations/interfaces/index.ts delete mode 100644 src/builtins/multiply/README.md delete mode 100644 src/builtins/multiply/index.ts delete mode 100644 src/builtins/regex/README.md delete mode 100644 src/builtins/regex/index.ts delete mode 100644 src/builtins/sci-embodied/README.md delete mode 100644 src/builtins/sci-embodied/index.ts delete mode 100644 src/builtins/sci/README.md delete mode 100644 src/builtins/sci/config.ts delete mode 100644 src/builtins/sci/index.ts delete mode 100644 src/builtins/shell/README.md delete mode 100644 src/builtins/shell/index.ts delete mode 100644 src/builtins/subtract/README.md delete mode 100644 src/builtins/subtract/index.ts delete mode 100644 src/builtins/sum/README.md delete mode 100644 src/builtins/sum/index.ts delete mode 100644 src/builtins/time-sync.ts diff --git a/src/builtins/README.md b/src/builtins/README.md deleted file mode 100644 index c37e143a1..000000000 --- a/src/builtins/README.md +++ /dev/null @@ -1,848 +0,0 @@ -# IF builtins - -There are three built-in features of IF: - -- time-sync -- CSV exporter -- groupby - -On this page, you can find the documentation for each of these three builtins. - -## Time-sync - -Time sync standardizes the start time, end time and temporal resolution of all output data across an entire tree. - -### Parameters - -### Plugin config - -The following should be defined in the plugin initialization: - -- `start-time`: global start time as ISO 8061 string -- `stop`: global end time as ISO 8061 string -- `interval`: temporal resolution in seconds -- `error-on-padding`: avoid zero/'zeroish' padding (if needed) and error out instead. `False` by defult. - -#### Inputs: - -- `inputs`: an array of observations - -#### Returns - -- `inputs`: time-synchronized version of the tree - - - - -#### Overview - -A manifest file for a tree might contain many nodes each representing some different part of an application's stack or even different applications running on different machines. It is therefore common to have time series data in each component that is not directly comparable to other components either because the temporal resolution of the data is different, they cover different periods, or there are gaps in some records (e.g. some apps might burst but then go dormant, while others run continuously). This makes post-hoc visualization, analysis and aggregation of data from groups of nodes difficult to achieve. To address this, we created a time synchronization plugin that takes in non-uniform times series and snaps them all to a regular timeline with uniform start time, end time and temporal resolution. - -We do this by implementing the following logic: - -- Shift readings to nearest whole seconds -- Upsample the time series to a base resolution (1s) -- Resample to desired resolution by batching 1s entries -- Extrapolate or trim to ensure all time series share global start and end dates - -The next section explains each stage in more detail. - -#### Details - -##### Upsampling rules - -A set of `inputs` is naturally a time series because all `observations` include a `timestamp` and a `duration`, measured in seconds. -For each `observation` in `inputs` we check whether the duration is greater than 1 second. If `duration` is greater than 1 second, we create N new `observation` objects, where N is equal to `duration`. This means we have an `observation` for every second between the initial timestamp and the end of the observation period. Each new object receives a timestamp incremented by one second. - -This looks as follows: - -```ts -[{timestamp: '2023-12-12T00:00:00.000Z', duration: 5}] - -# becomes -[ - {timestamp: '2023-12-12T00:00:01.000Z', duration: 1} - {timestamp: '2023-12-12T00:00:02.000Z', duration: 1} - {timestamp: '2023-12-12T00:00:03.000Z', duration: 1} - {timestamp: '2023-12-12T00:00:04.000Z', duration: 1} - {timestamp: '2023-12-12T00:00:05.000Z', duration: 1} -] -``` - -Each `observation` actually includes many key-value pairs. The precise content of the `observation` is not known until runtime because it depends on which plugins have been included in the pipeline. Different values have to be treated differently when we upsample in time. The method we use to upsample depends on the `aggregation-method` defined for each key in `units.yml`. - -If the right way to aggregate a value is to sum it, then the right way to upsample it is to divide by `duration`, effectively spreading the total out evenly across the new, higher resolution, `observations` so that the total across the same bucket of time is unchanged (i.e. if the total for some value is 10 when there is one entry with `duration = 10s`, then the total should still be 10 when there are 10 entries each witch `duration = 1s`). - -On the other hand, if the right way to aggregate a value is to take its average over some time period, the value should be copied unchanged into the newly upsampled `observations`. This is appropriate for values that are proportional or percentages, such as `cpu/utilization`. Treating these values as constants means the average over the `duration` for an observation is identical whether you consider the initial `observation` or the upsampled set of N `observation`s. - -Constants can simply be copied as-is, because they are constants. Examples might be the `grid/carbon-intensity` - this value does not change depending on how frequently you observe it. - -Therefore, we apply this logic and the resulting flow looks as follows (the `aggregation-method` for `carbon` and `energy` is `sum`, `grid/carbon-intensity` is a constant and `cpu/utilization` is expressed as a percentage): - -```ts -[{timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, 'grid/carbon-intensity': 471}] - -# becomes - -[ - {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, - {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, - {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, - {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, - {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471}, - {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, 'grid/carbon-intensity': 471} -] -``` - -The end result is that for each `observation`, we upsample the time series to yield 1 second resolution data between `timestamp` and `timestamp + duration`. - -##### Gap-filling - -Sometimes there might be discontinuities in the time series between one `observation` and another. For example we might have two `observations` in a set of `inputs` that have timestamps spaced 10 seconds apart, but the `duration` of the first `observation` is only 5 seconds. in this case, 5 seconds of data are unaccounted for and create a discontinuity in the time series. - -To solve this problem, for all but the first `observation` in the `inputs` array, we grab the `timestamp` and `duration` from the previous `observation` and check that `timestamp[N] + duration[N] == timestamp[N+1]`. If this condition is not satisfied, we backfill the missing data with a "zero-observation" which is identical to the surrounding observations except any values whose `aggregation-method` is `sum` are set to zero. This is equivalent to assuming that when there is no data available, the app being monitored is switched off. - -The end result of this gap-filling is that we have continuous 1 second resolution data that can be resampled to a new temporal resolution. - -```ts -[ - {timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:08.000Z', duration: 2, 'cpu/utilization': 12, carbon: 5, energy: 10, grid/carbon-intensity: 471} -] - -# There are 2 seconds of missing data between the end of timestamp[0] + duration, and timestamp[1] -# After expansion and infilling, the array becomes: - -[ - {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:06.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:07.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:08.000Z', duration: 1, 'cpu/utilization': 12, carbon: 2.5, energy: 5, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:09.000Z', duration: 1, 'cpu/utilization': 12, carbon: 2.5, energy: 5, grid/carbon-intensity: 471} -] -``` - -Note that when `error-on-padding` is `true` no gap-filling is performed and the plugin will error out instead. - -##### Trimming and padding - -To ensure parity across all the components in a tree, we need to synchronize the start and end times for all time series. To do this, we pass the `time-sync` plugin plugin some global config: `startTime`, `endTime` and `interval`. The `startTime` is the timestamp where _all_ input arrays across the entire tree should begin, and `endTime` is the timestamp where _all_ input arrays across the entire tree should end. `interval` is the time resolution we ultimately want to resample to. - -To synchronize the time series start and end we check the first element of `inputs` for each node in the tree and determine whether it is earlier, later or equal to the global start time. If it is equal then no action is required. If the `input` start time is earlier than the global start time, we simply discard entries from the front of the array until the start times are aligned. If the `input` start time is after the global start time, then we pad with our "zero-observation" object - one for every second separating the global start time from the `input` start time. The same process is repeated for the end time - we either trim away `input` data or pad it out with "zero-observation" objects. - -For example, for `startTime = 2023-12-12T00:00:00.000Z` and `endTime = 2023-12-12T00:00:15.000Z`: - -```ts -[ - {timestamp: '2023-12-12T00:00:05.000Z', duration: 5, 'cpu/utilization': 12, carbon: 5, energy: 10, 'grid/carbon-intensity': 471}, -] - -# There are 5 seconds missing from the start and end. After padding, the array becomes: - -[ - {timestamp: '2023-12-12T00:00:00.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:01.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:02.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:03.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:04.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:05.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:06.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:07.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:08.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:09.000Z', duration: 1, 'cpu/utilization': 12, carbon: 1, energy: 2, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:10.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:11.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:12.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:13.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - {timestamp: '2023-12-12T00:00:14.000Z', duration: 1, 'cpu/utilization': 0, carbon: 0, energy: 0, grid/carbon-intensity: 471}, - -] -``` - -Note that when `error-on-padding` is `true` no padding is performed and the plugin will error out instead. - -##### Resampling rules - -Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `intervalk` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `params.ts`. The returned array is the final, synchronized time series at the desired temporal resolution. - - -#### Assumptions and limitations - -To do time synchronization, we assume: - -- There is no environmental impact for an application when there is no data available. -- Evenly distributing the total for a `duration` across higher resolution `observations` is appropriate, as opposed to having some non-uniform distribution. - - -### Typescript implementation - - -To run the plugin, you must first create an instance of `TimeSync`. -Then, you can call `execute()`. - -```typescript -const globalConfig = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:00:30.000Z', - interval: 10 -} -const timeSync = TimeSync(globalConfig); -const results = timeSync.execute([ - { - timestamp: '2023-12-12T00:00:00.000Z' - duration: 10 - 'cpu/utilization': 10 - carbon: 100 - energy: 100 - requests: 300 - }, - { - timestamp: '2023-12-12T00:00:10.000Z' - duration: 10 - 'cpu/utilization': 20 - carbon: 100, - energy: 100, - requests: 380 - } -]) -``` - -### Example manifest - -IF users will typically call the plugin as part of a pipeline defined in an `manifest` -file. In this case, instantiating and configuring 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 `time-sync`: - -```yaml -name: time-sync-demo -description: impl with 2 levels of nesting with non-uniform timing of observations -tags: -initialize: - plugins: - teads-curve: - method: TeadsCurve - path: '@grnsft/if-unofficial-plugins' - sci-e: - method: SciE - path: '@grnsft/if-plugins' - sci-embodied: - path: 'builtin' - method: SciEmbodied - sci-o: - method: SciO - path: '@grnsft/if-plugins' - time-sync: - method: TimeSync - path: builtin - global-config: - start-time: '2023-12-12T00:00:00.000Z' # ISO timestamp - end-time: '2023-12-12T00:01:00.000Z' # ISO timestamp - interval: 5 # seconds -tree: - children: - child: # an advanced grouping node - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - config: - teads-curve: - cpu/thermal-design-power: 65 - sci-embodied: - device/emissions-embodied: 251000 # gCO2eq - time-reserved: 3600 # 1 hour in s - device/expected-lifespan: 126144000 # 4 years in seconds - resources-reserved: 1 - resources-total: 1 - sci-o: - grid/carbon-intensity: 457 # gCO2/kwh - children: - child-1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 10 - cpu/utilization: 10 - carbon: 100 - energy: 100 - requests: 300 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 10 - cpu/utilization: 20 - carbon: 200 - energy: 200 - requests: 380 -``` - - -## CSV Exporter - -IF supports exporting data to CSV files. This provides users with a data format that enables visualization and data analysis using standard data analysis tools. - -### Manifest config - -To export your data to a CSV file, you have to provide a small piece of config data to your manifest file: - -```yaml -initialize: - outputs: - - csv -``` - -You can also add `- yaml` if you want to export to both `yaml` and `csv` simultaneously. - -### CLI command - -Then, you must select the metric you want to export to CSV. The name of that metric must be added to the savepath provided to the `--output` command in the CLI, after a hashtag. - -For example, to export the `carbon` data from your tree to a CSV file: - -```sh -if-run --manifest example.yml --output example#carbon -``` - -This will save a CSV file called `example.csv`. The contents will look similar to the following: - -| | | | | | -| ---------------------------------------------- | ---------------- | ---------------------------- | ---------------------------- | ---------------------------- | -| **Path** | **Aggregated** | **2024-03-05T00:00:00.000Z** | **2024-03-05T00:05:00.000Z** | **2024-03-05T00:10:00.000Z** | -| tree.carbon | 425.289232008725 | 17.9269877157543 | 8.9024388783018 | 45.6021901509012 | -| tree.children.westus3.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | -| tree.children.westus3.children.server-1.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | -| tree.children.france.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | -| tree.children.france.children.server-2.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | - - -### Comparing CSV to Yaml - -The CSV above is generated from the following yaml. The `carbon` metric is extracted and added to the CSV. Otherwise, the CSV is an exact representation of the following yaml tree. You can see that the CSV representation is *much* easier to understand than the full yaml tree: - -```yaml -tree: - pipeline: - - mock-observations - - group-by - - cloud-metadata - - time-sync - - watttime - - teads-curve - - operational-carbon - defaults: - grid/carbon-intensity: 500 - config: - group-by: - group: - - cloud/region - - name - children: - westus3: - children: - server-1: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 66 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 4 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 54 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 19 - grid/carbon-intensity: 500 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 65.78 - grid/carbon-intensity: 369.4947514218548 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.018934842060004835 - carbon: 6.996324760173567 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 3.986666666666667 - grid/carbon-intensity: 369.38452029076234 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.004545546617763956 - carbon: 1.6790545568620359 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 53.82 - grid/carbon-intensity: 372.58122309244305 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.017357893372978016 - carbon: 6.467225143212361 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 18.936666666666667 - grid/carbon-intensity: 434.20042537311633 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.010385485956624245 - carbon: 4.5093824200727735 - aggregated: - carbon: 19.651986880320734 - outputs: - - carbon: 6.996324760173567 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 1.6790545568620359 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 6.467225143212361 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 4.5093824200727735 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 19.651986880320734 - france: - children: - server-2: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 15 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 78 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 16 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 6 - grid/carbon-intensity: 500 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 14.95 - grid/carbon-intensity: 1719.1647205176753 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.00905914075141129 - carbon: 15.574155178030272 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 77.74 - grid/carbon-intensity: 1719.0544893865829 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.020379266251888902 - carbon: 35.0330691407141 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 15.946666666666667 - grid/carbon-intensity: 1718.8707708347622 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.009405866514354337 - carbon: 16.16746902589712 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 5.98 - grid/carbon-intensity: 1718.6686804277592 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.0054492484351820105 - carbon: 9.365452617417297 - aggregated: - carbon: 76.1401459620588 - outputs: - - carbon: 15.574155178030272 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 35.0330691407141 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 16.16746902589712 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 9.365452617417297 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 76.1401459620588 - outputs: - - carbon: 22.57047993820384 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 36.71212369757613 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 22.63469416910948 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 13.87483503749007 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 95.79213284237952 -``` - -### CSV and aggregation - -The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the *rows* of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the *columns* in the CSV representation (this is not *exactly* accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). - - -## Groupby - -Groupby is an IF plugin that reorganizes a tree according to keys provided by the user. This allows users to regroup their observations according to various properties of their application. For example, the following manifest file contains a flat array of observations. This is how you might expect data to arrive from an importer plugin, maybe one that hits a metrics API for a cloud service. - - -```yaml -name: if-demo -description: demo pipeline -graph: - children: - my-app: - pipeline: - - group-by - - teads-curve - config: - group-by: - - cloud/region - - instance-type - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 1 -``` - -However, each observation contains an `instance-type` field that varies between observations. There are two instance types being represented in this array of observations. This means there are duplicate entries for the same timestamp in this array. This is the problem that `group-by` solves. You provide `instance-type` as a key to the `group-by` plugin and it extracts the data belonging to the different instances and separates them into independent arrays. The above example would be restructured so that instance types `A1` and `B1` have their own data, as follows: - -```yaml -graph: - children: - my-app: - pipeline: - # - group-by - - teads-curve - config: - group-by: - groups: - - cloud/region - - instance-type - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 1 -``` - -### Using `group-by` - -To use `group-by`, you have to initialize it as a plugin and invoke it in a pipeline. - -The initialization looks as follows: - -```yaml -initialize: -plugins: -group-by: - path: 'builtin' - method: GroupBy -``` - -You then have to provide config defining which keys to group by in each component. This is done at the component level (i.e. not global config). -For example: - - -```yaml -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - instance-type -``` - -In the example above, the plugin would regroup the input data for the specific component by `cloud/region` and by `instance-type`. - -Assuming the values `A1` and `B1` are found for `instance-type` and the values `uk-east` and `uk-west` are found for `cloud/region`, the result of `group-by` would look similar to the following: - -```yaml -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - groups: - - cloud/region - - instance-type - children: - uk-west: - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - uk-east: - children: - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 1 -``` - -This reorganized data can then be used to feed the rest of a computation pipeline. diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md deleted file mode 100644 index 4579cd5b8..000000000 --- a/src/builtins/coefficient/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# Coefficient - -`Coefficient` is a generic plugin for multiplying a value in an `input` array by a given coefficient. - -You provide the name of the value you want to multiply, a coefficient value, and a name to use to append the product to the output array. - -For example, you could multiply `cpu/energy` by 10 and name the result `energy-product`. `energy-product` would then be added to every observation in your input array as the product of `cpu/energy` and 10. - -## Parameters - -### Plugin global config - -Three parameters are required in global config: `input-parameter`, `coefficient` and `output-parameter`. - -- `input-parameter`: a string matching an existing key in the `inputs` array -- `coefficient`: the value to multiply `input-parameter` by. -- `output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. - -### Inputs - -All of `input-parameters` must be available in the input array. - -## Returns - -- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. - -## Calculation - -```pseudocode -output = input * coefficient -``` - -## Implementation - -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 coeff = Coefficient(config); -const result = coeff.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - }, -]); -``` - -## 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 `coefficient`: - -```yaml -name: coefficient-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - coefficient: - method: Coefficient - path: 'builtin' - global-config: - input-parameter: 'carbon' - coefficient: 3 - output-parameter: 'carbon-product' -tree: - children: - child: - pipeline: - - coefficient - config: - coefficient: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - carbon: 30 -``` - -You can run this example by saving it as `./examples/manifests/coefficient.yml` and executing the following command from the project root: - -```sh -if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml -``` - -The results will be saved to a new `yaml` file in `./examples/outputs` - - -## Errors - -`Coefficient` exposes one of the IF error classes. - -### GlobalConfigError - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: -- `input-parameter`: this must be a string -- `coefficient`: this must be a number -- `output-parameter`: this must be a string - -You can fix this error by checking you are providing valid values for each parameter in the config. - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts deleted file mode 100644 index 2d4f6a1c9..000000000 --- a/src/builtins/coefficient/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - CoefficientConfig, - ExecutePlugin, - PluginParams, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Calculate the product of each input parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const inputParameter = safeGlobalConfig['input-parameter']; - const outputParameter = safeGlobalConfig['output-parameter']; - const coefficient = safeGlobalConfig['coefficient']; - - return inputs.map(input => { - validateSingleInput(input, inputParameter); - - return { - ...input, - [outputParameter]: calculateProduct(input, inputParameter, coefficient), - }; - }); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = (input: PluginParams, inputParameter: string) => { - const inputData = { - 'input-parameter': input[inputParameter], - }; - const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; - }; - - /** - * Calculates the product of the energy components. - */ - const calculateProduct = ( - input: PluginParams, - inputParameter: string, - coefficient: number - ) => input[inputParameter] * coefficient; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const globalConfigSchema = z.object({ - coefficient: z.number(), - 'input-parameter': z.string().min(1), - 'output-parameter': z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/copy-param/README.md b/src/builtins/copy-param/README.md deleted file mode 100644 index 78ab5f656..000000000 --- a/src/builtins/copy-param/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Copy-param - -`copy-param` is a generic plugin that duplicates an existing parameter in the `input` data and assigns it to a new key. You can either keep or delete the original copied parameter. A common use case for this is to rename parameters in the `inputs` array. - -You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or delete the original copied value. - -For example, you could copy `energy` into `energy-copy`, with `keep-existing=true`. In this case your inputs: - -```yaml -- timestamp: "2023-12-12T00:00:13.000Z", - duration: 30, - energy: 30 -``` - -would become - -```yaml -- timestamp: "2023-12-12T00:00:13.000Z", - duration: 30, - energy: 30 - energy-copy: 30 -``` - -but with `keep-existing=false`, the same inputs would yield: - -```yaml -- timestamp: "2023-12-12T00:00:13.000Z", - duration: 30, - energy-copy: 30 -``` - -## Parameters - -### Config - -Three parameters are required in config: `from` and `to` and `keep-existing`. - -`from`: an array of strings. Each string should match an existing key in the `inputs` array -`to`: a string defining the name to use to add the result of summing the input parameters to the output array. -`keep-existing`: toggles whether to keep or delete the copied parameter (defined in `to`) - -### Inputs - -As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. - -## Returns - -The plugin adds a new parameter with the name defined in `to` to the `input` data. - - -## Implementation - -To run the plugin, you must first create an instance of `Copy`. Then, you can call `execute()`. - -```typescript -import { Copy } from "."; - -const plugin = Copy({ 'keep-existing': true, from: 'from-param', to: 'to-param' }); - -const result = plugin.execute([{ - timestamp: "2023-12-12T00:00:13.000Z", - duration: 30, - 'from-param': 'hello', -}]) - -console.log(result) - -``` - -## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `copy-param`: - -```yaml -name: copy-param -description: -tags: -initialize: - plugins: - copy-param: - path: builtin - method: Copy - global-config: - keep-existing: true - from: original - to: copy -tree: - children: - child-1: - pipeline: - - copy-param - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - original: 'hello' - -``` - -You can run this example by saving it as `./manifests/examples/copy.yml` and executing the following command from the project root: - -```sh -if-run --manifest ./manifests/examples/copy.yml -s -``` - -The results will be displayed in the console. diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts deleted file mode 100644 index 0602f6f75..000000000 --- a/src/builtins/copy-param/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -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): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const globalConfigSchema = z.object({ - 'keep-existing': z.boolean(), - from: z.string().min(1), - to: z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = input[param]; - - return acc; - }, - {} as Record - ); - - const validationSchema = z.record(z.string(), z.string()); - - validate(validationSchema, inputData); - - return input; - }; - - const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const keepExisting = safeGlobalConfig['keep-existing'] === true; - const from = safeGlobalConfig['from']; - const to = safeGlobalConfig['to']; - - return inputs.map(input => { - const safeInput = validateSingleInput(input, [from]); - - const outputValue = safeInput[from]; - if (safeInput[from]) { - if (!keepExisting) { - delete safeInput[from]; - } - } - - return { - ...safeInput, // need to return or what you provide won't be outputted, don't be evil! - [to]: outputValue, - }; - }); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md deleted file mode 100644 index 3663f4123..000000000 --- a/src/builtins/csv-lookup/README.md +++ /dev/null @@ -1,180 +0,0 @@ -# CSV Lookup Plugin - -`csv-lookup` is a generic plugin that enables you to select arbitrary data from a given csv file and add it to your manifest file's `input` data. - -You provide path to the target csv file pus some query parameters. The filepath can point to a location on the local filesystem or it can be a URL for an online resource. The query parameters include the column names for the target data you want to return (can be one column name, multiple column names or all column names, indicated using `"*"`), plus the column names and values you want to use as selectors. - -For example, for the following CSV: - -| | | | | | | | | | | | | | | | | | -| ---- | -------------- | --------------- | ---------- | ---------- | ------------ | --------- | ---------------- | ---------- | ---------- | ---------------------- | ---------- | -------------------------- | --------------------------------- | ------------------------------ | -------------------------------- | --------------------- | -| year | cloud-provider | cloud-region | cfe-region | em-zone-id | wt-region-id | location | geolocation | cfe-hourly | cfe-annual | power-usage-efficiency | net-carbon | grid-carbon-intensity-24x7 | grid-carbon-intensity-consumption | grid-carbon-intensity-marginal | grid-carbon-intensity-production | grid-carbon-intensity | -| 2022 | Google Cloud | asia-east1 | Taiwan | TW | TW | Taiwan | 25.0375,121.5625 | 0.18 | | | 0 | 453 | | | | 453 | -| 2022 | Google Cloud | asia-east2 | Hong Kong | HK | HK | Hong Kong | 22.3,114.2 | 0.28 | | | 0 | 453 | | | | 360 | -| 2022 | Google Cloud | asia-northeast1 | Tokyo | JP-TK | JP-TK | Tokyo | 35.6897,139.692 | 0.28 | | | 0 | 463 | | | | 463 | - - -You could select all the data for the cloud provider `Google Cloud` in the region `asia-east2` using the following configuration: - -```yaml -filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv -query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" -output: "*" -``` - -Notice that the query parameters are key/value pairs where the key is the column name in the target CSV and the value is a **reference to a value** in your `input` data (*not* an actual value - a reference). This is to enable you to chain CSV lookups together based on information from other plugins in your pipeline. - - -## Parameters - -### Plugin config - -- `filepath` - path to a csv file, either on the local filesystem or on the internet -- `query` - an array of key/value pairs where the key is a column name in the target csv and the value is a parameter from inputs -- `output` - the columns to grab data from and add to output data - should support wildcard or multiple values. - -The plugin also supports data renaming. This means you can grab data from a named column but push it into your manifest file data under another name, for example, maybe we want to grab data from the `processor-name` column int he target csv and add it to the manifest file data as `processor-id` because this is the name expected by some other plugin in your piepline. You can do this by passing comma separated values in arrays. - -```yaml -output: - ["processor-name": "processor-id"] -``` - -You can nest arrays to do this renaming for multiple columns. - -```yaml -output: - [["processor-name", "processor-model-id"],["tdp","thermal-design-power"]] -``` - -All the following values are valid for the `output` field: -- `"*"` -- `"tdp"` -- `["processor-name", "processor-model-id"]` -- `[["processor-name", "processor-model-id"],["tdp","thermal-design-power"]]` - -### 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. - -## Returns - -The input data with the requested csv content appended to it. - -## Plugin logic - -1. Validates global config which contains `filepath`, `query` and `output`. -2. Tries to retrieve given file (with url or local path). -3. Parses given CSV. -4. Filters requested information from CSV. -5. Adds new key-value pairs to the input data -6. Returns enriched input data - -## Implementation - -To run the plugin, you must first create an instance of `CSVLookup`. Then, you can call `execute()`. - -```typescript -const globalConfig = { - filepath: 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', - query: { - 'cloud-provider': 'cloud/provider' - region: 'cloud/region' - 'instance-type': 'cloud/instance-type' - }, - output: ['cpu-tdp', 'tdp'], -}; -const divide = CSVLookup(globalConfig); - -const input = [ - { - timestamp: '2023-08-06T00:00' - duration: 3600 - 'cpu/energy': 0.001 - 'cloud/provider': gcp - 'cloud/region': asia-east - }, -]; -``` - -## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `csv-lookup`: - -```yaml -name: csv-lookup-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - cloud-metadata: - method: CSVLookup - path: 'builtin' - global-config: - filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv - query: - cloud-provider: "cloud/provider" - cloud-region: "cloud/region" - output: "*" -tree: - children: - child: - pipeline: - - cloud-metadata - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cloud/provider: Google Cloud - cloud/region: 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: - -```sh -npm i -g @grnsft/if -if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup -``` - -The results will be saved to a new `yaml` file in `manifests/outputs`. - - -## Errors - -Coefficient exposes six of the IF error classes. - -### FetchingFileError - -This error is caused by problems finding the file at the path provided in the `filepath`. If the file is on your local filesystem, you can check that the file is definitely there. For a remote file, check your internet connection. You can check your connection to the server using a tool such as `ping` or `curl`. if you still experience problems, you could retrieve the remote file onto your local filesystem using a tool such as `wget`. - -### ReadFileError, - -This error is caused by problems reading the CSV file provided in the `filepath`. To fix it, check that the file contains valid CSV data. The file should have a `.csv` file extension and the data inside should be formatted correctly. - -### MissingCSVColumnError, - -This error is caused by `CsvLookup` failing to find a column in the CSV file whose name matches what was provided in `query`. To debug, check that you do not have any typos in your `query` and confirm that the requested column name definitely exists in the target file. - -### QueryDataNotFoundError, - -This error is caused by the `CsvLookup` plugin failing to find data that matches your query. Try revising your query parameters. - -### CSVParseError, - -This error arises due to problems parsing CSV data into IF. This can occur when the CSV data is incorrectly formatted or contains unexpected characters that IF does not recognize. These errors are expected to be unusual edge cases as incorrectly formatted data will usually be identified during file loading and cause a `ReadFileError`. To debug, check your CSV file for any unexpected formatting or unusual characters. - -### GlobalConfigError - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: -- `filepath`: This must be a path to a csv file -- `query`: this must be an array of key-value pairs where the key is a string containing a column name an the value is a string containing the name of a value in `inputs` -- `output`: this must be a string containing a name or a wildcard character (`"*"`) - -You can fix this error by checking you are providing valid values for each parameter in the config. - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts deleted file mode 100644 index 8243a6391..000000000 --- a/src/builtins/csv-lookup/index.ts +++ /dev/null @@ -1,247 +0,0 @@ -/* eslint-disable eqeqeq */ -import {readFile} from 'fs/promises'; - -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 {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const { - FILE_FETCH_FAILED, - FILE_READ_FAILED, - MISSING_CSV_COLUMN, - NO_QUERY_DATA, - MISSING_GLOBAL_CONFIG, -} = STRINGS; - -const { - FetchingFileError, - ReadFileError, - MissingCSVColumnError, - QueryDataNotFoundError, - GlobalConfigError, - CSVParseError, -} = ERRORS; - -export const CSVLookup = (globalConfig: any): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks if given string is URL. - */ - const isURL = (filepath: string) => { - try { - new URL(filepath); - return true; - } catch (error) { - return false; - } - }; - - /** - * Checks if given `filepath` is url, then tries to fetch it. - * Otherwise tries to read file. - */ - const retrieveFile = async (filepath: string) => { - if (isURL(filepath)) { - const {data} = await axios.get(filepath).catch(error => { - throw new FetchingFileError( - FILE_FETCH_FAILED(filepath, error.response.message) - ); - }); - - return data; - } - - return readFile(filepath).catch(error => { - throw new ReadFileError(FILE_READ_FAILED(filepath, error)); - }); - }; - - /** - * Checks if value is invalid: `undefined`, `null` or an empty string, then sets `nan` instead. - */ - const setNanValue = (value: any) => - value == null || value === '' ? 'nan' : value; - - /** - * Converts empty values to `nan`. - */ - const nanifyEmptyValues = (object: any) => { - if (typeof object === 'object') { - const keys = Object.keys(object); - - keys.forEach(key => { - const value = object[key]; - object[key] = setNanValue(value); - }); - - return object; - } - - return setNanValue(object); - }; - - /** - * If `field` is missing from `object`, then reject with error. - * Otherwise nanify empty values and return data. - */ - const fieldAccessor = (field: string, object: any) => { - if (!(`${field}` in object)) { - throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); - } - - return nanifyEmptyValues(object[field]); - }; - - /** - * 1. If output is anything, then removes query data from csv record to escape duplicates. - * 2. Otherwise checks if it's a miltidimensional array, then grabs multiple fields (). - * 3. If not, then returns single field. - * 4. In case if it's string, then - */ - const filterOutput = ( - dataFromCSV: any, - params: { - output: string | string[] | string[][]; - query: Record; - } - ) => { - const {output, query} = params; - - if (output === '*') { - const keys = Object.keys(query); - - keys.forEach(key => { - delete dataFromCSV[key]; - }); - - return nanifyEmptyValues(dataFromCSV); - } - - if (Array.isArray(output)) { - /** Check if it's a multidimensional array. */ - if (Array.isArray(output[0])) { - const result: any = {}; - - output.forEach(outputField => { - /** Check if there is no renaming request, then export as is */ - const outputTitle = outputField[1] || outputField[0]; - result[outputTitle] = fieldAccessor(outputField[0], dataFromCSV); - }); - - return result; - } - - const outputTitle = output[1] || output[0]; - - return { - [outputTitle as string]: fieldAccessor(output[0], dataFromCSV), - }; - } - - return { - [output]: fieldAccessor(output, dataFromCSV), - }; - }; - - /** - * Asserts CSV record with query data. - */ - const withCriteria = (queryData: Record) => (csvRecord: any) => { - const ifMatchesCriteria = Object.keys(queryData).map( - (key: string) => csvRecord[key] == queryData[key] - ); - - return ifMatchesCriteria.every(value => value === true); - }; - - /** - * Parses CSV file. - */ - const parseCSVFile = (file: string | Buffer) => { - try { - const parsedCSV: any[] = parse(file, { - columns: true, - skip_empty_lines: true, - cast: true, - }); - - return parsedCSV; - } catch (error: any) { - console.error(error); - throw new CSVParseError(error); - } - }; - - /** - * 1. Validates global config. - * 2. Tries to retrieve given file (with url or local path). - * 3. Parses given CSV. - * 4. Filters requested information from CSV. - */ - const execute = async (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const {filepath, query, output} = safeGlobalConfig; - - const file = await retrieveFile(filepath); - const parsedCSV = parseCSVFile(file); - - return inputs.map(input => { - /** Collects query values from input. */ - const queryData: any = {}; - const queryKeys = Object.keys(query); - queryKeys.forEach(queryKey => { - const queryValue = query[queryKey]; - queryData[queryKey] = input[queryValue]; - }); - - /** Gets related data from CSV. */ - const relatedData = parsedCSV.find(withCriteria(queryData)); - - if (!relatedData) { - throw new QueryDataNotFoundError(NO_QUERY_DATA); - } - - return { - ...input, - ...filterOutput(relatedData, {output, query}), - }; - }); - }; - - /** - * Checks for `filepath`, `query` and `output` fields in global config. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const globalConfigSchema = z.object({ - filepath: z.string(), - query: z.record(z.string(), z.string()), - output: z - .string() - .or(z.array(z.string())) - .or(z.array(z.array(z.string()))), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md deleted file mode 100644 index 9a4d04f36..000000000 --- a/src/builtins/divide/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# Divide - -`divide` is a generic plugin for doing arithmetic division of two values in an `input` array. - -You provide the names of the values you want to divide, and a name to use to add the divide to the output array. - -## Parameters - -### Plugin config - -- `numerator` - a parameter by a specific configured number -- `denominator` - a parameter by a specific configured number or the number by which `numerator` is divided -- `output` - the number to a configured output parameter - -### Inputs - -- `numerator` - as input parameter, must be available in the input array -- `denominator` - must be available in the input array if is an input parameter -- `output` - as input parameter, must be available in the input array - -## Returns - -- `output`: the division of `numerator` with the parameter name into `denominator` with the parameter name defined by `output` in global config. - -The plugin throws an exception if the division result is not a number. - ->Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. - -## Calculation - -```pseudocode -output = input0 / input1 -``` - -## Implementation - -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 divide = Divide(globalConfig); - -const input = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, -]; -``` - -## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `divide`: - -```yaml -name: divide-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - divide: - method: Divide - path: 'builtin' - global-config: - numerator: vcpus-allocated - denominator: 2 - output: cpu/number-cores -tree: - children: - child: - pipeline: - - divide - config: - divide: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - vcpus-allocated: 24 -``` - -You can run this example by saving it as `./examples/manifests/divide.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml -``` - -The results will be saved to a new `yaml` file in `./examples/outputs`. - -## Errors - -`Divide` exposes two of IF's error classes. - -### GlobalConfigError - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: -- `numerator`: a string containing the name of the input parameter whose value should be divided by `denominator` -- `denominator`: a number to use as the denominator -- ``output`: a string containing the name to assign the result of the division - -You can fix this error by checking you are providing valid values for each parameter in the config. - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the ``inputs` array must contain: -- `timestamp` -- `duration` -- whatever value you passed to `numerator` - - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts deleted file mode 100644 index 453a50921..000000000 --- a/src/builtins/divide/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; - -export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Calculate the division of each input parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const {numerator, denominator, output} = safeGlobalConfig; - - return inputs.map((input, index) => { - const safeInput = Object.assign( - {}, - input, - validateSingleInput(input, {numerator, denominator}) - ); - - return { - ...input, - [output]: calculateDivide(safeInput, index, {numerator, denominator}), - }; - }); - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const schema = z.object({ - numerator: z.string().min(1), - denominator: z.string().or(z.number()), - output: z.string(), - }); - - return validate>(schema, globalConfig); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - params: { - numerator: string; - denominator: number | string; - } - ) => { - const {numerator, denominator} = params; - - const schema = z - .object({ - [numerator]: z.number(), - [denominator]: z.number().optional(), - }) - .refine(() => { - if (typeof denominator === 'string' && !input[denominator]) { - throw new MissingInputDataError(MISSING_INPUT_DATA(denominator)); - } - - return true; - }); - - return validate>(schema, input); - }; - - /** - * Calculates the division of the given parameter. - */ - const calculateDivide = ( - input: PluginParams, - index: number, - params: { - numerator: string; - denominator: number | string; - } - ) => { - const {denominator, numerator} = params; - const finalDenominator = input[denominator] || denominator; - - if (finalDenominator === 0) { - console.warn(ZERO_DIVISION(Divide.name, index)); - return input[numerator]; - } - - return input[numerator] / finalDenominator; - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md deleted file mode 100644 index 91d938cef..000000000 --- a/src/builtins/exponent/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Exponent - -`exponent` is a generic plugin for calculating exponent of an input param (as base) and another (as the exponent) in an `input` array. - -You provide the names of the values you want to use for the exponent calculation, and a name to use to add the exponent result to the output array. - -For example, you use `cpu/energy` as base and `network/energy` as and name the result `energy`. `energy` would then be added to every observation in your input array as `cpu/energy` raised by the exponent `network/energy`. - -## Parameters - -### Plugin config - -Three parameters are required in global config: `input-parameter`, `exponent` and `output-parameter`. - -`input-parameter`: a string defining the base. Must match an existing key in the `inputs` array -`exponent`: a number defining the exponent. -`output-parameter`: a string defining the name to use to add the result of the exponent to the output array. - -### Inputs - -`input-parameter` and `exponent` must be available in the input array. - -## Returns - -- `output-parameter`: `input-parameter` raised by `exponent` with the parameter name defined by `output-parameter` in global config. - -## Calculation - -```pseudocode -output = input ^ exponent -``` - -## Implementation - -To run the plugin, you must first create an instance of `Exponent`. Then, you can call `execute()`. - -```typescript -import {Exponent} from 'builtins'; - -const config = { - inputParameter: ['cpu/energy'], - exponent: 2 - outputParameter: 'energy', -}; - -const exponent = Exponent(config); -const result = await exponent.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - 'cpu/energy': 0.1, - 'energy': 0.01, - }, -]); -``` - -## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `exponent`: - -```yaml -name: exponent demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - exponent: - method: Exponent - path: 'builtin' - global-config: - input-parameter: 'cpu/energy' - exponent: 2 - output-parameter: 'energy' -tree: - children: - child: - pipeline: - - exponent - config: - exponent: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - network/energy: 0.001 -``` - -You can run this example by saving it as `manifests/examples/test/exponent.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml -``` - -The results will be saved to a new `yaml` file in `manifests/outputs`. - -## Errors - -`Exponent` exposes two of IF's error classes. - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the `inputs` array must contain: - -- `timestamp` -- `duration` -- whatever value you passed to `input-parameter` - - -### `InputValidationError` - -This error arises when an invalid value is passed to `Exponent`. 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 diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts deleted file mode 100644 index ce4e959ef..000000000 --- a/src/builtins/exponent/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -import {z} from 'zod'; -import { - ExecutePlugin, - PluginParams, - ExponentConfig, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ - 'input-parameter': z.string().min(1), - exponent: z.number(), - 'output-parameter': z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = (input: PluginParams, inputParameter: string) => { - const inputData = { - 'input-parameter': input[inputParameter], - }; - const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; - }; - - /** - * Calculate the input param raised by to the power of the given exponent. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const { - 'input-parameter': inputParameter, - exponent, - 'output-parameter': outputParameter, - } = validateGlobalConfig(); - - return inputs.map(input => { - validateSingleInput(input, inputParameter); - - return { - ...input, - [outputParameter]: calculateExponent(input, inputParameter, exponent), - }; - }); - }; - - /** - * Calculates the input param raised by the power of a given exponent. - */ - const calculateExponent = ( - input: PluginParams, - inputParameter: string, - exponent: number - ) => { - const base = input[inputParameter]; - - return Math.pow(base, exponent); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts deleted file mode 100644 index 7afc21cb2..000000000 --- a/src/builtins/export-csv-raw.ts +++ /dev/null @@ -1,156 +0,0 @@ -import * as fs from 'fs/promises'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {STRINGS} from '../config'; - -import {Context} from '../types/manifest'; - -const {ExhaustOutputArgError, WriteFileError} = ERRORS; -const {OUTPUT_REQUIRED, WRITE_CSV_ERROR, EXPORTING_RAW_CSV_FILE} = STRINGS; - -export const ExportCSVRaw = () => { - /** - * handle a tree leaf, where there are no child nodes, by adding it as key->value pair to the flat map - * and capturing key as a header - */ - const handleLeafValue = ( - value: any, - fullPath: string, - key: any, - flatMap: {[key: string]: any}, - headers: Set - ) => { - if (fullPath.includes('outputs')) { - headers.add(key); - flatMap[fullPath] = value; - } - }; - - /** - * handle a tree node, recursively traverse the children and append their results to the flat map and captured headers - */ - const handleNodeValue = ( - value: any, - fullPath: string, - flatMap: Record, - headers: Set - ) => { - const [subFlatMap, subHeaders] = extractFlatMapAndHeaders(value, fullPath); - - if (Object.keys(subFlatMap).length > 0) { - Object.entries(subFlatMap).forEach(([subKey, value]) => { - flatMap[subKey] = value; - }); - - subHeaders.forEach(subHeader => { - headers.add(subHeader); - }); - } - }; - - /** - * Handles a key at the top level of the tree - */ - const handleKey = ( - value: any, - key: any, - prefix: string, - flatMap: Record, - headers: Set - ) => { - const fullPath = prefix ? `${prefix}.${key}` : key; - - if (value !== null && typeof value === 'object') { - return handleNodeValue(value, fullPath, flatMap, headers); - } - - return handleLeafValue(value, fullPath, key, flatMap, headers); - }; - - /** - * Recursively extract a flat map and headers from the hierarcial tree. - */ - const extractFlatMapAndHeaders = ( - tree: any, - prefix = '' - ): [Record, Set] => { - const headers: Set = new Set(); - const flatMap: Record = []; - - for (const key in tree) { - if (key in tree) { - handleKey(tree[key], key, prefix, flatMap, headers); - } - } - - return [flatMap, headers]; - }; - - /** - * extract the id of the key, that is removing the last token (which is the index). - * in this manner, multiple keys that identical besides their index share the same id. - */ - const extractIdHelper = (key: string): string => { - const parts = key.split('.'); - parts.pop(); - - return parts.join('.'); - }; - - /** - * generate a CSV formatted string based on a flat key->value map, headers and ids - */ - const getCsvString = ( - map: {[key: string]: any}, - headers: Set, - ids: Set - ): string => { - const csvRows: string[] = []; - csvRows.push(['id', ...headers].join(',')); - - ids.forEach(id => { - const rowData = [id]; - - headers.forEach(header => { - const value = map[`${id}.${header}`] ?? ''; - rowData.push(value.toString()); - }); - csvRows.push(rowData.join(',')); - }); - - return csvRows.join('\n'); - }; - - /** - * write the given string content to a file at the provided path - */ - const writeOutputFile = async (content: string, outputPath: string) => { - try { - await fs.writeFile(`${outputPath}.csv`, content); - } catch (error) { - throw new WriteFileError(WRITE_CSV_ERROR(outputPath, error)); - } - }; - - /** - * export the provided tree content to a CSV file, represented in a flat structure - */ - const execute = async (tree: any, _context: Context, outputPath: string) => { - if (!outputPath) { - throw new ExhaustOutputArgError(OUTPUT_REQUIRED); - } - - console.debug(EXPORTING_RAW_CSV_FILE(outputPath)); - - const [extractredFlatMap, extractedHeaders] = - extractFlatMapAndHeaders(tree); - const ids = new Set( - Object.keys(extractredFlatMap).map(key => extractIdHelper(key)) - ); - const csvString = getCsvString(extractredFlatMap, extractedHeaders, ids); - - await writeOutputFile(csvString, outputPath); - }; - - return {execute}; -}; diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts deleted file mode 100644 index 53a105733..000000000 --- a/src/builtins/export-csv.ts +++ /dev/null @@ -1,117 +0,0 @@ -import {writeFile} from 'fs/promises'; - -import {stringify} from 'csv-stringify/sync'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {PluginParams} from '@grnsft/if-core/types'; - -import {STRINGS} from '../config'; - -import {Context} from '../types/manifest'; - -const {ExhaustOutputArgError} = ERRORS; -const {CSV_EXPORT, OUTPUT_REQUIRED, EXPORTING_TO_CSV_FILE} = STRINGS; - -/** - * Extension to IF that outputs the tree in a CSV format. - */ -export const ExportCSV = () => { - const parseOutputAndField = (outputPath: string) => { - const validatedPath = validateOutputPath(outputPath); - - const paths = validatedPath.split('#'); - const criteria = paths[paths.length - 1]; - - if (paths.length <= 1 || !criteria) { - throw new ExhaustOutputArgError(CSV_EXPORT); - } - - const output = paths.slice(0, paths.length - 1).join(''); - console.debug(EXPORTING_TO_CSV_FILE(output)); - - return { - output, - criteria, - }; - }; - - /** - * Validates output path. - */ - const validateOutputPath = (outputPath: string) => { - if (!outputPath) { - throw new ExhaustOutputArgError(OUTPUT_REQUIRED); - } - - return outputPath; - }; - - /** - * Grabs output and criteria from cli args, then call tree walker to collect csv data. - */ - const execute = async (tree: any, context: Context, outputPath: string) => { - const columns = ['Path']; - const matrix = [columns]; - const {output, criteria} = parseOutputAndField(outputPath); - const aggregationIsEnabled = !!context.aggregation; - - /** - * Walks through all tree branches and leaves, collecting the data - */ - const treeWalker = (node: any, criteria: string, path = 'tree') => { - /** Hmm aggregated, then checks if it's the first one. If so adds column, pushes the value. */ - if (node.aggregated) { - if (path === 'tree') { - columns.push('Aggregated'); - } - - matrix.push([`${path}.${criteria}`, node.aggregated[criteria]]); - } - - /** So it has outputs, whats then? checks if timestamp is not there, adds one. Then appends values to it. */ - if (node.outputs) { - node.outputs.forEach((output: PluginParams) => { - const {timestamp} = output; - - if (!columns.includes(timestamp)) { - columns.push(output.timestamp); - } - - const lastRow = matrix[matrix.length - 1]; - - if (aggregationIsEnabled) { - lastRow.push(output[criteria]); - } else { - /** Handle without aggregation export strategy. */ - if (matrix.length === 1 || lastRow.length === columns.length) { - matrix.push([`${path}.${criteria}`, output[criteria]]); - } else { - lastRow.push(output[criteria]); - } - } - }); - } - - /** Ohh children? then call every one and execute. */ - if (node.children) { - for (const child in node.children) { - treeWalker( - node.children[child], - criteria, - `${path}.children.${child}` - ); - } - } - }; - - treeWalker(tree, criteria); - - await writeFile(`${output}.csv`, stringify(matrix, {columns})); - }; - - return { - execute, - metadata: { - kind: 'exhaust', - }, - }; -}; diff --git a/src/builtins/export-log.ts b/src/builtins/export-log.ts deleted file mode 100644 index fee267dc2..000000000 --- a/src/builtins/export-log.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as YAML from 'js-yaml'; - -import {Context} from '../types/manifest'; - -export const ExportLog = () => { - /** - * Logs output manifest in console. - */ - const execute = async (tree: any, context: Context) => { - const outputFile = { - ...context, - tree, - }; - - console.log(`# start -${YAML.dump(outputFile, {noRefs: true})} -# end`); - }; - - return {execute}; -}; diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts deleted file mode 100644 index 624e1298f..000000000 --- a/src/builtins/export-yaml.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {saveYamlFileAs} from '../util/yaml'; - -import {STRINGS} from '../config'; - -import {Context} from '../types/manifest'; - -const {ExhaustOutputArgError} = ERRORS; -const {OUTPUT_REQUIRED, EXPORTING_TO_YAML_FILE} = STRINGS; - -export const ExportYaml = () => { - /** Takes string before hashtag. */ - const stripHashtag = (path: string) => path.split('#')[0]; - - /** - * Saves output file in YAML format. - */ - const execute = async (tree: any, context: Context, outputPath: string) => { - if (!outputPath) { - throw new ExhaustOutputArgError(OUTPUT_REQUIRED); - } - - const outputFile = { - ...context, - tree, - }; - const path = stripHashtag(outputPath); - - console.debug(EXPORTING_TO_YAML_FILE(path)); - - await saveYamlFileAs(outputFile, `${path}.yaml`); - }; - - return {execute}; -}; diff --git a/src/builtins/group-by.ts b/src/builtins/group-by.ts deleted file mode 100644 index 63c4cd5c5..000000000 --- a/src/builtins/group-by.ts +++ /dev/null @@ -1,95 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - GroupByPlugin, - PluginParams, - GroupByConfig, -} from '@grnsft/if-core/types'; - -import {STRINGS} from '../config'; - -import {validate} from '../util/validations'; - -const {InvalidGroupingError, GlobalConfigError} = ERRORS; - -const {INVALID_GROUP_BY, MISSING_GLOBAL_CONFIG} = STRINGS; - -/** - * Plugin for inputs grouping. - */ -export const GroupBy = (): GroupByPlugin => { - const metadata = { - kind: 'groupby', - }; - - /** - * Creates structure to insert inputs by groups. - */ - const appendGroup = ( - value: PluginParams, - object: any, - groups: string[] - ): any => { - if (groups.length > 0) { - const group = groups.shift() as string; - - object.children = object.children ?? {}; - object.children[group] = object.children[group] ?? {}; - - if (groups.length === 0) { - if ( - object.children[group].inputs && - object.children[group].inputs.length > 0 - ) { - object.children[group].inputs.push(value); - } else { - object.children[group].inputs = [value]; - } - } - - appendGroup(value, object.children[group], groups); - } - - return object; - }; - - /** - * Interates over inputs, grabs config-group types values for each one. - * Based on grouping types, initializes the structure grouped structure. - */ - const execute = (inputs: PluginParams[], config: GroupByConfig) => - inputs.reduce((acc, input) => { - const validatedConfig = validateConfig(config); - const groups = validatedConfig.group.map(groupType => { - if (!input[groupType]) { - throw new InvalidGroupingError(INVALID_GROUP_BY(groupType)); - } - - return input[groupType]; - }); - - acc = { - ...acc, - ...appendGroup(input, acc, groups), - }; - - return acc; - }, {} as any).children; - - /** - * Validates config parameter. - */ - const validateConfig = (config: GroupByConfig) => { - if (!config) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const schema = z.object({ - group: z.array(z.string()).min(1), - }); - - return validate>(schema, config); - }; - - return {metadata, execute}; -}; diff --git a/src/builtins/index.ts b/src/builtins/index.ts deleted file mode 100644 index d22491aca..000000000 --- a/src/builtins/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export {GroupBy} from './group-by'; -export {TimeSync} from './time-sync'; -export {Interpolation} from './interpolation'; -export {MockObservations} from './mock-observations'; -export {Divide} from './divide'; -export {Subtract} from './subtract'; -export {Coefficient} from './coefficient'; -export {Multiply} from './multiply'; -export {Sum} from './sum'; -export {SciEmbodied} from './sci-embodied'; -export {Sci} from './sci'; -export {Exponent} from './exponent'; -export {CSVLookup} from './csv-lookup'; -export {Shell} from './shell'; -export {Regex} from './regex'; -export {Copy} from './copy-param'; diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md deleted file mode 100644 index 498c26c6e..000000000 --- a/src/builtins/interpolation/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# Interpolation Plugin - -## Overview - -Interpolation is a way to infer new data points from a previously known set of points. -This plugin provides the `y` value at a given `x` by interpolating between known points. You provide a set of known `x`s and `y`s and a target `x`, the plugin returns the `y` for your `x`. - -## Usage - -To employ the `Interpolation` plugin, adhere to these steps: - -1. **Initialize Plugin**: Import the `Interpolation` function and initialize it with global configuration parameters `method`, `x`, `y`, `input-parameter` and `output-parameter`. - -2. **Execute Plugin**: Invoke the `execute` method of the initialized plugin instance with an array of input parameters. Each input parameter should include a `timestamp`, `duration` and `[input-parameter]` information. - -3. **Result**: The plugin will return an array of plugin parameters enriched with the calculated average carbon intensity for each input. - -## Global Config - -- `method`: specifies the interpolation method for the data. Acceptable values are 'linear', 'spline', or 'polynomial'. The default method is linear. (optional) -- `x`: array of x points. Numbers should be in ascending order (required). -- `y`: array of y points. Numbers should be in ascending order (required). -- `input-parameter`: a string defining the name to use its value to calculate the interpolation. It should match an existing key in the inputs array (required). -- `output-parameter`: a string defining the name to use to add the result of interpolation with additional calculation (required). - -`x` and `y` arrays must be equal lengths. - -## Input Parameters - -The plugin expects the following input parameters: - -- `timestamp`: a timestamp for the input (required) -- `duration`: the amount of time, in seconds, that the input covers. (required) -- `[input-parameter]` - a field whose name matches the string provided to input-parameter in global config (i.e. if the input-parameter in global config is cpu/utilisation then cpu-utilisation must exist in the input data) - -## Output - -The plugin outputs a value `z` that is the result of looking up the `y` value at `x = 'input-parameter'` using the user-defined interpolation method in `kWh` units. `z` is assigned to a field with a name defined by `output-parameter` in the output data. - -## Error Handling - -The plugin conducts input validation using the `zod` library and may throw errors if the provided parameters are invalid. - -## Plugin Algorithm - -1. **Execution**: - - - Validate Global config - - - `method` - validates if the method is one of these methods: `linear`, `spline`, or `polynomial`. If the method isn’t provided, it sets to `linear`. - - `x` and `y` should be arrays of numbers, the length should be equal, and elements should be ordered in the ascendant order. - - `input-parameter` - validates if the parameter is string. - - `output-parameter` - validates if the parameter is string. - - - Iterate through each input, and do corresponding validation and calculation. - - - Validate input parameters - - - `duration` - validate if the duration is a number - - `timestamp` - should be in string or date format - - `[input-parameter]` - validates whether the parameter name is included in the input, and if its value should be a number within the range of x points. - - - Calculation - - - If the `method` is provided, choose the right way to calculate. For the `linear` and `polynomial` methods, calculate according to their formulas. For spline interpolation, use the npm module `typescript-cubic-spline`. - -2. **Output**: Output the provided input along with the calculated `cpu/energy` - -### 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 interpolationPlugin = Interpolation(globalConfig); - -const inputs = [ - { - timestamp: '2024-04-16T12:00:00Z', - duration: 3600, - 'cpu/utilization': 45 - }, -]; - -const results = interpolationPlugin.execute(inputs); - -console.log(results); -``` - -### Manifest Usage - -#### Input - -```yaml -name: interpolation-demo -description: simple demo of interpolation plugin -tags: -initialize: - outputs: - - yaml - 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: 'cpu/energy' -tree: - children: - child: - pipeline: - - interpolation - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 - cpu/utilization: 45 -``` - -#### Output - -```yaml -name: interpolation-demo -description: simple demo of interpolation plugin -tags: -initialize: - outputs: - - yaml - 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: 'cpu/energy' -tree: - children: - child: - pipeline: - - interpolation - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 - cpu/utilization: 45 - outputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 - cpu/utilization: 45 - cpu/energy: 0.00069625 -``` - -You can execute this by passing it to `ie`. Run the impact using the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml -``` - -## Errors - -`Interpolation` exposes one of IF's error classes. - -## `GlobalConfigError` - -### GlobalConfigError - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: -- `method`: a string containing either `linear`, `spline` or `polynomial` -- `x`: an array of numbers -- `y`: an array of numbers -- `input-parameter`: a string containing the name of a value present in the `inputs` array' -- `output-parameter`: a string - -You can fix this error by checking you are providing valid values for each parameter in the config. - -### Validation errors - -There are also several validation errors that can arise, including: -- if the lengths of `x` and `y` are not equal -- if `x` or `y` are empty -- if the requested point to interpolate at is outside the range of `x` - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/interpolation/index.ts b/src/builtins/interpolation/index.ts deleted file mode 100644 index 98a84ad8a..000000000 --- a/src/builtins/interpolation/index.ts +++ /dev/null @@ -1,197 +0,0 @@ -import Spline from 'typescript-cubic-spline'; -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - Method, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {GlobalConfigError} = ERRORS; -const { - MISSING_GLOBAL_CONFIG, - X_Y_EQUAL, - ARRAY_LENGTH_NON_EMPTY, - WITHIN_THE_RANGE, -} = STRINGS; - -export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { - /** - * Executes the energy consumption calculation for an array of input parameters. - */ - const execute = (inputs: PluginParams[]) => { - const validatedConfig = validateConfig(); - - return inputs.map((input, index) => { - const safeInput = validateInput(input, index); - const result = calculateResult(validatedConfig, safeInput); - - return { - ...input, - [validatedConfig['output-parameter']]: result, - }; - }); - }; - - /** - * Calculates the appropriate interpolation value based on the specified method type in the config and input parameters. - */ - const calculateResult = (config: ConfigParams, input: PluginParams) => { - const methodType: {[key: string]: number} = { - linear: getLinearInterpolation(config, input), - spline: getSplineInterpolation(config, input), - polynomial: getPolynomialInterpolation(config, input), - }; - - return methodType[config.method]; - }; - - /** - * Calculates the interpolation when the method is linear. - */ - const getLinearInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = input[globalConfig['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - - const result = xPoints.reduce( - (acc, xPoint, i) => { - if (parameter === xPoint) { - acc.baseCpu = xPoint; - acc.baseRate = yPoints[i]; - } else if (parameter > xPoint && parameter < xPoints[i + 1]) { - acc.baseCpu = xPoint; - acc.baseRate = yPoints[i]; - acc.ratio = (yPoints[i + 1] - yPoints[i]) / (xPoints[i + 1] - xPoint); - } - - return acc; - }, - {baseRate: 0, baseCpu: 0, ratio: 0} - ); - - return result.baseRate + (parameter - result.baseCpu) * result.ratio; - }; - - /** - * Calculates the interpolation when the method is spline. - */ - const getSplineInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = input[globalConfig['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - const spline: any = new Spline(xPoints, yPoints); - - return spline.at(parameter); - }; - - /** - * Calculates the interpolation when the method is polynomial. - */ - const getPolynomialInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = input[globalConfig['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - - const result = xPoints.reduce((acc, x, i) => { - const term = - yPoints[i] * - xPoints.reduce((prod, xPoint, j) => { - if (j !== i) { - return (prod * (parameter - xPoint)) / (x - xPoint); - } - return prod; - }, 1); - return acc + term; - }, 0); - - return result; - }; - - /** - * Validates global config parameters. - * Sorts elements of `x` and `y`. - */ - const validateConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const schema = z - .object({ - method: z.nativeEnum(Method), - x: z.array(z.number()), - y: z.array(z.number()), - 'input-parameter': z.string(), - 'output-parameter': z.string(), - }) - .refine(data => data.x && data.y && data.x.length === data.y.length, { - message: X_Y_EQUAL, - }) - .refine(data => data.x.length > 1 && data.y.length > 1, { - message: ARRAY_LENGTH_NON_EMPTY, - }); - - const defaultMethod = globalConfig.method ?? Method.LINEAR; - const updatedConfig = Object.assign( - {}, - {method: defaultMethod}, - globalConfig, - { - x: sortPoints(globalConfig.x), - y: sortPoints(globalConfig.y), - } - ); - - return validate>(schema, updatedConfig); - }; - - const sortPoints = (items: number[]) => - items.sort((a: number, b: number) => { - return a - b; - }); - - /** - * Validates inputes parameters. - */ - const validateInput = (input: PluginParams, index: number) => { - const inputParameter = globalConfig['input-parameter']; - const schema = z - .object({ - timestamp: z.string().or(z.date()), - duration: z.number(), - [inputParameter]: z.number().gt(0), - }) - .refine( - data => - data[inputParameter] >= globalConfig.x[0] && - data[inputParameter] <= globalConfig.x[globalConfig.x.length - 1], - { - message: WITHIN_THE_RANGE, - } - ); - - return validate>(schema, input, index); - }; - - return { - metadata: { - kind: 'execute', - }, - execute, - }; -}; diff --git a/src/builtins/mock-observations/README.md b/src/builtins/mock-observations/README.md deleted file mode 100644 index 1af4cd6d6..000000000 --- a/src/builtins/mock-observations/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Mock Observations Plugin - -## Introduction - -A plugin for mocking observations (inputs) for testing and demo purposes - -## Scope - -The mode currently mocks 2 types of observation data: - -- Common key-value pairs, that are generated statically and are the same for each generated observation/input (see 'helpers/CommonGenerator.ts') -- Randomly generated integer values for predefined keys (see 'helpers/RandIntGenerator.ts') - -### Plugin global config - -- `timestamp-from`, `timestamp-to` and `duration` define time buckets for which to generate observations. -- `generators` define which fields to generate for each observation -- `components` define the components for which to generate observations. The observations generated according to `timestamp-from`, `timestamp-to`, `duration` and `generators` will be duplicated for each component. - -### Authentication - -N/A - -### Inputs - -The plugin's `global-config` section in the manifest file determines its behaviour. -'inputs' section is ignored. - -### 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 result = await mockObservations.execute([]); -``` - -### manifest Example - -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 `mock-observation`: - -```yaml -name: mock-observation-demo -description: example invoking mock-observation plugin -tags: -initialize: - outputs: - - yaml - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: 'builtin' - global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 60 - components: - - instance-type: A1 - - instance-type: B1 - generators: - common: - region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - memory/utilization: - min: 1 - max: 99 -tree: - children: - child: - pipeline: - - mock-observations - inputs: -``` - -You can run this example `manifest` by saving it as `manifests/plugins/mock-observation.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation -``` - -The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/builtins/mock-observations/helpers/common-generator.ts b/src/builtins/mock-observations/helpers/common-generator.ts deleted file mode 100644 index 8283cf1bd..000000000 --- a/src/builtins/mock-observations/helpers/common-generator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {ConfigParams} from '@grnsft/if-core/types'; - -import {STRINGS} from '../../../config'; - -import {Generator} from '../interfaces'; - -const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -export const CommonGenerator = (config: ConfigParams): Generator => { - /** - * Generates next value by copying the validated config. - * Validates the provided config is not null or empty. - * Returns a copy of the validated config, otherwise throws an GlobalConfigError. - */ - const validateConfig = (config: object) => { - if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - return structuredClone(config); - }; - - /** - * Generates next value by copying the validated config. - */ - const next = (): Object => validateConfig(config); - - return { - next, - }; -}; diff --git a/src/builtins/mock-observations/helpers/rand-int-generator.ts b/src/builtins/mock-observations/helpers/rand-int-generator.ts deleted file mode 100644 index 1cb4d161f..000000000 --- a/src/builtins/mock-observations/helpers/rand-int-generator.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {RandIntGeneratorParams, ConfigParams} from '@grnsft/if-core/types'; - -import {STRINGS} from '../../../config'; - -import {Generator} from '../interfaces'; - -const {GlobalConfigError} = ERRORS; - -const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = - STRINGS; - -export const RandIntGenerator = ( - name: string, - config: ConfigParams -): Generator => { - const next = () => ({ - [validatedName]: generateRandInt(getFieldToPopulate()), - }); - - const validateName = (name: string | null): string => { - if (!name || name.trim() === '') { - throw new GlobalConfigError(INVALID_NAME); - } - - return name; - }; - - const validateConfig = (config: ConfigParams): {min: number; max: number} => { - if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - if (!config.min || !config.max) { - throw new GlobalConfigError(MISSING_MIN_MAX); - } - - if (config.min >= config.max) { - throw new GlobalConfigError(INVALID_MIN_MAX(validatedName)); - } - - return {min: config.min, max: config.max}; - }; - - const validatedName = validateName(name); - const validatedConfig = validateConfig(config); - - const getFieldToPopulate = () => ({ - name: validatedName, - min: validatedConfig.min, - max: validatedConfig.max, - }); - - const generateRandInt = ( - randIntGenerator: RandIntGeneratorParams - ): number => { - const randomNumber = Math.random(); - const scaledNumber = - randomNumber * (randIntGenerator.max - randIntGenerator.min) + - randIntGenerator.min; - - return Math.trunc(scaledNumber); - }; - - return { - next, - }; -}; diff --git a/src/builtins/mock-observations/index.ts b/src/builtins/mock-observations/index.ts deleted file mode 100644 index c7488de0f..000000000 --- a/src/builtins/mock-observations/index.ts +++ /dev/null @@ -1,178 +0,0 @@ -import {DateTime, Duration} from 'luxon'; -import {z} from 'zod'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - ObservationParams, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {CommonGenerator} from './helpers/common-generator'; -import {RandIntGenerator} from './helpers/rand-int-generator'; - -import {Generator} from './interfaces/index'; - -export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Generate sets of mocked observations based on config. - */ - const execute = (inputs: PluginParams[]) => { - const {duration, timeBuckets, components, generators} = - generateParamsFromConfig(); - const generatorToHistory = new Map(); - - generators.forEach(generator => { - generatorToHistory.set(generator, []); - }); - - 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)); - }); - - return acc; - }, []); - }; - - /** - * Validates global config parameters. - */ - const validateGlobalConfig = () => { - const schema = z.object({ - 'timestamp-from': z.string(), - 'timestamp-to': z.string(), - duration: z.number(), - components: z.array(z.record(z.string())), - generators: z.object({ - common: z.record(z.string().or(z.number())), - randint: z.record(z.object({min: z.number(), max: z.number()})), - }), - }); - - return validate>(schema, globalConfig); - }; - - /** - * Configures the MockObservations Plugin for IF - */ - const generateParamsFromConfig = () => { - const { - 'timestamp-from': timestampFrom, - 'timestamp-to': timestampTo, - duration, - generators, - components, - } = validateGlobalConfig(); - const convertedTimestampFrom = DateTime.fromISO(timestampFrom, { - zone: 'UTC', - }); - const convertedTimestampTo = DateTime.fromISO(timestampTo, {zone: 'UTC'}); - - return { - duration, - timeBuckets: createTimeBuckets( - convertedTimestampFrom, - convertedTimestampTo, - duration - ), - generators: createGenerators(generators), - components, - }; - }; - - /* - * create time buckets based on start time, end time and duration of each bucket. - */ - const createTimeBuckets = ( - timestampFrom: DateTime, - timestampTo: DateTime, - duration: number, - timeBuckets: DateTime[] = [] - ): DateTime[] => { - if ( - timestampFrom < timestampTo || - timestampFrom.plus(Duration.fromObject({seconds: duration})) < timestampTo - ) { - return createTimeBuckets( - timestampFrom.plus(Duration.fromObject({seconds: duration})), - timestampTo, - duration, - [...timeBuckets, timestampFrom] - ); - } - return timeBuckets; - }; - - /* - * create generators based on a given config - */ - const createGenerators = (generatorsConfig: object): Generator[] => { - const createCommonGenerator = (config: any): Generator[] => [ - CommonGenerator(config), - ]; - - const createRandIntGenerators = (config: any): Generator[] => - Object.entries(config).map(([fieldToPopulate, value]) => - RandIntGenerator(fieldToPopulate, value as Record) - ); - - return Object.entries(generatorsConfig).flatMap(([key, value]) => - key === 'randint' - ? createRandIntGenerators(value).flat() - : createCommonGenerator(value) - ); - }; - - /* - * Creates time buckets based on start time, end time and duration of each bucket. - */ - const createObservation = ( - observationParams: ObservationParams, - generatorToHistory: Map - ): PluginParams => { - const {duration, component, timeBucket, generators} = observationParams; - const timestamp = timeBucket.toISO(); - - const generateObservation = (generator: Generator) => { - const history = generatorToHistory.get(generator) || []; - const generated: Record = generator.next(history); - - generatorToHistory.set(generator, [...history, generated.value]); - - return generated; - }; - - const generateObservations = (gen: Generator) => generateObservation(gen); - const generatedValues = generators.map(generateObservations); - const initialObservation: PluginParams = { - timestamp, - duration, - ...component, - }; - const generatedObservation = generatedValues.reduce( - (observation, generated) => Object.assign(observation, generated), - initialObservation - ); - - return generatedObservation as PluginParams; - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/mock-observations/interfaces/index.ts b/src/builtins/mock-observations/interfaces/index.ts deleted file mode 100644 index 4efae5f59..000000000 --- a/src/builtins/mock-observations/interfaces/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type Generator = { - /** - * generate the next value, optionally based on historical values - */ - next: (historical: Object[] | undefined) => Object; -}; diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md deleted file mode 100644 index 7e9c2dfbd..000000000 --- a/src/builtins/multiply/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# Multiply - -`multiply` is a generic plugin for multiplying two or more values in an `input` array. - -You provide the names of the values you want to multiply, and a name to use to append the product to the output array. - -For example, you could multiply `cpu/energy` and `network/energy` and name the result `energy-product`. `energy-product` would then be added to every observation in your input array as the product of `cpu/energy` and `network/energy`. - -## Parameters - -### Plugin config - -Two parameters are required in global config: `input-parameters` and `output-parameter`. - -`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array -`output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. - -### Inputs - -All of `input-parameters` must be available in the input array. - -## Returns - -- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. - -## Calculation - -```pseudocode -output = input0 * input1 * input2 ... inputN -``` - -## Implementation - -To run the plugin, you must first create an instance of `Multiply`. Then, you can call `execute()`. - -```typescript -import {Multiply} from 'builtins'; - -const config = { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'energy-product', -}; - -const mult = Multiply(config); -const result = await mult.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - 'cpu/energy': 0.001, - 'memory/energy': 0.0005, - }, -]); -``` - -## 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`: - -```yaml -name: multiply-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - multiply: - method: Multiply - path: 'builtin' - global-config: - input-parameters: ['cpu/energy', 'network/energy'] - output-parameter: 'energy-product' -tree: - children: - child: - pipeline: - - multiply - config: - multiply: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - network/energy: 0.001 -``` - -You can run this example by saving it as `./examples/manifests/test/multiply.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml -``` - -The results will be saved to a new `yaml` file in `./examples/outputs` - - -## Errors - -`Multiply` uses one of the IF error classes. - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the `inputs` array must contain: -- `timestamp` -- `duration` -- whatever values you passed to `input-parameters` - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts deleted file mode 100644 index cd2a74837..000000000 --- a/src/builtins/multiply/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -import {z} from 'zod'; -import { - ExecutePlugin, - PluginParams, - MultiplyConfig, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = input[param]; - - return acc; - }, - {} as Record - ); - - const validationSchema = z.record(z.string(), z.number()); - - validate(validationSchema, inputData); - - return input; - }; - - /** - * Calculate the product of each input parameter. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeGlobalConfig = validateGlobalConfig(); - const inputParameters = safeGlobalConfig['input-parameters']; - const outputParameter = safeGlobalConfig['output-parameter']; - - return inputs.map(input => { - validateSingleInput(input, inputParameters); - - return { - ...input, - [outputParameter]: calculateProduct(input, inputParameters), - }; - }); - }; - - /** - * Calculates the product of the components. - */ - const calculateProduct = (input: PluginParams, inputParameters: string[]) => - inputParameters.reduce( - (accumulator, metricToMultiply) => accumulator * input[metricToMultiply], - 1 - ); - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md deleted file mode 100644 index a0fa5d624..000000000 --- a/src/builtins/regex/README.md +++ /dev/null @@ -1,121 +0,0 @@ -# Regex - -`regex` is a generic plugin to match part of one string in an `input` and extract it into an output. - -You provide the name of the value you want to match, and a name to use to add the regex to the output array. - -``` -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 -``` - -## Parameters - -### Plugin config - -- `parameter` - a parameter by a specific configured string -- `match` - a regex by which needs to match the `parameter` -- `output` - output parameter name in the input - -### Inputs - -- `parameter` - as input parameter, must be available in the input array - -## Returns - -- `output`: the first match of `parameter` with the parameter name with `match` defined in global config. - -## 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 regex = Regex(globalConfig); - -const input = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': - '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', - }, -]; -``` - -## 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 `if` and does not have to be done explicitly by the user. The following is an example manifest that calls `regex`: - -```yaml -name: regex-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - regex: - method: Regex - path: 'builtin' - global-config: - parameter: physical-processor - match: ^[^,]+ - output: cpu/name -tree: - children: - child: - pipeline: - - regex - config: - regex: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - physical-processor: 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 -``` - -You can run this example by saving it as `manifests/plugins/regex.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if --manifest manifests/examples/regex.yml --output manifests/outputs/regex.yml -``` - -The results will be saved to a new `yaml` file in `manifests/outputs`. - -## Errors - -`Regex` uses three of IF's error classes: - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the `inputs` array must contain: -- `timestamp` -- `duration` -- whatever value you passed to `parameter` - - -### `GlobalConfigError` - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: - -- `parameter`: a string containing the name of a value in the inputs array -- `match`: a valid regex pattern -- `output`: a string - -You can fix this error by checking you are providing valid values for each parameter in the config. - - -### `RegexMismatchError` - -This error arises when the requested regex cannot find any matches in the given data. If there are multiple matches, the plugin returns the first, but if there are none, it throws this error. - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/regex/index.ts b/src/builtins/regex/index.ts deleted file mode 100644 index 8d382ec74..000000000 --- a/src/builtins/regex/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; - -export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const schema = z.object({ - parameter: z.string().min(1), - match: z.string().min(1), - output: z.string(), - }); - - return validate>(schema, globalConfig); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = (input: PluginParams, parameter: string) => { - if (!input[parameter]) { - throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); - } - - return input; - }; - - /** - * Executes the regex of the given parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const {parameter: parameter, match, output} = safeGlobalConfig; - - return inputs.map(input => { - const safeInput = Object.assign( - {}, - input, - validateSingleInput(input, parameter) - ); - - return { - ...input, - [output]: extractMatching(safeInput, parameter, match), - }; - }); - }; - - /** - * Extracts a substring from the given input parameter that matches the provided regular expression pattern. - */ - const extractMatching = ( - input: PluginParams, - parameter: string, - match: string - ) => { - if (!match.startsWith('/')) { - match = '/' + match; - } - - if (!match.endsWith('/g') && !match.endsWith('/')) { - match += '/'; - } - - const regex = eval(match); - const matchedItem = input[parameter].match(regex); - - if (!matchedItem || !matchedItem[0]) { - throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); - } - - return matchedItem[0]; - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md deleted file mode 100644 index 97b6ce4af..000000000 --- a/src/builtins/sci-embodied/README.md +++ /dev/null @@ -1,124 +0,0 @@ -# SCI-Embodied - -Software systems cause emissions through the hardware that they operate on, both through the energy that the physical hardware consumes and the emissions associated with manufacturing the hardware. Embodied carbon refers to the carbon emitted during the manufacture and eventual disposal of a component. It is added to the operational carbon (carbon emitted when a component is used) to give an overall SCI score. - -Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions) - -## Parameters - -### Plugin config - -Not Needed - -### Inputs - -- `device/emissions-embodied`: the sum of Life Cycle Assessment (LCA) emissions for the component -- `device/expected-lifespan`: the length of time, in seconds, between a component's manufacture and its disposal -- `resources-reserved`: the number of resources reserved for use by the software -- `resources-total`: the total number of resources available -- `duration`: the amount of time covered by an observation, in this context it is used as the share of the total life span of the hardware reserved for use by an application, in seconds. - -> Note that if you have a plugin pipeline that adds `vcpus-allocated` and `vcpus-total` to each observation, such as the `cloud-metadata` plugin, those values will be used **in preference** to the given `resources-reserved` and `resources-total` fields. - -## Returns - -- `carbon-embodied`: the carbon emitted in manufacturing and disposing of a component, in gCO2eq - -## Calculation - -To calculate the embodied carbon, `m` for a software application, use the equation: - -``` -m = te * ts * rs -``` - -Where: - -- `device/emissions-embodied` = Total embodied emissions; the sum of Life Cycle Assessment (LCA) emissions for the component. - -- `timeShare` = Time-share; the share of the total life span of the hardware reserved for use by an application. - - - `timeShare` is calculated as `duration/'device/expected-lifespan'`, where: - - `duration` = the length of time the hardware is reserved for use by the software. - - `device/expected-lifespan` = Expected lifespan: the length of time, in seconds, between a component's manufacture and its disposal. - -- `resourceShare` = Resource-share; the share of the total available resources of the hardware reserved for use by an application. - - `resourceShare` is calculated as `resources-reserved/resources-total`, where: - - `resources-reserved` = Resources reserved; the number of resources reserved for use by the software. - - `resources-total` = Total Resources; the total number of resources available. - -## Implementation - -IF implements the plugin based on the logic described above. To run the plugin, you must first create an instance of `SciEmbodied`. Then, you can call `execute()` to return `m`. - -## Usage - -The following snippet demonstrates how to call the `sci-embodied` plugin from Typescript. - -```typescript -import {SciEmbodied} from 'builtins'; - -const sciEmbodied = SciEmbodied(); -const results = await sciEmbodied.execute([ - { - 'device/emissions-embodied': 200, // in gCO2e for total resource units - duration: 60 * 60 * 24 * 30, // time reserved in seconds, can point to another field "duration" - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, // lifespan in seconds (4 years) - 'resources-reserved': 1, // resource units reserved / used - 'resources-total': 1, // total resource units available - }, -]); -``` - -## 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`: - -```yaml -name: sci-embodied -description: simple demo invoking sci-embodied -tags: -initialize: - outputs: - - yaml - plugins: - sci-embodied: - method: SciEmbodied - path: 'builtins' -tree: - children: - child: - pipeline: - - sci-embodied # duration & config -> embodied - defaults: - device/emissions-embodied: 1533.120 # gCO2eq - device/expected-lifespan: 3 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 -``` - -You can run this example `manifest` by executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml -``` - -The results will be saved to a new `yaml` file in `./examples/outputs`. - - -## Errors - -`SciEmbodied` uses one of IF's error classes - -### `SciEmbodiedError` - -This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. - -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 diff --git a/src/builtins/sci-embodied/index.ts b/src/builtins/sci-embodied/index.ts deleted file mode 100644 index a88017e9f..000000000 --- a/src/builtins/sci-embodied/index.ts +++ /dev/null @@ -1,130 +0,0 @@ -import {z} from 'zod'; -import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; - -import {validate, allDefined} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {SCI_EMBODIED_ERROR} = STRINGS; - -export const SciEmbodied = (): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - const METRICS = [ - 'device/emissions-embodied', - 'device/expected-lifespan', - 'resources-reserved', - 'vcpus-allocated', - 'resources-total', - 'vcpus-total', - ]; - - /** - * Calculate the Embodied carbon for a list of inputs. - */ - const execute = (inputs: PluginParams[]) => - inputs.map(input => { - const safeInput = validateInput(input); - - return { - ...input, - 'carbon-embodied': calculateEmbodiedCarbon(safeInput), - }; - }); - - /** - * Calculate the Embodied carbon for the input. - * M = totalEmissions * (duration/ExpectedLifespan) * (resourcesReserved/totalResources) - */ - const calculateEmbodiedCarbon = (input: PluginParams) => { - const totalEmissions = input['device/emissions-embodied']; - const duration = input['duration']; - const expectedLifespan = input['device/expected-lifespan']; - const resourcesReserved = - input['vcpus-allocated'] || input['resources-reserved']; - const totalResources = input['vcpus-total'] || input['resources-total']; - - return ( - totalEmissions * - (duration / expectedLifespan) * - (resourcesReserved / totalResources) - ); - }; - - /** - * Checks for required fields in input. - */ - const validateInput = (input: PluginParams) => { - const commonSchemaPart = (errorMessage: (unit: string) => string) => ({ - 'device/emissions-embodied': z - .number({ - invalid_type_error: errorMessage('gCO2e'), - }) - .gte(0) - .min(0), - 'device/expected-lifespan': z - .number({ - invalid_type_error: errorMessage('gCO2e'), - }) - .gte(0) - .min(0), - duration: z - .number({ - invalid_type_error: errorMessage('seconds'), - }) - .gte(1), - }); - - const vcpusSchemaPart = { - 'vcpus-allocated': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - 'vcpus-total': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - }; - - const resourcesSchemaPart = { - 'resources-reserved': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - 'resources-total': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - }; - - const schemaWithVcpus = z.object({ - ...commonSchemaPart(SCI_EMBODIED_ERROR), - ...vcpusSchemaPart, - }); - const schemaWithResources = z.object({ - ...commonSchemaPart(SCI_EMBODIED_ERROR), - ...resourcesSchemaPart, - }); - - const schema = schemaWithVcpus.or(schemaWithResources).refine(allDefined, { - message: `All ${METRICS} should be present.`, - }); - - return validate>(schema, input); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md deleted file mode 100644 index 592bd1ed0..000000000 --- a/src/builtins/sci/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# SCI (software carbon intensity) - -[SCI](https://sci-guide.greensoftware.foundation/) represents the amount of carbon emitted per [functional unit](https://sci-guide.greensoftware.foundation/R/). - -## Parameters - -### Plugin global config - -- `functional-unit`: the name of the functional unit in which to express the carbon impact (required) - - -### Inputs - - -- `carbon`: total carbon in gCO2eq (required) -- `functional-unit`: whatever `functional-unit` you define in global config also has to be present in each input, for example if you provide `functional-unit: requests` in global config, `requests` must be present in your input data. - -## Returns - -- `sci`: carbon expressed in terms of the given functional unit - ->Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. - -## Calculation - -SCI is calculated as: - -```pseudocode -sci = carbon / functional unit -``` - - -## IF Implementation - -To run the plugin, you must first create an instance of `Sci`. Then, you can call `execute()` to return `sci`. - -```typescript -import {Sci} from 'builtins'; - -const sci = Sci({'functional-unit': 'requests'}); -const results = await sci.execute( - [ - { - 'carbon': 5' - duration: 1, - requests: 100, - }, - ] -); -``` - -## 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`: - -```yaml -name: sci-demo -description: example invoking sci plugin -tags: -initialize: - outputs: - - yaml - plugins: - sci: - method: Sci - path: 'builtin' - global-config: - functional-unit: 'requests' -tree: - children: - child: - pipeline: - - sci - config: - inputs: - - timestamp: 2023-07-06T00:00 - carbon: 5 - duration: 1 - requests: 100 -``` - -You can run this example `manifest` by saving it as `./manifests/plugins/sci.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml -``` - -The results will be saved to a new `yaml` file. - -## Errors - -`SCI` uses one of the IF error classes. - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. - -Every element in the `inputs` array must contain: -- `timestamp` -- `duration` -- `carbon`: a numeric value named `carbon` must exist in the inputs array -- whatever value you passed to `functional-unit` - - -### Validation errors - -There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/sci/config.ts b/src/builtins/sci/config.ts deleted file mode 100644 index edbf8881e..000000000 --- a/src/builtins/sci/config.ts +++ /dev/null @@ -1,40 +0,0 @@ -export const TIME_UNITS_IN_SECONDS: Record = { - s: 1, - second: 1, - sec: 1, - secs: 1, - seconds: 1, - min: 60, - mins: 60, - minute: 60, - minutes: 60, - h: 3600, - hs: 3600, - hr: 3600, - hrs: 3600, - hour: 3600, - hours: 3600, - d: 86400, - ds: 86400, - day: 86400, - days: 86400, - w: 604800, - ws: 604800, - wk: 604800, - wks: 604800, - week: 604800, - weeks: 604800, - m: 2419200, - mnth: 2419200, - mth: 2419200, - mnths: 2419200, - mths: 2419200, - month: 2419200, - months: 2419200, - y: 31536000, - ys: 31536000, - yr: 31536000, - yrs: 31536000, - year: 31536000, - years: 31536000, -}; diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts deleted file mode 100644 index 47d495351..000000000 --- a/src/builtins/sci/index.ts +++ /dev/null @@ -1,91 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; - -import {validate, allDefined} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {MissingInputDataError} = ERRORS; -const { - MISSING_FUNCTIONAL_UNIT_CONFIG, - MISSING_FUNCTIONAL_UNIT_INPUT, - SCI_MISSING_FN_UNIT, - ZERO_DIVISION, -} = STRINGS; - -export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Validates node and gloabl configs. - */ - const validateConfig = (config?: ConfigParams) => { - const schema = z - .object({ - 'functional-unit': z.string(), - }) - .refine(data => data['functional-unit'], { - message: MISSING_FUNCTIONAL_UNIT_CONFIG, - }); - - return validate>(schema, config); - }; - - /** - * Calculate the total emissions for a list of inputs. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => - inputs.map((input, index) => { - const safeInput = validateInput(input); - const functionalUnit = input[globalConfig['functional-unit']]; - - if (functionalUnit === 0) { - console.warn(ZERO_DIVISION(Sci.name, index)); - - return { - ...input, - sci: safeInput['carbon'], - }; - } - - return { - ...input, - sci: safeInput['carbon'] / functionalUnit, - }; - }); - - /** - * Checks for fields in input. - */ - const validateInput = (input: PluginParams) => { - const validatedConfig = validateConfig(globalConfig); - - if ( - !( - validatedConfig['functional-unit'] in input && - input[validatedConfig['functional-unit']] >= 0 - ) - ) { - throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); - } - - const schema = z - .object({ - carbon: z.number().gte(0), - duration: z.number().gte(1), - }) - .refine(allDefined, { - message: SCI_MISSING_FN_UNIT(globalConfig['functional-unit']), - }); - - return validate>(schema, input); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md deleted file mode 100644 index bacba1255..000000000 --- a/src/builtins/shell/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Shell Plugin - -The `shell` is a wrapper enabling plugins implemented in any other programming language to be executed as a part of IF pipeline. For example, you might have a standalone plugin written in Python. `shell` spawns a subprocess to execute that Python plugin in a dedicated shell and pipes the results back into IF's Typescript process. - -## Parameters - -### Plugin global config - -The plugin should be initialized as follows: - -``` -initialize: - plugins: - shell: - method: Shell - path: 'builtin' - global-config: - command: python3 /usr/local/bin/sampler -``` - -The `shell` plugin interface requires a path to the plugin command. This path is provided in the plugin configuration with the name command. The path should be appended by the execution command, for example, if the executable is a binary, the path would be prepended with `./` on a Linux system. If the plugin is a Python script, you can prepend `python`. - -- `command`: the path to the plugin executable along with the execution command as it would be entered into a shell. - -### Inputs - -The parameters included in the `inputs` field in the `manifest` depend entirely on the plugin itself. A typical plugin might expect the following common data to be provided as `inputs`: - -- `timestamp`: A timestamp for the specific input -- `duration`: The length of time these specific inputs cover - -## 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. - -## Implementation - -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 result = await output.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'cpu/energy': 0.002, - 'memory/energy': 0.000005, - }, -]); -``` - -## Considerations - -The `shell` is designed to run arbitrary external plugins. This means IF does not necessarily know what calculations are being executed in the external plugin. There is no strict requirement on the return type, as this depends upon the calculations and the position of the external plugin in a plugin pipeline. For example, one external plugin might carry out the entire end-to-end SCI calculation, taking in usage inputs and returning `sci`. In this case, the plugin is expected to return `sci` and it would be the only plugin invoked in the `manifest`. - -However, it is also entirely possible to have external plugins that only deliver some small part of the overall pipeline, and rely on IF other plugins to do the rest. - -Since the design space for external plugins is so large, it is up to external plugin developers to ensure compatibility with IF built-ins. - -## Example manifest - -IF users will typically call the shell plugin as part of a pipeline defined in a `manifest` file. In this case, instantiating and configuring the plugin is handled by and does not have to be done explicitly by the user. The following is an example `manifest` that calls an external plugin via `shell`. It assumes the plugin takes `cpu/energy` and `memory/energy` as inputs and returns `energy`: - -```yaml -name: shell-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - sampler: - method: Shell - path: 'builtin' - global-config: - command: python3 /usr/local/bin/sampler -tree: - children: - child: - pipeline: - - sampler - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 # Secs - cpu/energy: 0.002 - memory/energy: 0.000005 -``` - -In this hypothetical example, the plugin is written in Python and invoked by executing `python3 /usr/local/bin/sampler` in a shell. -The plugin should return an `output` looking as follows: - -```yaml -name: shell-demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - sampler: - method: Shell - path: 'builtin' - global-config: - command: python3 /usr/local/bin/sampler -tree: - children: - child: - pipeline: - - sampler - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 # Secs - cpu/energy: 0.002 - memory/energy: 0.000005 - outputs: - - timestamp: 2023-07-06T00:00 - duration: 1 # Secs - cpu/energy: 0.002 - memory/energy: 0.000005 - energy: 0.02 # added by plugin -``` - -You can run this example `manifest` by saving it as `manifests/plugins/shell.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml -``` - -The results will be saved to a new `yaml` file. - - -## Errors - -`Shell` uses one of the error classes provided by IF - -### `ProcessExecutionError` - -This error is thrown when the program invoked in the spawned shell fails for some reason that is not known to IF. Since the shell executes arbitrary code, it is difficult for IF to provide specific errors - this is delegated to the developers of the executed program. - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/shell/index.ts b/src/builtins/shell/index.ts deleted file mode 100644 index 352ee6bcd..000000000 --- a/src/builtins/shell/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -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 {validate} from '../../util/validations'; - -const {ProcessExecutionError} = ERRORS; - -export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Calculate the total emissions for a list of inputs. - */ - const execute = (inputs: PluginParams[]): any[] => { - const inputWithConfig = Object.assign({}, inputs[0], validateConfig()); - const command = inputWithConfig.command; - const inputAsString: string = dump(inputs, {indent: 2}); - const results = runModelInShell(inputAsString, command); - - return results?.outputs?.flat(); - }; - - /** - * Checks for required fields in input. - */ - const validateConfig = () => { - const schema = z.object({ - command: z.string(), - }); - - return validate>(schema, globalConfig); - }; - - /** - * Runs the model in a shell. Spawns a child process to run an external IMP, - * an executable with a CLI exposing two methods: `--execute` and `--manifest`. - * The shell command then calls the `--command` method passing var manifest as the path to the desired manifest file. - */ - const runModelInShell = (input: string, command: string) => { - try { - const [executable, ...args] = command.split(' '); - - const result: SpawnSyncReturns = spawnSync(executable, args, { - input, - encoding: 'utf8', - }); - const outputs = loadAll(result.stdout); - - return {outputs}; - } catch (error: any) { - throw new ProcessExecutionError(error.message); - } - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md deleted file mode 100644 index 8ff9a922f..000000000 --- a/src/builtins/subtract/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# Subtract - -`subtract` is a generic plugin for doing arithmetic subtractions of two or more values in an `input` array. - -You provide the names of the values you want to subtract, and a name to use to add the subtraction to the output array. - -For example, you could subtract `cpu/energy` and `network/energy` and name the result `offset/energy`. `offset/energy` would then be added to every observation in your input array as the diff of `cpu/energy` and `network/energy`. - -## Parameters - -### Plugin config - -Two parameters are required in global config: `input-parameters` and `output-parameter`. - -`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array -`output-parameter`: a string defining the name to use to add the result of the diff to the output array. - -### Inputs - -All of `input-parameters` must be available in the input array. - -## Returns - -- `output-parameter`: the subtraction of all `input-parameters` with the parameter name defined by `output-parameter` in global config. - -## Calculation - -```pseudocode -output = input0 - input1 - input2 ... - inputN -``` - -## Implementation - -To run the plugin, you must first create an instance of `Subtract`. Then, you can call `execute()`. - -```typescript -import {Subtract} from 'builtins'; - -const config = { - inputParameters: ['cpu/energy', 'network/energy'], - outputParameter: 'offset/energy', -}; - -const subtract = Subtract(config); -const result = subtract subtract.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - 'cpu/energy': 0.005, - 'memory/energy': 0.0001, - }, -]); -``` - -## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `subtract`: - -```yaml -name: subtract demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - subtract: - method: Subtract - path: 'builtin' - global-config: - input-parameters: ['cpu/energy', 'network/energy'] - output-parameter: 'energy/diff' -tree: - children: - child: - pipeline: - - subtract - config: - subtract: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.003 - network/energy: 0.001 -``` - -You can run this example by saving it as `./examples/manifests/test/subrtact.yml` and executing the following command from the project root: - -```sh -npm i -g @grnsft/if -if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml -``` - -The results will be saved to a new `yaml` file in `manifests/outputs`. - - -## Errors - -`Subtract` uses one of IF's error classes: - -### `InputValidationError` - -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 diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts deleted file mode 100644 index 797b259c1..000000000 --- a/src/builtins/subtract/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -import {z} from 'zod'; -import { - ExecutePlugin, - PluginParams, - SubtractConfig, -} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = input[param]; - - return acc; - }, - {} as Record - ); - - const validationSchema = z.record(z.string(), z.number()); - - validate(validationSchema, inputData); - - return input; - }; - - /** - * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const { - 'input-parameters': inputParameters, - 'output-parameter': outputParameter, - } = validateGlobalConfig(); - - return inputs.map(input => { - validateSingleInput(input, inputParameters); - - return { - ...input, - [outputParameter]: calculateDiff(input, inputParameters), - }; - }); - }; - - /** - * Calculates the diff between the 1st item in the inputs nad the rest of the items - */ - const calculateDiff = (input: PluginParams, inputParameters: string[]) => { - const [firstItem, ...restItems] = inputParameters; - - return restItems.reduce( - (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], - input[firstItem] // Starting accumulator with the value of the first item - ); - }; - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md deleted file mode 100644 index ea0f0113d..000000000 --- a/src/builtins/sum/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# Sum - -`sum` is a generic plugin for doing arithmetic sums of two or more values in an `input` array. - -You provide the names of the values you want to sum, and a name to use to add the sum to the output array. - -For example, you could add `cpu/energy` and `network/energy` and name the result `energy`. `energy` would then be added to every observation in your input array as the sum of `cpu/energy` and `network/energy`. - -## Parameters - -### Plugin config - -Two parameters are required in global config: `input-parameters` and `output-parameter`. - -`input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array -`output-parameter`: a string defining the name to use to add the result of summing the input parameters to the output array. - -### Inputs - -All of `input-parameters` must be available in the input array. - -## Returns - -- `output-parameter`: the sum of all `input-parameters` with the parameter name defined by `output-parameter` in global config. - -## Calculation - -```pseudocode -output = input0 + input1 + input2 ... inputN -``` - -## Implementation - -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 sum = Sum(config); -const result = sum.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'cpu/energy': 0.001, - 'memory/energy': 0.0005, - }, -]); -``` - -## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `sum`: - -```yaml -name: sum demo -description: -tags: -initialize: - outputs: - - yaml - plugins: - sum: - method: Sum - path: 'builtin' - global-config: - input-parameters: ['cpu/energy', 'network/energy'] - output-parameter: 'energy' -tree: - children: - child: - pipeline: - - sum - config: - sum: - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - network/energy: 0.001 -``` - -You can run this example by saving it as `./examples/manifests/sum.yml` and executing the following command from the project root: - -```sh -if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml -``` - -The results will be saved to a new `yaml` file in `./examples/outputs`. - - -## Errors - -`Sum` exposes two of the IF error classes. - -### GlobalConfigError - -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. - -The required parameters are: -- `input-parameters`: this must be an array of strings, each being the name of a value in the `inputs` array -- `output-parameter`: this must be a string - -You can fix this error by checking you are providing valid values for each parameter in the config. - -### `MissingInputDataError` - -This error arises when a necessary piece of input data is missing from the `inputs` array. -Every element in the ``inputs` array must contain: - -- `timestamp` -- `duration` -- whatever values you passed to `input-parameters` - - -For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors). diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts deleted file mode 100644 index 57437ba31..000000000 --- a/src/builtins/sum/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, SumConfig} from '@grnsft/if-core/types'; - -import {validate} from '../../util/validations'; - -import {STRINGS} from '../../config'; - -const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -export const Sum = (globalConfig: SumConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Calculate the sum of each input-paramters. - */ - const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); - const inputParameters = safeGlobalConfig['input-parameters']; - const outputParameter = safeGlobalConfig['output-parameter']; - - return inputs.map(input => { - validateSingleInput(input, inputParameters); - - return { - ...input, - [outputParameter]: calculateSum(input, inputParameters), - }; - }); - }; - - /** - * Checks global config value are valid. - */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const globalConfigSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), - }); - - return validate>( - globalConfigSchema, - globalConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = input[param]; - - return acc; - }, - {} as Record - ); - const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; - }; - - /** - * Calculates the sum of the energy components. - */ - const calculateSum = (input: PluginParams, inputParameters: string[]) => - inputParameters.reduce( - (accumulator, metricToSum) => accumulator + input[metricToSum], - 0 - ); - - return { - metadata, - execute, - }; -}; diff --git a/src/builtins/time-sync.ts b/src/builtins/time-sync.ts deleted file mode 100644 index 8b37241b8..000000000 --- a/src/builtins/time-sync.ts +++ /dev/null @@ -1,459 +0,0 @@ -import {isDate} from 'node:util/types'; - -import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - ExecutePlugin, - PluginParams, - PaddingReceipt, - TimeNormalizerConfig, - TimeParams, -} from '@grnsft/if-core/types'; - -import {parameterize} from '../lib/parameterize'; - -import {validate} from '../util/validations'; - -import {STRINGS} from '../config'; - -Settings.defaultZone = 'utc'; - -const { - GlobalConfigError, - InvalidDateInInputError, - InvalidPaddingError, - InvalidInputError, -} = ERRORS; - -const { - INVALID_TIME_NORMALIZATION, - INVALID_OBSERVATION_OVERLAP, - AVOIDING_PADDING_BY_EDGES, - INVALID_DATE_TYPE, - START_LOWER_END, - TIMESTAMP_REQUIRED, - INVALID_DATETIME, -} = STRINGS; - -export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Take input array and return time-synchronized input array. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const validatedConfig = validateGlobalConfig(); - const timeParams = { - startTime: DateTime.fromISO(validatedConfig['start-time']), - endTime: DateTime.fromISO(validatedConfig['end-time']), - interval: validatedConfig.interval, - allowPadding: validatedConfig['allow-padding'], - }; - - const pad = checkForPadding(inputs, timeParams); - validatePadding(pad, timeParams); - - const paddedInputs = padInputs(inputs, pad, timeParams); - - const flattenInputs = paddedInputs.reduce( - (acc: PluginParams[], input, index) => { - const safeInput = Object.assign({}, input, validateInput(input, index)); - const currentMoment = parseDate(safeInput.timestamp); - - /** Checks if not the first input, then check consistency with previous ones. */ - if (index > 0) { - const previousInput = paddedInputs[index - 1]; - const previousInputTimestamp = parseDate(previousInput.timestamp); - - /** Checks for timestamps overlap. */ - if ( - parseDate(previousInput.timestamp).plus({ - seconds: previousInput.duration, - }) > currentMoment - ) { - throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); - } - - const compareableTime = previousInputTimestamp.plus({ - seconds: previousInput.duration, - }); - - const timelineGapSize = currentMoment - .diff(compareableTime) - .as('seconds'); - - /** Checks if there is gap in timeline. */ - if (timelineGapSize > 1) { - acc.push( - ...getZeroishInputPerSecondBetweenRange( - compareableTime, - currentMoment, - safeInput - ) - ); - } - } - /** Break down current observation. */ - for (let i = 0; i < safeInput.duration; i++) { - const normalizedInput = breakDownInput(safeInput, i); - - acc.push(normalizedInput); - } - - return trimInputsByGlobalTimeline(acc, timeParams); - }, - [] as PluginParams[] - ); - - const sortedInputs = flattenInputs.sort((a, b) => - parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') - ); - - return resampleInputs(sortedInputs, timeParams) as PluginParams[]; - }; - - const parseDate = (date: Date | string) => { - if (!date) { - return DateTime.invalid('Invalid date'); - } - - // dates are passed to time-sync.ts both in ISO 8601 format - // and as a Date object (from the deserialization of a YAML file) - // if the YAML parser fails to identify as a date, it passes as a string - if (isDate(date)) { - return DateTime.fromJSDate(date); - } - - if (typeof date === 'string') { - return DateTime.fromISO(date); - } - - throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); - }; - - /** - * Validates input parameters. - */ - const validateInput = (input: PluginParams, index: number) => { - const schema = z.object({ - timestamp: z - .string({ - required_error: TIMESTAMP_REQUIRED(index), - }) - .datetime({ - message: INVALID_DATETIME(index), - }) - .or(z.date()), - duration: z.number(), - }); - - return validate>(schema, input); - }; - - /** - * Validates global config parameters. - */ - const validateGlobalConfig = () => { - if (globalConfig === undefined) { - throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); - } - - const schema = z - .object({ - 'start-time': z.string().datetime(), - 'end-time': z.string().datetime(), - interval: z.number(), - 'allow-padding': z.boolean(), - }) - .refine(data => data['start-time'] < data['end-time'], { - message: START_LOWER_END, - }); - - return validate>(schema, globalConfig); - }; - - /** - * Calculates minimal factor. - */ - const convertPerInterval = (value: number, duration: number) => - value / duration; - - /** - * Normalize time per given second. - */ - const normalizeTimePerSecond = ( - currentRoundMoment: Date | string, - i: number - ) => { - const thisMoment = parseDate(currentRoundMoment).startOf('second'); - - return thisMoment.plus({seconds: i}); - }; - - /** - * Breaks down input per minimal time unit. - */ - const breakDownInput = (input: PluginParams, i: number) => { - const inputKeys = Object.keys(input); - - return inputKeys.reduce((acc, key) => { - const method = parameterize.getAggregationMethod(key); - - if (key === 'timestamp') { - const perSecond = normalizeTimePerSecond(input.timestamp, i); - acc[key] = perSecond.toUTC().toISO() ?? ''; - - return acc; - } - - /** @todo use user defined resolution later */ - if (key === 'duration') { - acc[key] = 1; - - return acc; - } - - acc[key] = - method === 'sum' - ? convertPerInterval(input[key], input['duration']) - : input[key]; - - return acc; - }, {} as PluginParams); - }; - - /** - * Populates object to fill the gaps in observational timeline using zeroish values. - */ - const fillWithZeroishInput = ( - input: PluginParams, - missingTimestamp: DateTimeMaybeValid - ) => { - const metrics = Object.keys(input); - - return metrics.reduce((acc, metric) => { - if (metric === 'timestamp') { - acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; - - return acc; - } - - /** @todo later will be changed to user defined interval */ - if (metric === 'duration') { - acc[metric] = 1; - - return acc; - } - - if (metric === 'time-reserved') { - acc[metric] = acc['duration']; - - return acc; - } - - const method = parameterize.getAggregationMethod(metric); - - if (method === 'avg' || method === 'sum') { - acc[metric] = 0; - - return acc; - } - - acc[metric] = input[metric]; - - return acc; - }, {} as PluginParams); - }; - - /** - * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. - */ - const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { - const {start, end} = pad; - const isPaddingNeeded = start || end; - - if (!params.allowPadding && isPaddingNeeded) { - throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); - } - }; - - /** - * Checks if padding is needed either at start of the timeline or the end and returns status. - */ - const checkForPadding = ( - inputs: PluginParams[], - params: TimeParams - ): PaddingReceipt => { - const startDiffInSeconds = parseDate(inputs[0].timestamp) - .diff(params.startTime) - .as('seconds'); - - const lastInput = inputs[inputs.length - 1]; - - const endDiffInSeconds = parseDate(lastInput.timestamp) - .plus({second: lastInput.duration}) - .diff(params.endTime) - .as('seconds'); - - return { - start: startDiffInSeconds > 0, - end: endDiffInSeconds < 0, - }; - }; - - /** - * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. - * For methods is `avg` and `none` calculating average of the frame. - */ - const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => - inputsInTimeslot.reduce((acc, input, index, inputs) => { - const metrics = Object.keys(input); - - metrics.forEach(metric => { - const method = parameterize.getAggregationMethod(metric); - acc[metric] = acc[metric] ?? 0; - - if (metric === 'timestamp') { - acc[metric] = inputs[0][metric]; - - return; - } - - if (method === 'sum') { - acc[metric] += input[metric]; - - return; - } - - if (method === 'none') { - acc[metric] = input[metric]; - - return; - } - - /** - * If timeslot contains records more than one, then divide each metric by the timeslot length, - * so that their sum yields the timeslot average. - */ - if ( - inputsInTimeslot.length > 1 && - index === inputsInTimeslot.length - 1 - ) { - acc[metric] /= inputsInTimeslot.length; - - return; - } - - acc[metric] += input[metric]; - }); - - return acc; - }, {} as PluginParams); - - /** - * Takes each array frame with interval length, then aggregating them together as from units.yaml file. - */ - const resampleInputs = (inputs: PluginParams[], params: TimeParams) => - inputs.reduce((acc: PluginParams[], _input, index, inputs) => { - const frameStart = index * params.interval; - const frameEnd = (index + 1) * params.interval; - const inputsFrame = inputs.slice(frameStart, frameEnd); - - const resampledInput = resampleInputFrame(inputsFrame); - - /** Checks if resampled input is not empty, then includes in result. */ - if (Object.keys(resampledInput).length > 0) { - acc.push(resampledInput); - } - - return acc; - }, [] as PluginParams[]); - - /** - * Pads zeroish inputs from the beginning or at the end of the inputs if needed. - */ - const padInputs = ( - inputs: PluginParams[], - pad: PaddingReceipt, - params: TimeParams - ): PluginParams[] => { - const {start, end} = pad; - const paddedFromBeginning = []; - - if (start) { - paddedFromBeginning.push( - ...getZeroishInputPerSecondBetweenRange( - params.startTime, - parseDate(inputs[0].timestamp), - inputs[0] - ) - ); - } - - const paddedArray = paddedFromBeginning.concat(inputs); - - if (end) { - const lastInput = inputs[inputs.length - 1]; - const lastInputEnd = parseDate(lastInput.timestamp).plus({ - seconds: lastInput.duration, - }); - paddedArray.push( - ...getZeroishInputPerSecondBetweenRange( - lastInputEnd, - params.endTime.plus({seconds: 1}), - lastInput - ) - ); - } - - return paddedArray; - }; - - const getZeroishInputPerSecondBetweenRange = ( - startDate: DateTimeMaybeValid, - endDate: DateTimeMaybeValid, - templateInput: PluginParams - ) => { - const array: PluginParams[] = []; - const dateRange = Interval.fromDateTimes(startDate, endDate); - - for (const interval of dateRange.splitBy({second: 1})) { - array.push( - fillWithZeroishInput( - templateInput, - // as far as I can tell, start will never be null - // because if we pass an invalid start/endDate to - // Interval, we get a zero length array as the range - interval.start || DateTime.invalid('not expected - start is null') - ) - ); - } - - return array; - }; - - /* - * Checks if input's timestamp is included in global specified period then leaves it, otherwise. - */ - const trimInputsByGlobalTimeline = ( - inputs: PluginParams[], - params: TimeParams - ): PluginParams[] => - inputs.reduce((acc: PluginParams[], item) => { - const {timestamp} = item; - - if ( - parseDate(timestamp) >= params.startTime && - parseDate(timestamp) <= params.endTime - ) { - acc.push(item); - } - - return acc; - }, [] as PluginParams[]); - - return {metadata, execute}; -}; From 23e083586dc6afe764a7ae1419c5f057ad580398 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:19:50 +0400 Subject: [PATCH 324/863] revert(src): drop old tests --- src/__tests__/integration/helpers/common.ts | 29 - .../integration/helpers/module-installer.ts | 11 - src/__tests__/integration/scenarios/sci-e.ts | 75 -- .../integration/templates/integration.yaml | 16 - src/__tests__/integration/test-data/sci-e.ts | 11 - .../unit/builtins/CommonGenerator.test.ts | 41 - .../unit/builtins/RandIntGenerator.test.ts | 60 -- .../unit/builtins/coefficient.test.ts | 127 --- .../unit/builtins/copy-param.test.ts | 124 --- .../unit/builtins/csv-lookup.test.ts | 514 ------------ src/__tests__/unit/builtins/divide.test.ts | 183 ---- src/__tests__/unit/builtins/exponent.test.ts | 118 --- .../unit/builtins/export-csv-raw.test.ts | 77 -- .../unit/builtins/export-csv.test.ts | 236 ------ .../unit/builtins/export-log.test.ts | 36 - .../unit/builtins/export-yaml.test.ts | 51 -- src/__tests__/unit/builtins/group-by.test.ts | 177 ---- .../unit/builtins/interpolation.test.ts | 221 ----- .../unit/builtins/mock-observations.test.ts | 326 -------- src/__tests__/unit/builtins/multiply.test.ts | 101 --- src/__tests__/unit/builtins/regex.test.ts | 152 ---- .../unit/builtins/sci-embodied.test.ts | 306 ------- src/__tests__/unit/builtins/sci.test.ts | 165 ---- src/__tests__/unit/builtins/shell.test.ts | 97 --- src/__tests__/unit/builtins/subtract.test.ts | 101 --- src/__tests__/unit/builtins/sum.test.ts | 127 --- src/__tests__/unit/builtins/time-sync.test.ts | 781 ------------------ src/__tests__/unit/lib/aggregate.test.ts | 201 ----- src/__tests__/unit/lib/compare.test.ts | 114 --- src/__tests__/unit/lib/compute.test.ts | 237 ------ src/__tests__/unit/lib/environment.test.ts | 35 - src/__tests__/unit/lib/exhaust.test.ts | 92 --- src/__tests__/unit/lib/initialize.test.ts | 180 ---- src/__tests__/unit/lib/load.test.ts | 143 ---- src/__tests__/unit/lib/parameterize.test.ts | 114 --- .../unit/util/aggregation-helper.test.ts | 100 --- src/__tests__/unit/util/args.test.ts | 522 ------------ src/__tests__/unit/util/debug-logger.test.ts | 96 --- src/__tests__/unit/util/fs.test.ts | 144 ---- src/__tests__/unit/util/helpers.test.ts | 687 --------------- src/__tests__/unit/util/json.test.ts | 26 - src/__tests__/unit/util/log-memoize.test.ts | 31 - src/__tests__/unit/util/logger.test.ts | 11 - src/__tests__/unit/util/npm.test.ts | 265 ------ src/__tests__/unit/util/os-checker.test.ts | 151 ---- .../unit/util/plugin-storage.test.ts | 68 -- src/__tests__/unit/util/yaml.test.ts | 74 -- 47 files changed, 7554 deletions(-) delete mode 100644 src/__tests__/integration/helpers/common.ts delete mode 100644 src/__tests__/integration/helpers/module-installer.ts delete mode 100644 src/__tests__/integration/scenarios/sci-e.ts delete mode 100644 src/__tests__/integration/templates/integration.yaml delete mode 100644 src/__tests__/integration/test-data/sci-e.ts delete mode 100644 src/__tests__/unit/builtins/CommonGenerator.test.ts delete mode 100644 src/__tests__/unit/builtins/RandIntGenerator.test.ts delete mode 100644 src/__tests__/unit/builtins/coefficient.test.ts delete mode 100644 src/__tests__/unit/builtins/copy-param.test.ts delete mode 100644 src/__tests__/unit/builtins/csv-lookup.test.ts delete mode 100644 src/__tests__/unit/builtins/divide.test.ts delete mode 100644 src/__tests__/unit/builtins/exponent.test.ts delete mode 100644 src/__tests__/unit/builtins/export-csv-raw.test.ts delete mode 100644 src/__tests__/unit/builtins/export-csv.test.ts delete mode 100644 src/__tests__/unit/builtins/export-log.test.ts delete mode 100644 src/__tests__/unit/builtins/export-yaml.test.ts delete mode 100644 src/__tests__/unit/builtins/group-by.test.ts delete mode 100644 src/__tests__/unit/builtins/interpolation.test.ts delete mode 100644 src/__tests__/unit/builtins/mock-observations.test.ts delete mode 100644 src/__tests__/unit/builtins/multiply.test.ts delete mode 100644 src/__tests__/unit/builtins/regex.test.ts delete mode 100644 src/__tests__/unit/builtins/sci-embodied.test.ts delete mode 100644 src/__tests__/unit/builtins/sci.test.ts delete mode 100644 src/__tests__/unit/builtins/shell.test.ts delete mode 100644 src/__tests__/unit/builtins/subtract.test.ts delete mode 100644 src/__tests__/unit/builtins/sum.test.ts delete mode 100644 src/__tests__/unit/builtins/time-sync.test.ts delete mode 100644 src/__tests__/unit/lib/aggregate.test.ts delete mode 100644 src/__tests__/unit/lib/compare.test.ts delete mode 100644 src/__tests__/unit/lib/compute.test.ts delete mode 100644 src/__tests__/unit/lib/environment.test.ts delete mode 100644 src/__tests__/unit/lib/exhaust.test.ts delete mode 100644 src/__tests__/unit/lib/initialize.test.ts delete mode 100644 src/__tests__/unit/lib/load.test.ts delete mode 100644 src/__tests__/unit/lib/parameterize.test.ts delete mode 100644 src/__tests__/unit/util/aggregation-helper.test.ts delete mode 100644 src/__tests__/unit/util/args.test.ts delete mode 100644 src/__tests__/unit/util/debug-logger.test.ts delete mode 100644 src/__tests__/unit/util/fs.test.ts delete mode 100644 src/__tests__/unit/util/helpers.test.ts delete mode 100644 src/__tests__/unit/util/json.test.ts delete mode 100644 src/__tests__/unit/util/log-memoize.test.ts delete mode 100644 src/__tests__/unit/util/logger.test.ts delete mode 100644 src/__tests__/unit/util/npm.test.ts delete mode 100644 src/__tests__/unit/util/os-checker.test.ts delete mode 100644 src/__tests__/unit/util/plugin-storage.test.ts delete mode 100644 src/__tests__/unit/util/yaml.test.ts diff --git a/src/__tests__/integration/helpers/common.ts b/src/__tests__/integration/helpers/common.ts deleted file mode 100644 index 47b013e88..000000000 --- a/src/__tests__/integration/helpers/common.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {exec} from 'node:child_process'; -import {promisify} from 'node:util'; - -export const execPromise = promisify(exec); - -const stripAnsi = (text: string) => { - const pattern = [ - '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', - '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))', - ].join('|'); - - const ansiRegex = new RegExp(pattern, 'g'); - - return text.replaceAll(ansiRegex, ''); -}; - -export const getJSONFromText = (text: string) => { - const textWithoutAnsi = stripAnsi(text); - const jsonRegex = /\{[^]*\}/; - const jsonMatch = textWithoutAnsi.match(jsonRegex); - - if (jsonMatch) { - const jsonString = jsonMatch[0]; - - return JSON.parse(jsonString); - } else { - throw new Error('No JSON found in the log.'); - } -}; diff --git a/src/__tests__/integration/helpers/module-installer.ts b/src/__tests__/integration/helpers/module-installer.ts deleted file mode 100644 index a70ede21a..000000000 --- a/src/__tests__/integration/helpers/module-installer.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {execPromise} from './common'; - -const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'; - -export const npmInstallPackage = (module: string) => { - return execPromise(`${npmCommand} install ${module} --s`); -}; - -export const npmUninstallPackage = (module: string) => { - return execPromise(`${npmCommand} uninstall ${module}`); -}; diff --git a/src/__tests__/integration/scenarios/sci-e.ts b/src/__tests__/integration/scenarios/sci-e.ts deleted file mode 100644 index 0342240c2..000000000 --- a/src/__tests__/integration/scenarios/sci-e.ts +++ /dev/null @@ -1,75 +0,0 @@ -import * as YAML from 'js-yaml'; - -import {openYamlFileAsObject, saveYamlFileAs} from '../../../util/yaml'; -import {Manifest} from '../../../types/manifest'; -import { - npmInstallPackage, - npmUninstallPackage, -} from '../helpers/module-installer'; -import {execPromise} from '../helpers/common'; -import {sciEInputData} from '../test-data/sci-e'; - -describe('integration/sci-e', () => { - const modelName = 'sci-e'; - const absoluteManifestPath = `${__dirname}/../manifest/sci-e.yaml`; - const relativeManifestPath = 'src/__tests__/integration/manifest/sci-e.yaml'; - const implTemplatePath = `${__dirname}/../templates/integration.yaml`; - - beforeAll(() => { - return npmInstallPackage('@grnsft/if-plugins'); - }, 15000); - - it('output creation without ompl path.', async () => { - const file = await openYamlFileAsObject(implTemplatePath); - - file.initialize.plugins[modelName] = { - method: 'SciE', - path: '@grnsft/if-plugins', - }; - file.initialize.outputs = []; - - file.tree.children.child.pipeline = [modelName]; - file.tree.children.child.config = {}; - file.tree.children.child.config[modelName] = {}; - file.tree.children.child.inputs = sciEInputData['success-3-params']; - - await saveYamlFileAs(file, absoluteManifestPath); // save yaml uses absolute path - const response = ( - await execPromise( - `npm run if-run -- --manifest ${relativeManifestPath} --stdout` - ) - ).stdout; // exec promise uses relative path - - const yamlPart = response.substring( - response.indexOf('name:'), - response.length - ); - const finalOutputParsed: any = YAML.load(yamlPart); - - // assertions - const path = finalOutputParsed.tree.children.child.outputs[0]; - const manifestPath = file.tree.children.child.inputs[0]; - - // assert timestamp - expect(finalOutputParsed.tree.children.child.inputs[0].timestamp).toEqual( - file.tree.children.child.inputs[0].timestamp - ); - - // assert duration - expect(finalOutputParsed.tree.children.child.inputs[0].duration).toEqual( - file.tree.children.child.inputs[0].duration - ); - - // assert total energy - const sum = - manifestPath['cpu/energy'] + - manifestPath['memory/energy'] + - manifestPath['network/energy']; - - expect(path.energy).toEqual(sum); - }, 15000); - - afterAll(() => { - return npmUninstallPackage('@grnsft/if-plugins'); - }, 15000); -}); diff --git a/src/__tests__/integration/templates/integration.yaml b/src/__tests__/integration/templates/integration.yaml deleted file mode 100644 index 2d1523e91..000000000 --- a/src/__tests__/integration/templates/integration.yaml +++ /dev/null @@ -1,16 +0,0 @@ -name: integration-template -description: -tags: -initialize: - plugins: - 'sci-e': - model: ${model} - path: ${path} -tree: - children: - child: - pipeline: - - ${name} - config: - inputs: - - ${input} diff --git a/src/__tests__/integration/test-data/sci-e.ts b/src/__tests__/integration/test-data/sci-e.ts deleted file mode 100644 index e6a5acde7..000000000 --- a/src/__tests__/integration/test-data/sci-e.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const sciEInputData = { - 'success-3-params': [ - { - timestamp: '2023-08-06T00:00', - duration: 3600, - 'cpu/energy': 10, - 'memory/energy': 100, - 'network/energy': 100, - }, - ], -}; diff --git a/src/__tests__/unit/builtins/CommonGenerator.test.ts b/src/__tests__/unit/builtins/CommonGenerator.test.ts deleted file mode 100644 index b0c165d1a..000000000 --- a/src/__tests__/unit/builtins/CommonGenerator.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {CommonGenerator} from '../../../builtins/mock-observations/helpers/common-generator'; - -import {STRINGS} from '../../../config'; - -const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -describe('builtins/mock-observations/CommonGenerator: ', () => { - describe('initialize: ', () => { - it('throws an error when config is not empty object.', async () => { - const commonGenerator = CommonGenerator({}); - - expect.assertions(1); - - try { - commonGenerator.next([]); - } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); - } - }); - }); - - describe('next(): ', () => { - it('returns a result with valid data.', async () => { - const config: Record = { - key1: 'value1', - key2: 'value2', - }; - const commonGenerator = CommonGenerator(config); - - expect.assertions(1); - - expect(commonGenerator.next([])).toEqual({ - key1: 'value1', - key2: 'value2', - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/RandIntGenerator.test.ts b/src/__tests__/unit/builtins/RandIntGenerator.test.ts deleted file mode 100644 index 328f7d6f4..000000000 --- a/src/__tests__/unit/builtins/RandIntGenerator.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {RandIntGenerator} from '../../../builtins/mock-observations/helpers/rand-int-generator'; - -import {STRINGS} from '../../../config'; - -const {GlobalConfigError} = ERRORS; -const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; - -describe('builtins/mock-observations/RandIntGenerator: ', () => { - describe('initialize', () => { - it('throws an error when the generator name is empty string.', async () => { - expect.assertions(1); - try { - RandIntGenerator('', {}); - } catch (error) { - expect(error).toEqual(new GlobalConfigError(INVALID_NAME)); - } - }); - - it('throws an error when config is empty object.', async () => { - expect.assertions(1); - try { - RandIntGenerator('generator-name', {}); - } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); - } - }); - - it('throws an error `min` is missing from the config.', async () => { - const config = {max: 90}; - - expect.assertions(1); - - try { - RandIntGenerator('random', config); - } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_MIN_MAX)); - } - }); - }); - - describe('next(): ', () => { - it('returns a result with valid data.', async () => { - const config: Record = { - min: 10, - max: 90, - }; - const randIntGenerator = RandIntGenerator('random', config); - const result = randIntGenerator.next([]) as {random: number}; - - expect.assertions(4); - - expect(result).toBeInstanceOf(Object); - expect(result).toHaveProperty('random'); - expect(result.random).toBeGreaterThanOrEqual(10); - expect(result.random).toBeLessThanOrEqual(90); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/coefficient.test.ts b/src/__tests__/unit/builtins/coefficient.test.ts deleted file mode 100644 index 034d20f95..000000000 --- a/src/__tests__/unit/builtins/coefficient.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Coefficient} from '../../../builtins/coefficient'; - -import {STRINGS} from '../../../config'; - -const {InputValidationError, GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -describe('builtins/coefficient: ', () => { - describe('Coefficient: ', () => { - const globalConfig = { - 'input-parameter': 'carbon', - coefficient: 3, - 'output-parameter': 'carbon-product', - }; - const coefficient = Coefficient(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(coefficient).toHaveProperty('metadata'); - expect(coefficient).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies coefficient strategy to given input.', () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - carbon: 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 coefficient = Coefficient(config!); - - expect.assertions(1); - - try { - coefficient.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); - } - }); - - it('throws an error on missing `input-parameter` param in input.', () => { - const invalidConfig = { - 'input-parameter': '', - coefficient: 3, - 'output-parameter': 'carbon-product', - }; - const coefficient = Coefficient(invalidConfig); - const expectedMessage = - '"input-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; - - expect.assertions(1); - - try { - coefficient.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError(expectedMessage) - ); - } - }); - - it('throws an error on missing `output-parameter` param in input.', () => { - const invalidConfig = { - 'input-parameter': 'carbon', - coefficient: 10, - 'output-parameter': '', - }; - const coefficient = Coefficient(invalidConfig); - const expectedMessage = - '"output-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; - - expect.assertions(1); - try { - coefficient.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError(expectedMessage) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts deleted file mode 100644 index 64809e44a..000000000 --- a/src/__tests__/unit/builtins/copy-param.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Copy} from '../../../builtins/copy-param'; - -import {STRINGS} from '../../../config'; - -const {GlobalConfigError, InputValidationError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -describe('builtins/copy: ', () => { - describe('Copy: ', () => { - const globalConfig = { - 'keep-existing': true, - from: 'original', - to: 'copy', - }; - const copy = Copy(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(copy).toHaveProperty('metadata'); - expect(copy).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Copy strategy to given input.', () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - original: '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 copy = Copy(config!); - - expect.assertions(1); - - try { - copy.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - original: 1, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); - } - }); - - it('throws an error on missing params in input.', () => { - const globalConfig = { - 'keep-existing': true, - from: 'original', - to: 'copy', - }; - const copy = Copy(globalConfig); - expect.assertions(1); - - try { - copy.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"original" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - it('does not persist the original value when keep-existing==false.', () => { - expect.assertions(1); - const globalConfig = { - 'keep-existing': false, - from: 'original', - to: 'copy', - }; - const copy = Copy(globalConfig); - - const expectedResult = [ - { - duration: 3600, - 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); - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts deleted file mode 100644 index 81e0498b4..000000000 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ /dev/null @@ -1,514 +0,0 @@ -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -import axios from 'axios'; -import AxiosMockAdapter from 'axios-mock-adapter'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {CSVLookup} from '../../../builtins'; - -import {STRINGS} from '../../../config'; - -const { - GlobalConfigError, - ReadFileError, - FetchingFileError, - QueryDataNotFoundError, - MissingCSVColumnError, - CSVParseError, -} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; - -describe('builtins/CSVLookup: ', () => { - const mock = new AxiosMockAdapter(axios); - - describe('CSVLookup: ', () => { - afterEach(() => { - mock.reset(); - }); - - describe('init: ', () => { - it('successfully initalized.', () => { - const globalConfig = { - filepath: '', - query: { - 'cpu-cores-available': 'cpu/available', - }, - output: ['cpu-tdp', 'tdp'], - }; - const csvLookup = CSVLookup(globalConfig); - expect(csvLookup).toHaveProperty('metadata'); - expect(csvLookup).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies CSVLookup `url` strategy to given input.', async () => { - expect.assertions(1); - const globalConfig = { - filepath: - 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - const csvLookup = CSVLookup(globalConfig); - - 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 -16,16,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.4xlarge,EBS-Only,32,32,November 2018,0`; - mock.onGet(globalConfig.filepath).reply(200, responseData); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - tdp: 150, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('successfully applies CSVLookup `local file` strategy to given input.', 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 csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - tdp: 150, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('rejects with file not found error.', async () => { - const globalConfig = { - filepath: './file-fail.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - const csvLookup = CSVLookup(globalConfig); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(ReadFileError); - } - } - }); - - it('rejects with file not found error.', async () => { - const globalConfig = { - filepath: './file-fail.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - const csvLookup = CSVLookup(globalConfig); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(ReadFileError); - } - } - }); - - it('rejects with axios error.', async () => { - const globalConfig = { - filepath: - 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - mock.onGet(globalConfig.filepath).reply(404); - - const csvLookup = CSVLookup(globalConfig); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(FetchingFileError); - } - } - }); - - it('successfully applies CSVLookup if output is `*`.', 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: '*', - }; - const csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - 'gpu-count': 'N/A', - 'gpu-model-name': 'N/A', - 'instance-class': 'a1.4xlarge', - 'instance-storage': 'EBS-Only', - 'memory-available': 32, - 'platform-memory': 32, - 'release-date': 'November 2018', - 'storage-drives': 'nan', - 'Hardware Information on AWS Documentation & Comments': - 'AWS Graviton (ARM)', - 'cpu-model-name': 'AWS Graviton', - 'cpu-tdp': 150, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('successfully applies CSVLookup if output is matrix.', 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: [ - ['gpu-count', 'gpuc'], - ['gpu-model-name', 'gpumodel'], - ], - }; - const csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - gpuc: 'N/A', - gpumodel: 'N/A', - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('successfully applies CSVLookup if output is exact string.', 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: 'gpu-count', - }; - const csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - 'gpu-count': 'N/A', - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('rejects with query data not found.', async () => { - expect.assertions(2); - const globalConfig = { - filepath: './file.csv', - query: { - 'fail-cpu-cores-available': 'cpu/available', - 'fail-cpu-cores-utilized': 'cpu/utilized', - 'fail-cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - - const csvLookup = CSVLookup(globalConfig); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(QueryDataNotFoundError); - expect(error.message).toEqual(NO_QUERY_DATA); - } - } - }); - - it('rejects with config not found error.', async () => { - expect.assertions(2); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const csvLookup = CSVLookup(); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error.message).toEqual(MISSING_GLOBAL_CONFIG); - } - } - }); - - it('rejects with no such column in csv error.', async () => { - expect.assertions(2); - - const globalConfig = { - filepath: './file.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: 'mock', - }; - const csvLookup = CSVLookup(globalConfig); - const input = [ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]; - - try { - await csvLookup.execute(input); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(MissingCSVColumnError); - expect(error.message).toEqual( - MISSING_CSV_COLUMN(globalConfig.output) - ); - } - } - }); - - it('successfully applies CSVLookup if output is array with string.', 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: ['gpu-count'], - }; - const csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - 'gpu-count': 'N/A', - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - it('successfully applies CSVLookup if output is matrix with strings.', 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: [['gpu-count']], - }; - const csvLookup = CSVLookup(globalConfig); - - 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/utilized': 16, - 'cpu/manufacturer': 'AWS', - 'gpu-count': 'N/A', - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - }); - - it('rejects with CSV parse error', async () => { - process.env.csv = 'fail'; - expect.assertions(1); - const globalConfig = { - filepath: './fail-csv-reader.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/utilized', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: [['gpu-count']], - }; - const csvLookup = CSVLookup(globalConfig); - - try { - await csvLookup.execute([ - { - timestamp: '2024-03-01', - 'cpu/available': 16, - 'cpu/utilized': 16, - 'cpu/manufacturer': 'AWS', - }, - ]); - } catch (error) { - expect(error).toBeInstanceOf(CSVParseError); - } - }); - }); -}); diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts deleted file mode 100644 index ba75e3879..000000000 --- a/src/__tests__/unit/builtins/divide.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Divide} from '../../../builtins'; - -import {STRINGS} from '../../../config'; - -const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; - -describe('builtins/divide: ', () => { - describe('Divide: ', () => { - const globalConfig = { - numerator: 'vcpus-allocated', - denominator: 2, - output: 'cpu/number-cores', - }; - const divide = Divide(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(divide).toHaveProperty('metadata'); - expect(divide).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Divide strategy to given input.', async () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - 'vcpus-allocated': 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 = { - numerator: 'vcpus-allocated', - denominator: 'duration', - output: 'vcpus-allocated-per-second', - }; - const divide = Divide(globalConfig); - - const input = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, - ]; - const response = await divide.execute(input); - - const expectedResult = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - 'vcpus-allocated-per-second': 24 / 3600, - }, - ]; - - expect(response).toEqual(expectedResult); - }); - - it('throws an error on missing params in input.', async () => { - const expectedMessage = - '"vcpus-allocated" parameter is required. Error code: invalid_type.'; - - const globalConfig = { - numerator: 'vcpus-allocated', - denominator: 3600, - output: 'vcpus-allocated-per-second', - }; - const divide = Divide(globalConfig); - - expect.assertions(1); - - try { - await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError(expectedMessage) - ); - } - }); - }); - - it('throws an error on missing global config.', async () => { - const config = undefined; - const divide = Divide(config!); - - expect.assertions(1); - - try { - await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); - } - }); - - it('throws an error when `denominator` is 0.', async () => { - const globalConfig = { - numerator: 'vcpus-allocated', - denominator: 0, - output: 'vcpus-allocated-per-second', - }; - const divide = Divide(globalConfig); - - expect.assertions(1); - - const response = await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, - ]); - - expect(response).toEqual([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - 'vcpus-allocated-per-second': 24, - }, - ]); - }); - - it('throws an error when `denominator` is string.', async () => { - const globalConfig = { - numerator: 'vcpus-allocated', - denominator: '10', - output: 'vcpus-allocated-per-second', - }; - const divide = Divide(globalConfig); - - expect.assertions(1); - - try { - await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new MissingInputDataError( - MISSING_INPUT_DATA(globalConfig.denominator) - ) - ); - } - }); - }); -}); diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts deleted file mode 100644 index ad438179d..000000000 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Exponent} from '../../../builtins/exponent'; - -const {InputValidationError} = ERRORS; - -describe('builtins/exponent: ', () => { - describe('Exponent: ', () => { - const globalConfig = { - 'input-parameter': 'energy/base', - exponent: 3, - 'output-parameter': 'energy', - }; - const exponent = Exponent(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(exponent).toHaveProperty('metadata'); - expect(exponent).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Exponent strategy to given input.', async () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - 'energy/base': 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); - - try { - await exponent.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"input-parameter" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throws an error on input param value not numeric.', async () => { - expect.assertions(1); - const input = [ - { - duration: 3600, - 'energy/base': 'i-am-not-a-number', - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - try { - await exponent.execute(input); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"input-parameter" parameter is expected number, received string. Error code: invalid_type.' - ) - ); - } - }); - - it('returns a result with input params not related to energy.', async () => { - expect.assertions(1); - const newConfig = { - 'input-parameter': 'carbon/base', - exponent: 4, - 'output-parameter': 'carbon', - }; - const exponent = Exponent(newConfig); - - const data = [ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - 'carbon/base': 2, - }, - ]; - const response = await exponent.execute(data); - - const expectedResult = [ - { - duration: 3600, - 'carbon/base': 2, - carbon: 16, - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - expect(response).toEqual(expectedResult); - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts deleted file mode 100644 index e97242a4d..000000000 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as fs from 'fs/promises'; - -import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; - -import {STRINGS} from '../../../config'; - -import {tree, context, outputs} from '../../../__mocks__/builtins/export-csv'; - -const {ExhaustOutputArgError} = ERRORS; -const {WRITE_CSV_ERROR, OUTPUT_REQUIRED} = STRINGS; - -jest.mock('fs/promises', () => ({ - __esModule: true, - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('builtins/export-csv-raw: ', () => { - describe('ExportCSVRaw: ', () => { - const exportCSVRaw = ExportCSVRaw(); - - beforeEach(() => { - jest.resetAllMocks(); - }); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(exportCSVRaw).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output#carbon'; - const content = - "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,8000.000004051243,"; - - await exportCSVRaw.execute(tree, context, outputPath); - - expect(fs.writeFile).toHaveBeenCalledWith(`${outputPath}.csv`, content); - }); - - it('throws an error when the CSV file could not be created.', async () => { - const outputPath = 'output#carbon'; - const expectedMessage = 'Could not write CSV file.'; - - expect.assertions(1); - - jest.spyOn(fs, 'writeFile').mockRejectedValue(expectedMessage); - - await expect( - exportCSVRaw.execute(tree, context, outputPath) - ).rejects.toThrow( - new ExhaustOutputArgError( - WRITE_CSV_ERROR(outputPath, expectedMessage) - ) - ); - }); - - it('throws an error when output path is empty.', async () => { - const outputPath = ''; - - context.initialize = Object.assign({}, context.initialize, outputs); - - expect.assertions(2); - try { - await exportCSVRaw.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts deleted file mode 100644 index 78feaf534..000000000 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ /dev/null @@ -1,236 +0,0 @@ -import * as fs from 'fs/promises'; - -import {stringify} from 'csv-stringify/sync'; -import {jest} from '@jest/globals'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {ExportCSV} from '../../../builtins/export-csv'; - -import {STRINGS} from '../../../config'; - -import { - tree, - context, - outputs, - aggregated, - aggregation, -} from '../../../__mocks__/builtins/export-csv'; - -const {ExhaustOutputArgError} = ERRORS; -const {OUTPUT_REQUIRED, CSV_EXPORT} = STRINGS; - -jest.mock('fs/promises', () => ({ - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('builtins/export-csv: ', () => { - describe('ExportCSV: ', () => { - const exportCSV = ExportCSV(); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(exportCSV).toMatchObject({metadata: {kind: 'exhaust'}}); - expect(exportCSV).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - const reformedContext = Object.assign({}, context, {outputs}); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, reformedContext, outputPath); - - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when the `outputs` type is missing.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, context, outputPath); - - expect.assertions(1); - - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when `aggregation` persists.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, - }, - }, - }); - - await exportCSV.execute(reformedTree, reformedContext, outputPath); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('generates CSV file when `aggregation` is missing.', async () => { - const outputPath = 'output#carbon'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - [ - 'tree.children.child-1.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - [ - 'tree.children.child-2.carbon', - 4000.0000020256216, - 4000.0000020256216, - ], - ]; - - const reformedContext = Object.assign({}, context, {outputs}); - - await exportCSV.execute(tree, reformedContext, outputPath); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); - - it('throws an error when output path is empty.', async () => { - const outputPath = ''; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); - } - }); - - it('throws an error when output path does not contains `#`.', async () => { - const outputPath = 'output.csv'; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); - } - }); - - it('throws an error when output path does not contains a criteria.', async () => { - const outputPath = 'output.csv#'; - - context.initialize = Object.assign({}, context.initialize, outputs); - - try { - await exportCSV.execute(tree, context, outputPath); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/export-log.test.ts b/src/__tests__/unit/builtins/export-log.test.ts deleted file mode 100644 index f6990ab1e..000000000 --- a/src/__tests__/unit/builtins/export-log.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as YAML from 'js-yaml'; - -import {ExportLog} from '../../../builtins/export-log'; -import {tree, context} from '../../../__mocks__/builtins/export-csv'; - -describe('builtins/export-log:', () => { - describe('ExportLog: ', () => { - it('successfully logs output manifest in console.', async () => { - const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(); - await ExportLog().execute(tree, context); - - const expectedMessage = `# start -${YAML.dump({...context, tree}, {noRefs: true})} -# end`; - - expect(mockConsoleLog).toHaveBeenCalled(); - expect(mockConsoleLog).toHaveBeenCalledWith(expectedMessage); - - mockConsoleLog.mockRestore(); - }); - - it('successfully logs output manifest if tree is an empty object.', async () => { - const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(); - await ExportLog().execute({}, context); - - const expectedMessage = `# start -${YAML.dump({...context, tree: {}}, {noRefs: true})} -# end`; - - expect(mockConsoleLog).toHaveBeenCalled(); - expect(mockConsoleLog).toHaveBeenCalledWith(expectedMessage); - - mockConsoleLog.mockRestore(); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts deleted file mode 100644 index fb7954c1e..000000000 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {ExportYaml} from '../../../builtins/export-yaml'; -import {saveYamlFileAs} from '../../../util/yaml'; - -import {STRINGS} from '../../../config'; - -import {tree, context} from '../../../__mocks__/builtins/export-csv'; - -jest.mock('../../../util/yaml', () => ({ - saveYamlFileAs: jest.fn(), -})); - -const {ExhaustOutputArgError} = ERRORS; -const {OUTPUT_REQUIRED} = STRINGS; - -describe('builtins/export-yaml: ', () => { - describe('ExportYaml: ', () => { - const exportYaml = ExportYaml(); - - describe('init ExportYaml: ', () => { - it('initalizes object with properties.', async () => { - expect(exportYaml).toHaveProperty('execute'); - }); - }); - - describe('execute', () => { - it('returns result with correct arguments', async () => { - const outputPath = 'outputPath.yaml'; - - await exportYaml.execute(tree, context, outputPath); - - expect(saveYamlFileAs).toHaveBeenCalledWith( - {...context, tree}, - `${outputPath.split('#')[0]}.yaml` - ); - }); - - it('throws an error if outputPath is not provided.', async () => { - expect.assertions(2); - - try { - await exportYaml.execute({}, context, ''); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/group-by.test.ts b/src/__tests__/unit/builtins/group-by.test.ts deleted file mode 100644 index 3d676148b..000000000 --- a/src/__tests__/unit/builtins/group-by.test.ts +++ /dev/null @@ -1,177 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {GroupBy} from '../../../builtins/group-by'; - -import {STRINGS} from '../../../config'; - -const {InvalidGroupingError, InputValidationError, GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, INVALID_GROUP_BY} = STRINGS; - -describe('builtins/group-by: ', () => { - describe('GroupBy: ', () => { - const plugin = GroupBy(); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(plugin).toHaveProperty('metadata'); - expect(plugin).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('groups inputs correctly.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - const config = { - group: ['region', 'cloud/instance-type'], - }; - - const expectedOutput = { - 'uk-west': { - children: { - A1: { - inputs: [ - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T00:00', - }, - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T05:00', - }, - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T10:00', - }, - ], - }, - }, - }, - }; - - const result = plugin.execute(inputs, config); - expect(result).toEqual(expectedOutput); - }); - - it('throws an error when config is not provided.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - - const config = undefined; - - expect.assertions(2); - try { - plugin.execute(inputs, config!); - } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); - } - }); - - it('throws an error if `group` is an empty array.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - const config = { - group: ['region', 'cloud/instance-type'], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InvalidGroupingError); - expect(error).toEqual( - new InvalidGroupingError('Invalid group region.') - ); - } - }); - - it('throws an error if group type is missing from the input.', () => { - const inputs = [ - {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, - ]; - const config = { - group: [], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"group" parameter is array must contain at least 1 element(s). Error code: too_small.' - ) - ); - } - }); - - it('throws an error if input does not have required group type.', () => { - const inputs = [ - {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, - ]; - const config = { - group: ['region', 'cloud/instance-type', 'unknown'], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InvalidGroupingError); - expect(error).toEqual( - new InvalidGroupingError(INVALID_GROUP_BY(config.group[2])) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/interpolation.test.ts b/src/__tests__/unit/builtins/interpolation.test.ts deleted file mode 100644 index 6219e01ec..000000000 --- a/src/__tests__/unit/builtins/interpolation.test.ts +++ /dev/null @@ -1,221 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {Method} from '@grnsft/if-core/types'; - -import {Interpolation} from '../../../builtins'; - -import {STRINGS} from '../../../config'; - -const {InputValidationError, GlobalConfigError} = ERRORS; -const { - MISSING_GLOBAL_CONFIG, - WITHIN_THE_RANGE, - ARRAY_LENGTH_NON_EMPTY, - X_Y_EQUAL, -} = STRINGS; - -describe('builtins/interpolation: ', () => { - describe('Interpolation: ', () => { - 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/utilization': 45, - }, - ]; - const plugin = Interpolation(globalConfig); - - describe('init Interpolation: ', () => { - it('initalizes object with properties.', async () => { - expect(plugin).toHaveProperty('metadata'); - expect(plugin).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('returns result when all parameters are valid.', () => { - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 45, - 'interpolation-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], - y: [0.12, 0.32, 0.75, 1.02], - 'input-parameter': 'cpu/utilization', - 'output-parameter': 'interpolation-result', - }; - const plugin = Interpolation(globalConfig); - - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 45, - 'interpolation-result': 0.69625, - }, - ]; - - expect(plugin.execute(inputs)).toEqual(outputs); - }); - - it('returns result when the `method` is `spline`.', () => { - const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config); - - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 45, - 'interpolation-result': 0.7169698932926829, - }, - ]; - - expect(plugin.execute(inputs)).toEqual(outputs); - }); - - it('returns result when the `method` is `polynomial`.', () => { - const config = Object.assign({}, globalConfig, { - method: Method.POLYNOMIAL, - }); - const plugin = Interpolation(config); - - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 45, - 'interpolation-result': 0.7187374999999999, - }, - ]; - - expect(plugin.execute(inputs)).toEqual(outputs); - }); - - it('returns result when the elements of `x` is not in acsending order.', () => { - const config = Object.assign({}, globalConfig, { - x: [0, 10, 100, 50], - }); - const plugin = Interpolation(config); - - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 45, - 'interpolation-result': 0.69625, - }, - ]; - - expect(plugin.execute(inputs)).toEqual(outputs); - }); - - it('returns result when the `cpu/utilization` is equal to one of the `x` points element.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 50, - }, - ]; - const outputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 50, - 'interpolation-result': 0.75, - }, - ]; - - expect(plugin.execute(inputs)).toEqual(outputs); - }); - - it('throws an when the global config is not provided.', () => { - const config = undefined; - const plugin = Interpolation(config!); - - expect.assertions(2); - try { - plugin.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); - } - }); - - it('throws an error when `x` and `y` points not equal.', () => { - const config = Object.assign({}, globalConfig, { - x: [0, 10, 100], - }); - - const plugin = Interpolation(config); - - expect.assertions(2); - try { - plugin.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual(new InputValidationError(X_Y_EQUAL)); - } - }); - - it('throws an error when `cpu/utilization` is out of the range of `x` elements.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 105, - }, - ]; - expect.assertions(2); - try { - plugin.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual(new InputValidationError(WITHIN_THE_RANGE)); - } - }); - it('throws an error when the the length of the input arrays is <2', () => { - const globalConfig = { - x: [0], - y: [0.12], - 'input-parameter': 'cpu/utilization', - 'output-parameter': 'interpolation-result', - }; - const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config); - const inputs = [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 105, - }, - ]; - expect.assertions(2); - try { - plugin.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError(ARRAY_LENGTH_NON_EMPTY) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/mock-observations.test.ts b/src/__tests__/unit/builtins/mock-observations.test.ts deleted file mode 100644 index fd28d5595..000000000 --- a/src/__tests__/unit/builtins/mock-observations.test.ts +++ /dev/null @@ -1,326 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {MockObservations} from '../../../builtins/mock-observations'; - -import {STRINGS} from '../../../config'; - -const {InputValidationError, GlobalConfigError} = ERRORS; -const {INVALID_MIN_MAX} = STRINGS; - -describe('builtins/mock-observations: ', () => { - describe('init: ', () => { - it('successfully initalized.', () => { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }); - - expect(mockObservations).toHaveProperty('metadata'); - expect(mockObservations).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('executes successfully.', 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 mockObservations = MockObservations(config); - 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/utilization': 10, - }, - { - timestamp: '2023-07-06T00:00:30.000Z', - duration: 30, - 'common-key': 'common-val', - 'instance-type': 'A1', - region: 'uk-west', - 'cpu/utilization': 10, - }, - { - timestamp: '2023-07-06T00:00:00.000Z', - duration: 30, - 'common-key': 'common-val', - 'instance-type': 'B1', - region: 'uk-west', - 'cpu/utilization': 10, - }, - { - timestamp: '2023-07-06T00:00:30.000Z', - duration: 30, - 'common-key': 'common-val', - 'instance-type': 'B1', - region: 'uk-west', - 'cpu/utilization': 10, - }, - ]); - }); - - it('throws an error when the `min` is greater then `max` of `randint` config.', 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: 20, max: 11}, - }, - }, - }; - - expect.assertions(2); - - const mockObservations = MockObservations(config); - try { - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual( - new GlobalConfigError(INVALID_MIN_MAX('cpu/utilization')) - ); - } - }); - - it('throws when `generators` are not provided.', async () => { - const config = { - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - }; - - expect.assertions(2); - - try { - const mockObservations = MockObservations(config); - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"generators" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throws when `components` are not provided.', async () => { - const errorMessage = - '"components" parameter is required. Error code: invalid_type.'; - const config = { - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }; - - expect.assertions(2); - - try { - const mockObservations = MockObservations(config); - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual(new InputValidationError(errorMessage)); - } - }); - - it('throws when `duration` is not provided.', async () => { - expect.assertions(2); - - try { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }); - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"duration" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throws when `timestamp-to` is not provided.', async () => { - expect.assertions(2); - - try { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }); - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"timestamp-to" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throws when `timestamp-from` is missing.', async () => { - expect.assertions(2); - - try { - const mockObservations = MockObservations({ - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }); - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"timestamp-from" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throws an error when `randInt` is not valid.', 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: null, - }, - }; - const mockObservations = MockObservations(config); - - expect.assertions(2); - - try { - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"generators.randint" parameter is expected object, received null. Error code: invalid_type.' - ) - ); - } - }); - - it('throws an error when `common` is not valid.', 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: null, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, - }, - }, - }; - const mockObservations = MockObservations(config); - - expect.assertions(2); - - try { - await mockObservations.execute([]); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"generators.common" parameter is expected object, received null. Error code: invalid_type.' - ) - ); - } - }); - }); -}); diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts deleted file mode 100644 index d15a7e8f9..000000000 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Multiply} from '../../../builtins/multiply'; - -const {InputValidationError} = ERRORS; - -describe('builtins/multiply: ', () => { - describe('Multiply: ', () => { - const globalConfig = { - 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], - 'output-parameter': 'energy', - }; - const multiply = Multiply(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(multiply).toHaveProperty('metadata'); - expect(multiply).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Multiply strategy to given input.', async () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - 'cpu/energy': 2, - 'network/energy': 2, - 'memory/energy': 2, - energy: 8, - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - const result = await multiply.execute([ - { - duration: 3600, - 'cpu/energy': 2, - 'network/energy': 2, - 'memory/energy': 2, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - - expect(result).toStrictEqual(expectedResult); - }); - - it('throws an error on missing params in input.', async () => { - expect.assertions(1); - - try { - await multiply.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('returns a result with input params not related to energy.', async () => { - expect.assertions(1); - const newConfig = { - 'input-parameters': ['carbon', 'other-carbon'], - 'output-parameter': 'carbon-product', - }; - const multiply = Multiply(newConfig); - - const data = [ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - 'other-carbon': 2, - }, - ]; - const response = await multiply.execute(data); - - const expectedResult = [ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - 'other-carbon': 2, - 'carbon-product': 6, - }, - ]; - - expect(response).toEqual(expectedResult); - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/regex.test.ts b/src/__tests__/unit/builtins/regex.test.ts deleted file mode 100644 index 54a70ed9e..000000000 --- a/src/__tests__/unit/builtins/regex.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Regex} from '../../../builtins/regex'; - -import {STRINGS} from '../../../config'; - -const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; - -describe('builtins/regex: ', () => { - describe('Regex: ', () => { - const globalConfig = { - parameter: 'physical-processor', - match: '^[^,]+', - output: 'cpu/name', - }; - const regex = Regex(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(regex).toHaveProperty('metadata'); - expect(regex).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Regex strategy to given input.', 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'; - expect.assertions(1); - - const expectedResult = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': physicalProcessor, - 'cpu/name': 'Intel® Xeon® Platinum 8272CL', - }, - ]; - - const result = await regex.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': physicalProcessor, - }, - ]); - - 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'; - expect.assertions(1); - - const globalConfig = { - parameter: 'physical-processor', - match: '[^,]+/', - output: 'cpu/name', - }; - const regex = Regex(globalConfig); - - const expectedResult = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': physicalProcessor, - 'cpu/name': 'Intel® Xeon® Platinum 8272CL', - }, - ]; - - const result = await regex.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': physicalProcessor, - }, - ]); - - expect(result).toStrictEqual(expectedResult); - }); - - it('throws an error when `parameter` does not match to `match`.', 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'; - - const globalConfig = { - parameter: 'physical-processor', - match: '^(^:)+', - output: 'cpu/name', - }; - const regex = Regex(globalConfig); - - expect.assertions(1); - - try { - await regex.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'physical-processor': physicalProcessor, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new RegexMismatchError( - REGEX_MISMATCH(physicalProcessor, '/^(^:)+/') - ) - ); - } - }); - - it('throws an error on missing global config.', async () => { - const config = undefined; - const regex = Regex(config!); - - expect.assertions(1); - - try { - await regex.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); - } - }); - - it('throws an error on missing params in input.', async () => { - expect.assertions(1); - - try { - await regex.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new MissingInputDataError(MISSING_INPUT_DATA('physical-processor')) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/sci-embodied.test.ts b/src/__tests__/unit/builtins/sci-embodied.test.ts deleted file mode 100644 index a3f5bcbff..000000000 --- a/src/__tests__/unit/builtins/sci-embodied.test.ts +++ /dev/null @@ -1,306 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {SciEmbodied} from '../../../builtins/sci-embodied'; - -import {STRINGS} from '../../../config'; - -const {InputValidationError} = ERRORS; -const {SCI_EMBODIED_ERROR} = STRINGS; - -describe('builtins/sci-embodied:', () => { - describe('SciEmbodied: ', () => { - const sciEmbodied = SciEmbodied(); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(sciEmbodied).toHaveProperty('metadata'); - expect(sciEmbodied).toHaveProperty('execute'); - }); - }); - - describe('execute():', () => { - it('returns a result with valid inputs.', async () => { - 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/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'resources-reserved': 1, - 'resources-total': 1, - 'carbon-embodied': 4.10958904109589, - }, - { - 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, - 'carbon-embodied': 4.10958904109589 * 2, - }, - ]); - }); - - it('returns a result when `vcpus-allocated` and `vcpus-total` are in the input.', async () => { - 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, - 'vcpus-allocated': 1, - 'vcpus-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/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589, - }, - ]); - }); - - it('returns a result when `vcpus-allocated` and `vcpus-total` are preferred to `resources-reserved` and `resources-total`.', async () => { - 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': 2, - 'resources-total': 2, - 'vcpus-allocated': 1, - 'vcpus-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, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'resources-reserved': 2, - 'resources-total': 2, - }, - ]; - - const result = await sciEmbodied.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589, - 'resources-reserved': 2, - 'resources-total': 2, - }, - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30 * 2, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589 * 2, - 'resources-reserved': 2, - 'resources-total': 2, - }, - ]); - }); - - it('returns a result when `vcpus-allocated` and `vcpus-total` are miised.', async () => { - 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/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'carbon-embodied': 4.10958904109589, - '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, - 'carbon-embodied': 4.10958904109589 * 2, - 'resources-reserved': 1, - 'resources-total': 1, - }, - ]); - }); - - it('throws an error when `device/emissions-embodied` is string.', async () => { - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': '10,00', - '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, - }, - ]; - - expect.assertions(2); - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( - 'gco2e' - )}. Error code: invalid_union.` - ) - ); - expect(error).toBeInstanceOf(InputValidationError); - } - }); - - it('throws an exception on missing `device/emissions-embodied`.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is required. Error code: invalid_union.'; - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); - expect(error).toBeInstanceOf(InputValidationError); - } - }); - - it('throws an exception on missing `device/expected-lifespan`.', async () => { - const errorMessage = - '"device/expected-lifespan" parameter is required. Error code: invalid_union.'; - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); - expect(error).toBeInstanceOf(InputValidationError); - } - }); - - it('throws an exception on invalid values.', async () => { - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': '200', - 'vcpus-allocated': true, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( - 'gco2e' - )}. Error code: invalid_union.` - ) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts deleted file mode 100644 index 6a8ddc8db..000000000 --- a/src/__tests__/unit/builtins/sci.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Sci} from '../../../builtins/sci'; - -const {MissingInputDataError} = ERRORS; - -describe('builtins/sci:', () => { - describe('Sci: ', () => { - const sci = Sci({'functional-unit': 'users'}); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(sci).toHaveProperty('metadata'); - expect(sci).toHaveProperty('execute'); - }); - }); - - describe('execute():', () => { - it('returns a result with valid inputs.', async () => { - const sci = Sci({ - 'functional-unit': 'users', - }); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.02, - 'carbon-embodied': 5, - carbon: 5.02, - users: 100, - duration: 1, - }, - ]; - const result = await sci.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.02, - 'carbon-embodied': 5, - carbon: 5.02, - users: 100, - duration: 1, - sci: 0.050199999999999995, - }, - ]); - }); - - it('returns the same result regardless of input duration.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.2, - 'carbon-embodied': 0.05, - carbon: 0.205, - duration: 1, - requests: 10, - }, - { - timestamp: '2021-01-01T00:01:00Z', - 'carbon-operational': 0.2, - 'carbon-embodied': 0.05, - carbon: 0.205, - duration: 100, - requests: 10, - }, - ]; - const result = await sci.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.2, - 'carbon-embodied': 0.05, - carbon: 0.205, - duration: 1, - requests: 10, - sci: 0.020499999999999997, - }, - { - timestamp: '2021-01-01T00:01:00Z', - carbon: 0.205, - 'carbon-embodied': 0.05, - 'carbon-operational': 0.2, - duration: 100, - requests: 10, - sci: 0.020499999999999997, - }, - ]); - }); - - it('throws exception on invalid functional unit data.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.002, - 'carbon-embodied': 0.0005, - duration: 1, - }, - ]; - - expect.assertions(1); - - try { - await sci.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(MissingInputDataError); - } - }); - - it('throws exception if functional unit value is not positive integer.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.002, - 'carbon-embodied': 0.0005, - duration: 1, - requests: -5, - }, - ]; - - expect.assertions(1); - - try { - await sci.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(MissingInputDataError); - } - }); - }); - - it('fallbacks to carbon value, if functional unit is 0.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - 'carbon-operational': 0.2, - 'carbon-embodied': 0.05, - carbon: 0.205, - duration: 1, - requests: 0, - }, - ]; - const result = await sci.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts deleted file mode 100644 index 96de944f1..000000000 --- a/src/__tests__/unit/builtins/shell.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -import {spawnSync} from 'child_process'; -import {loadAll} from 'js-yaml'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Shell} from '../../../builtins/shell'; - -const {InputValidationError, ProcessExecutionError} = ERRORS; - -jest.mock('child_process'); -jest.mock('js-yaml'); - -describe('builtins/shell', () => { - describe('Shell', () => { - const shell = Shell({}); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(shell).toHaveProperty('metadata'); - expect(shell).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('execute with valid inputs and command', async () => { - const shell = Shell({command: 'python3 /path/to/script.py'}); - const mockSpawnSync = spawnSync as jest.MockedFunction< - typeof spawnSync - >; - mockSpawnSync.mockReturnValueOnce({stdout: 'mocked stdout'} as any); - - const mockLoadAll = loadAll as jest.MockedFunction; - mockLoadAll.mockReturnValueOnce(['mocked output'] as any); - - const inputs = [ - { - duration: 3600, - timestamp: '2022-01-01T00:00:00Z', - }, - ]; - - expect.assertions(2); - - await shell.execute(inputs); - - expect(mockSpawnSync).toHaveBeenCalledWith( - 'python3', - ['/path/to/script.py'], - { - encoding: 'utf8', - } - ); - expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); - }); - - it('throw an error if validation fails', async () => { - const invalidInputs = [ - {duration: 3600, timestamp: '2022-01-01T00:00:00Z', command: 123}, - ]; - - try { - await shell.execute(invalidInputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - '"command" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('throw an error when shell could not run command.', async () => { - const shell = Shell({command: 'python3 /path/to/script.py'}); - (spawnSync as jest.Mock).mockImplementation(() => { - throw new InputValidationError('Could not run the command'); - }); - - const inputs = [ - { - duration: 3600, - timestamp: '2022-01-01T00:00:00Z', - }, - ]; - expect.assertions(2); - - try { - await shell.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(ProcessExecutionError); - expect(error).toStrictEqual( - new ProcessExecutionError('Could not run the command') - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts deleted file mode 100644 index fd4cf7c96..000000000 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Subtract} from '../../../builtins/subtract'; - -const {InputValidationError} = ERRORS; - -describe('builtins/subtract: ', () => { - describe('Subtract: ', () => { - const globalConfig = { - 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], - 'output-parameter': 'energy/diff', - }; - const subtract = Subtract(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(subtract).toHaveProperty('metadata'); - expect(subtract).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Subtract strategy to given input.', async () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - 'cpu/energy': 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); - - try { - await subtract.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('returns a result with input params not related to energy.', async () => { - expect.assertions(1); - const newConfig = { - 'input-parameters': ['carbon', 'other-carbon'], - 'output-parameter': 'carbon-diff', - }; - const subtract = Subtract(newConfig); - - const data = [ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 3, - 'other-carbon': 2, - }, - ]; - const response = await subtract.execute(data); - - const expectedResult = [ - { - duration: 3600, - carbon: 3, - 'other-carbon': 2, - 'carbon-diff': 1, - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - expect(response).toEqual(expectedResult); - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts deleted file mode 100644 index 1810fc13a..000000000 --- a/src/__tests__/unit/builtins/sum.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {Sum} from '../../../builtins/sum'; - -import {STRINGS} from '../../../config'; - -const {GlobalConfigError, InputValidationError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; - -describe('builtins/sum: ', () => { - describe('Sum: ', () => { - const globalConfig = { - 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], - 'output-parameter': 'energy', - }; - const sum = Sum(globalConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(sum).toHaveProperty('metadata'); - expect(sum).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('successfully applies Sum strategy to given input.', () => { - expect.assertions(1); - - const expectedResult = [ - { - duration: 3600, - 'cpu/energy': 1, - 'network/energy': 1, - 'memory/energy': 1, - energy: 3, - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - 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!); - - expect.assertions(1); - - try { - sum.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'cpu/energy': 1, - 'network/energy': 1, - 'memory/energy': 1, - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); - } - }); - - it('throws an error on missing params in input.', () => { - expect.assertions(1); - - try { - sum.execute([ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - }, - ]); - } catch (error) { - expect(error).toStrictEqual( - new InputValidationError( - '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' - ) - ); - } - }); - - it('returns a result with input params not related to energy.', () => { - expect.assertions(1); - const newConfig = { - 'input-parameters': ['carbon', 'other-carbon'], - 'output-parameter': 'carbon-sum', - }; - const sum = Sum(newConfig); - - const data = [ - { - duration: 3600, - timestamp: '2021-01-01T00:00:00Z', - carbon: 1, - 'other-carbon': 2, - }, - ]; - const response = sum.execute(data); - - const expectedResult = [ - { - duration: 3600, - carbon: 1, - 'other-carbon': 2, - 'carbon-sum': 3, - timestamp: '2021-01-01T00:00:00Z', - }, - ]; - - expect(response).toEqual(expectedResult); - }); - }); - }); -}); diff --git a/src/__tests__/unit/builtins/time-sync.test.ts b/src/__tests__/unit/builtins/time-sync.test.ts deleted file mode 100644 index 6dd984659..000000000 --- a/src/__tests__/unit/builtins/time-sync.test.ts +++ /dev/null @@ -1,781 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {Settings, DateTime} from 'luxon'; - -import {TimeSync} from '../../../builtins/time-sync'; - -import {STRINGS} from '../../../config'; - -Settings.defaultZone = 'utc'; -const { - InputValidationError, - InvalidPaddingError, - InvalidDateInInputError, - InvalidInputError, - GlobalConfigError, -} = ERRORS; - -const { - INVALID_OBSERVATION_OVERLAP, - INVALID_TIME_NORMALIZATION, - AVOIDING_PADDING_BY_EDGES, - INVALID_DATE_TYPE, -} = STRINGS; - -jest.mock('luxon', () => { - const originalModule = jest.requireActual('luxon'); - return { - ...originalModule, - Interval: { - ...originalModule.Interval, - fromDateTimes: jest.fn((start, end) => ({ - start, - end, - splitBy: jest.fn(() => { - const intervals = []; - let current = start; - - while (current < end) { - intervals.push({ - start: process.env.MOCK_INTERVAL === 'true' ? null : current, - end: current.plus({seconds: 1}), - }); - - current = current.plus({seconds: 1}); - } - - return intervals; - }), - })), - }, - }; -}); - -describe('builtins/time-sync:', () => { - describe('time-sync: ', () => { - const basicConfig = { - 'start-time': '2023-12-12T00:01:00.000Z', - 'end-time': '2023-12-12T00:01:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const timeSync = TimeSync(basicConfig); - - describe('init: ', () => { - it('successfully initalized.', () => { - expect(timeSync).toHaveProperty('metadata'); - 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, - }, - ]; - - expect(result).toStrictEqual(expectedResult); - }); - - 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, - }; - - const timeModel = TimeSync(basicConfig); - - 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 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, - }; - - 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('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, - }; - - const timeModel = TimeSync(basicConfig); - - 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 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, - }; - - 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('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, - }; - - 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('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, - }; - - 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('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, - }; - - 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); - }); -}); diff --git a/src/__tests__/unit/lib/aggregate.test.ts b/src/__tests__/unit/lib/aggregate.test.ts deleted file mode 100644 index fb652e219..000000000 --- a/src/__tests__/unit/lib/aggregate.test.ts +++ /dev/null @@ -1,201 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import {aggregate} from '../../../lib/aggregate'; - -describe('lib/aggregate: ', () => { - describe('aggregate(): ', () => { - it('returns tree if aggregation is missing.', () => { - const tree = {}; - const aggregation = undefined; - - const aggregatedTree = aggregate(tree, aggregation); - expect(aggregatedTree).toEqual(tree); - }); - - it('returns tree if aggregation.type is missing.', () => { - const tree = {}; - const aggregation = { - metrics: [], - }; - - // @ts-ignore - const aggregatedTree = aggregate(tree, aggregation); - expect(aggregatedTree).toEqual(tree); - }); - - it('does horizontal aggregation.', () => { - const tree = { - children: { - mocks: { - outputs: [ - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - ], - }, - }, - }; - - const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], - type: 'horizontal', - }); - const expectedAggregated = { - carbon: - tree.children.mocks.outputs[0].carbon + - tree.children.mocks.outputs[1].carbon, - }; - expect(aggregatedTree.children.mocks.aggregated).toEqual( - expectedAggregated - ); - }); - - it('does vertical aggregation.', () => { - const tree = { - children: { - 'mocks-1': { - outputs: [ - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - ], - }, - 'mocks-2': { - outputs: [ - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 20, - }, - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 20, - }, - ], - }, - }, - }; - - const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], - type: 'vertical', - }); - const expectedOutputs = [ - { - carbon: 30, - timestamp: 'mock-timestamp', - duration: 'mock-duration', - }, - { - carbon: 30, - timestamp: 'mock-timestamp', - duration: 'mock-duration', - }, - ]; - const expectedAggregated = { - carbon: - tree.children['mocks-1'].outputs[0].carbon + - tree.children['mocks-2'].outputs[0].carbon + - tree.children['mocks-1'].outputs[1].carbon + - tree.children['mocks-2'].outputs[1].carbon, - }; - expect(aggregatedTree.outputs).toEqual(expectedOutputs); - expect(aggregatedTree.aggregated).toEqual(expectedAggregated); - }); - - it('does both aggregations.', () => { - const tree = { - children: { - 'mocks-1': { - outputs: [ - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 10, - }, - ], - }, - 'mocks-2': { - outputs: [ - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 20, - }, - { - timestamp: 'mock-timestamp', - duration: 'mock-duration', - carbon: 20, - }, - ], - }, - }, - }; - - const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], - type: 'both', - }); - - // horizontal aggregation - const expectedNode1Horizontal = { - carbon: - tree.children['mocks-1'].outputs[0].carbon + - tree.children['mocks-1'].outputs[1].carbon, - }; - expect(aggregatedTree.children['mocks-1'].aggregated).toEqual( - expectedNode1Horizontal - ); - const expectedNode2Horizontal = { - carbon: - tree.children['mocks-2'].outputs[0].carbon + - tree.children['mocks-2'].outputs[1].carbon, - }; - expect(aggregatedTree.children['mocks-2'].aggregated).toEqual( - expectedNode2Horizontal - ); - - // vertical aggregation - const expectedOutputs = [ - { - carbon: 30, - timestamp: 'mock-timestamp', - duration: 'mock-duration', - }, - { - carbon: 30, - timestamp: 'mock-timestamp', - duration: 'mock-duration', - }, - ]; - expect(aggregatedTree.outputs).toEqual(expectedOutputs); - const expectedAggregated = { - carbon: - tree.children['mocks-1'].outputs[0].carbon + - tree.children['mocks-2'].outputs[0].carbon + - tree.children['mocks-1'].outputs[1].carbon + - tree.children['mocks-2'].outputs[1].carbon, - }; - expect(aggregatedTree.aggregated).toEqual(expectedAggregated); - }); - }); -}); diff --git a/src/__tests__/unit/lib/compare.test.ts b/src/__tests__/unit/lib/compare.test.ts deleted file mode 100644 index dbac5a490..000000000 --- a/src/__tests__/unit/lib/compare.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import {compare} from '../../../lib/compare'; - -describe('lib/compare: ', () => { - describe('compare(): ', () => { - it('test if empty objects are equal.', () => { - const a = {}; - const b = {}; - - const response = compare(a, b); - expect(Object.keys(response).length).toEqual(0); - }); - - it('tests for nested objects with arrays.', () => { - const a = { - tree: { - inputs: [1, 2], - }, - }; - const b = { - tree: { - inputs: [1, 2], - }, - }; - - const response = compare(a, b); - expect(Object.keys(response).length).toEqual(0); - }); - - it('tests for nested objects with arrays (negative case).', () => { - const a = { - tree: { - inputs: [1, 2], - }, - }; - const b = { - tree: { - inputs: [1], - }, - }; - - const response = compare(a, b); - expect(response.path).toEqual('tree.inputs.1'); - expect(response.source).toEqual(2); - expect(response.target).toBeUndefined(); - }); - - it('checks if execution params are ignored.', () => { - const a = { - tree: { - inputs: [1, 2], - }, - execution: { - a: 'mock-a', - b: 'mock-b', - status: 'success', - }, - }; - const b = { - tree: { - inputs: [1, 2], - }, - execution: { - status: 'success', - }, - }; - - const response = compare(a, b); - expect(Object.keys(response).length).toEqual(0); - }); - - it('checks if error and status are in place, and others are ignored.', () => { - const a = { - tree: { - inputs: [1, 2], - }, - execution: { - a: 'a', - b: 'b', - error: 'mock-error-message', - status: 'fail', - }, - }; - const b = { - tree: { - inputs: [1, 2], - }, - execution: { - error: 'mock-error-message', - status: 'fail', - }, - }; - - const response = compare(a, b); - expect(Object.keys(response).length).toEqual(0); - }); - - it('checks if arrays are equal.', () => { - const a = [1, 2]; - const b = [1, 2]; - - const response = compare(a, b); - expect(Object.keys(response).length).toEqual(0); - }); - - it('checks if arrays are equal (first one is missing some items).', () => { - const a = [1]; - const b = [1, 2]; - - const response = compare(a, b); - const expectedResponse = {path: '1', source: undefined, target: 2}; - expect(response).toEqual(expectedResponse); - }); - }); -}); diff --git a/src/__tests__/unit/lib/compute.test.ts b/src/__tests__/unit/lib/compute.test.ts deleted file mode 100644 index 9ff951586..000000000 --- a/src/__tests__/unit/lib/compute.test.ts +++ /dev/null @@ -1,237 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import {compute} from '../../../lib/compute'; - -import {ComputeParams} from '../../../types/compute'; -import {pluginStorage} from '../../../util/plugin-storage'; - -describe('lib/compute: ', () => { - /** - * Mock plugins. - */ - const mockExecutePlugin = () => ({ - execute: (inputs: any) => - inputs.map((input: any) => { - input.newField = 'mock-newField'; - - return input; - }), - metadata: { - kind: 'execute', - }, - }); - const mockGroupByPlugin = () => ({ - execute: (inputs: any) => ({children: inputs}), - metadata: { - kind: 'groupby', - }, - }); - /** - * Compute params. - */ - const paramsExecute: ComputeParams = { - // @ts-ignore - context: { - name: 'mock-name', - initialize: { - plugins: { - mock: { - path: 'mockavizta', - method: 'Mockavizta', - }, - }, - }, - }, - pluginStorage: pluginStorage().set('mock', mockExecutePlugin()), - }; - const params: ComputeParams = { - // @ts-ignore - context: { - name: 'mock-name', - initialize: { - plugins: { - mock: { - path: 'mockavizta', - method: 'Mockavizta', - }, - }, - }, - }, - pluginStorage: pluginStorage().set('mock', mockGroupByPlugin()), - }; - - describe('compute(): ', () => { - it('computes simple tree with execute plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }; - - const response = await compute(tree, paramsExecute); - const expectedResult = mockExecutePlugin().execute( - tree.children.mockChild.inputs - ); - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); - - it('computes simple tree with groupby plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }; - const response = await compute(tree, params); - const expectedResult = mockGroupByPlugin().execute( - tree.children.mockChild.inputs - ); - - expect(response.children.mockChild.children).toEqual(expectedResult); - }); - - it('computes simple tree with defaults and execute plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - defaults: { - 'cpu/name': 'Intel CPU', - }, - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }; - const response = await compute(tree, paramsExecute); - const expectedResult = mockExecutePlugin().execute( - tree.children.mockChild.inputs.map((input: any) => { - input['cpu/name'] = 'Intel CPU'; - - return input; - }) - ); - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); - - it('computes nested tree with defaults and execute plugin.', async () => { - const tree = { - children: { - mockChild1: { - pipeline: ['mock'], - defaults: { - 'cpu/name': 'Intel CPU', - }, - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - mockChild2: { - children: { - mockChild21: { - pipeline: ['mock'], - defaults: { - 'cpu/name': 'Intel CPU', - }, - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }, - }, - }; - const response = await compute(tree, paramsExecute); - - const mapper = (input: any) => { - input['cpu/name'] = 'Intel CPU'; - - return input; - }; - const expectedResult1 = mockExecutePlugin().execute( - tree.children.mockChild1.inputs.map(mapper) - ); - const expectedResult21 = mockExecutePlugin().execute( - tree.children.mockChild2.children.mockChild21.inputs.map(mapper) - ); - - expect(response.children.mockChild1.outputs).toEqual(expectedResult1); - expect(response.children.mockChild2.children.mockChild21.outputs).toEqual( - expectedResult21 - ); - }); - - it('computes simple tree with no defaults and no inputs with execue plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - defaults: {}, - inputs: [], - }, - }, - }; - const response = await compute(tree, paramsExecute); - const expectedResult: any[] = []; - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); - - it('computes simple tree with defaults and no inputs with execue plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - defaults: { - carbon: 10, - }, - input: [], - }, - }, - }; - const response = await compute(tree, paramsExecute); - const expectedResult: any[] = [{carbon: 10, newField: 'mock-newField'}]; - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); - - it('computes simple tree with node config and execute plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: ['mock'], - config: { - 'cpu/name': 'Intel CPU', - }, - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }; - const response = await compute(tree, paramsExecute); - const expectedResult = mockExecutePlugin().execute( - tree.children.mockChild.inputs - ); - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); - }); -}); diff --git a/src/__tests__/unit/lib/environment.test.ts b/src/__tests__/unit/lib/environment.test.ts deleted file mode 100644 index c528eaee1..000000000 --- a/src/__tests__/unit/lib/environment.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -import {injectEnvironment} from '../../../lib/environment'; - -describe('lib/envirnoment: ', () => { - describe('injectEnvironment(): ', () => { - const context = {}; - - it('checks response to have `execution` property.', async () => { - // @ts-ignore - const response = await injectEnvironment(context); - expect(response).toHaveProperty('execution'); - }); - - it('checks `execution` to have `command` and `environment` props.', async () => { - // @ts-ignore - const response = await injectEnvironment(context); - const {execution} = response; - - expect(execution).toHaveProperty('command'); - expect(execution).toHaveProperty('environment'); - }); - - it('checks environment response type.', async () => { - // @ts-ignore - const response = await injectEnvironment(context); - const environment = response.execution!.environment!; - - expect(typeof environment['date-time']).toEqual('string'); - expect(Array.isArray(environment.dependencies)).toBeTruthy(); - expect(typeof environment['node-version']).toEqual('string'); - expect(typeof environment.os).toEqual('string'); - expect(typeof environment['os-version']).toEqual('string'); - }); - }); -}); diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts deleted file mode 100644 index 49db14370..000000000 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -jest.mock('fs', () => require('../../../__mocks__/fs')); - -import {ERRORS} from '@grnsft/if-core/utils'; - -import {exhaust} from '../../../lib/exhaust'; - -import {STRINGS} from '../../../config'; - -const {ExhaustOutputArgError, InvalidExhaustPluginError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN, OUTPUT_REQUIRED} = STRINGS; - -describe('lib/exhaust: ', () => { - describe('exhaust(): ', () => { - const spy = jest.spyOn(global.console, 'log'); - - beforeEach(() => { - spy.mockReset(); - }); - - it('returns void if no exhaust plugin selected.', async () => { - const tree = {}; - const context = { - initialize: { - outputs: null, - }, - }; - - // @ts-ignore - const result = await exhaust(tree, context, {}); - - expect(result).toBeUndefined(); - }); - - it('uses log exhaust plugin as export.', async () => { - const tree = {}; - const context = { - initialize: {}, - }; - - // @ts-ignore - await exhaust(tree, context, {stdout: true}); - expect(spy).toHaveBeenCalledTimes(1); - }); - - it('rejects with cli input error if output path is not provided with yaml.', async () => { - const tree = {}; - const context = { - initialize: { - outputs: ['yaml'], - }, - }; - - expect.assertions(2); - - try { - // @ts-ignore - await exhaust(tree, context, {}); - } catch (error) { - expect(error).toBeInstanceOf(ExhaustOutputArgError); - - if (error instanceof ExhaustOutputArgError) { - expect(error.message).toEqual(OUTPUT_REQUIRED); - } - } - }); - - it('rejects with module init error if output module is not supported.', async () => { - const tree = {}; - const context = { - initialize: { - outputs: ['mock'], - }, - }; - - expect.assertions(2); - - try { - // @ts-ignore - await exhaust(tree, context, {}); - } catch (error) { - expect(error).toBeInstanceOf(InvalidExhaustPluginError); - - if (error instanceof InvalidExhaustPluginError) { - expect(error.message).toEqual( - INVALID_EXHAUST_PLUGIN(context.initialize.outputs[0]) - ); - } - } - }); - }); -}); diff --git a/src/__tests__/unit/lib/initialize.test.ts b/src/__tests__/unit/lib/initialize.test.ts deleted file mode 100644 index ff3c10c45..000000000 --- a/src/__tests__/unit/lib/initialize.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -jest.mock('mockavizta', () => require('../../../__mocks__/plugin'), { - virtual: true, -}); -jest.mock('../../../builtins', () => require('../../../__mocks__/plugin'), { - virtual: true, -}); -const mockLog = jest.fn(); -jest.mock('../../../util/log-memoize', () => ({ - memoizedLog: mockLog, -})); - -import {ERRORS} from '@grnsft/if-core/utils'; - -import {initialize} from '../../../lib/initialize'; - -import {STRINGS} from '../../../config'; - -import {GlobalPlugins} from '../../../types/manifest'; - -const { - MissingPluginPathError, - MissingPluginMethodError, - PluginInitializationError, -} = ERRORS; -const {MISSING_METHOD, MISSING_PATH, INVALID_MODULE_PATH} = STRINGS; - -describe('lib/initalize: ', () => { - describe('initalize(): ', () => { - it('creates instance with get and set methods.', async () => { - const plugins = {}; - const response = await initialize(plugins); - - expect(response).toHaveProperty('get'); - expect(response).toHaveProperty('set'); - expect(typeof response.get).toEqual('function'); - expect(typeof response.set).toEqual('function'); - }); - - it('checks if plugin is initalized, warning is logged and plugin has execute and metadata props.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'mockavizta', - method: 'Mockavizta', - }, - }; - const storage = await initialize(plugins); - - const pluginName = Object.keys(plugins)[0]; - const module = storage.get(pluginName); - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - expect(mockLog).toHaveBeenCalledTimes(1); // checks if logger is called - }); - - it('checks if plugin is initalized with global config and has execute and metadata.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'mockavizta', - method: 'Mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - const storage = await initialize(plugins); - - const pluginName = Object.keys(plugins)[0]; - const module = storage.get(pluginName); - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - }); - - it('throws error if plugin does not have path property.', async () => { - const plugins: GlobalPlugins = { - // @ts-ignore - mockavizta: { - method: 'Mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - - try { - await initialize(plugins); - } catch (error) { - expect(error).toBeInstanceOf(MissingPluginPathError); - - if (error instanceof MissingPluginPathError) { - expect(error.message).toEqual(MISSING_PATH); - } - } - }); - - it('throws error if plugin does not have path property.', async () => { - const plugins: GlobalPlugins = { - // @ts-ignore - mockavizta: { - path: 'mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - - try { - await initialize(plugins); - } catch (error) { - expect(error).toBeInstanceOf(MissingPluginMethodError); - - if (error instanceof MissingPluginMethodError) { - expect(error.message).toEqual(MISSING_METHOD); - } - } - }); - - it('checks if builtin plugin is initalized.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'builtin', - method: 'Mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - const storage = await initialize(plugins); - - const pluginName = Object.keys(plugins)[0]; - const module = storage.get(pluginName); - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - }); - - it('checks if github plugin is initalized.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'https://github.com/mockavizta', - method: 'Mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - const storage = await initialize(plugins); - - const pluginName = Object.keys(plugins)[0]; - const module = storage.get(pluginName); - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - }); - - it('throws error if plugin path is invalid.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'failing-mock', - method: 'Mockavizta', - 'global-config': { - verbose: true, - }, - }, - }; - - try { - await initialize(plugins); - } catch (error: any) { - expect(error).toBeInstanceOf(PluginInitializationError); - expect(error.message).toEqual( - INVALID_MODULE_PATH( - plugins.mockavizta.path, - new Error( - "Cannot find module 'failing-mock' from 'src/lib/initialize.ts'" - ) - ) - ); - } - }); - }); -}); diff --git a/src/__tests__/unit/lib/load.test.ts b/src/__tests__/unit/lib/load.test.ts deleted file mode 100644 index ba3bca902..000000000 --- a/src/__tests__/unit/lib/load.test.ts +++ /dev/null @@ -1,143 +0,0 @@ -jest.mock('../../../util/json', () => require('../../../__mocks__/json')); -jest.mock( - 'mockavizta', - () => ({ - __esmodule: true, - Mockavizta: () => ({ - execute: (input: PluginParams) => input, - metadata: { - kind: 'execute', - }, - }), - }), - {virtual: true} -); -jest.mock('../../../util/helpers', () => ({ - parseManifestFromStdin: () => { - if (process.env.readline === 'valid-source') { - return ` -name: 'mock-name' -description: 'mock-description' -`; - } - return ''; - }, -})); -jest.mock('../../../util/yaml', () => ({ - openYamlFileAsObject: (path: string) => { - switch (path) { - case 'load-default.yml': - return 'raw-manifest'; - case 'source-path.yml': - return 'source-manifest'; - case 'target-path.yml': - return 'target-manifest'; - default: - return ''; - } - }, -})); - -import {PluginParams} from '@grnsft/if-core/types'; - -import {load, loadIfDiffFiles} from '../../../lib/load'; - -import {PARAMETERS, STRINGS} from '../../../config'; - -import {parseManifestFromStdin} from '../../../util/helpers'; - -import {LoadDiffParams} from '../../../types/util/args'; - -const {INVALID_SOURCE} = STRINGS; - -describe('lib/load: ', () => { - describe('load(): ', () => { - it('loads yaml with default parameters.', async () => { - const inputPath = 'load-default.yml'; - const paramPath = undefined; - - const result = await load(inputPath, paramPath); - - const expectedValue = { - rawManifest: 'raw-manifest', - parameters: PARAMETERS, - }; - - expect(result).toEqual(expectedValue); - }); - - it('loads yaml with custom parameters.', async () => { - const inputPath = 'load-default.yml'; - const paramPath = 'param-mock.json'; - - const result = await load(inputPath, paramPath); - - const expectedValue = { - rawManifest: 'raw-manifest', - parameters: { - 'mock-carbon': { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'mock-cpu': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - }, - }; - - expect(result).toEqual(expectedValue); - }); - }); - - describe('loadIfDiffFiles(): ', () => { - it('rejects with invalid source error.', async () => { - const params = { - sourcePath: '', - targetPath: '', - }; - - try { - await loadIfDiffFiles(params); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(Error); - expect(error.message).toBe(INVALID_SOURCE); - } - } - }); - - it('successfully loads target, and source from stdin.', async () => { - process.env.readline = 'valid-source'; - const piped = await parseManifestFromStdin(); - const params: LoadDiffParams = { - targetPath: 'target-path.yml', - pipedSourceManifest: piped, - }; - - const response = await loadIfDiffFiles(params); - const expectedSource = { - name: 'mock-name', - description: 'mock-description', - }; - const expectedTarget = 'target-manifest'; - expect(response.rawSourceManifest).toEqual(expectedSource); - expect(response.rawTargetManifest).toEqual(expectedTarget); - }); - - it('successfully loads target, and source from stdin.', async () => { - const params = { - targetPath: 'target-path.yml', - sourcePath: 'source-path.yml', - }; - - const response = await loadIfDiffFiles(params); - const expectedSource = 'source-manifest'; - const expectedTarget = 'target-manifest'; - expect(response.rawSourceManifest).toEqual(expectedSource); - expect(response.rawTargetManifest).toEqual(expectedTarget); - }); - }); -}); diff --git a/src/__tests__/unit/lib/parameterize.test.ts b/src/__tests__/unit/lib/parameterize.test.ts deleted file mode 100644 index 430d8e043..000000000 --- a/src/__tests__/unit/lib/parameterize.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import {LeveledLogMethod} from 'winston'; - -const mockLog = jest.fn((message: string) => message); - -jest.mock('../../../util/log-memoize', () => ({ - memoizedLog: mockLog, -})); -jest.mock('../../../util/logger', () => ({ - logger: { - warn: mockLog, - debug: mockLog, - }, -})); - -import {PARAMETERS} from '../../../config'; -import {parameterize} from '../../../lib/parameterize'; - -import {STRINGS} from '../../../config'; - -import {ManifestParameter} from '../../../types/manifest'; - -const {REJECTING_OVERRIDE, CHECKING_AGGREGATION_METHOD} = STRINGS; - -describe('lib/parameterize: ', () => { - afterEach(() => { - (mockLog as jest.Mock).mockReset(); - }); - - describe('getAggregationMethod(): ', () => { - it('returns method for average aggregation method metric.', () => { - const metric = 'cpu/utilization'; - const method = parameterize.getAggregationMethod(metric); - - const expectedMethod = 'avg'; - - expect(method).toEqual(expectedMethod); - }); - - it('returns method for unknown aggregation method metric.', () => { - const metric = 'mock/metric'; - const method = parameterize.getAggregationMethod(metric); - - const expectedMethod = 'sum'; - - expect(method).toEqual(expectedMethod); - expect(mockLog as unknown as LeveledLogMethod).toHaveBeenCalledTimes(2); - }); - - it('prints debug log for first input.', () => { - const unitName = 'timestamp'; - - parameterize.getAggregationMethod(unitName); - - expect(mockLog as typeof console.debug).toHaveBeenCalledWith( - console.debug, - CHECKING_AGGREGATION_METHOD(unitName) - ); - }); - }); - - describe('combine(): ', () => { - it('checks if return type is undefined.', () => { - const params = {}; - const response = parameterize.combine(null, params); - - expect(response).toBeUndefined(); - }); - - it('checks if uninitialized custom param is requested, then returns fallback `sum` method.', () => { - const name = 'mock-name'; - const method = parameterize.getAggregationMethod(name); - - const expectedMethodName = 'sum'; - expect(method).toEqual(expectedMethodName); - }); - - it('checks if custom params are inserted successfully.', () => { - const params = [ - { - name: 'mock-name', - description: 'mock-description', - unit: 'mock/sq', - aggregation: 'none', - }, - ] as ManifestParameter[]; - const object = {}; - - parameterize.combine(params, object); - const method = parameterize.getAggregationMethod(params[0].name); - - expect(method).toEqual(params[0].aggregation); - }); - - it('rejects on default param override.', () => { - const params = [ - { - name: 'carbon', - description: 'mock-description', - unit: 'mock/co', - aggregation: 'none', - }, - ] as ManifestParameter[]; - - parameterize.combine(params, PARAMETERS); - const method = parameterize.getAggregationMethod(params[0].name); - - const expectedMethodName = 'sum'; - const expectedMessage = REJECTING_OVERRIDE(params[0]); - - expect(method).toEqual(expectedMethodName); - expect(mockLog).toHaveBeenCalledWith(expectedMessage); - }); - }); -}); diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts deleted file mode 100644 index 1a23bc3c1..000000000 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; -import {PluginParams} from '@grnsft/if-core/types'; - -import {aggregateInputsIntoOne} from '../../../util/aggregation-helper'; - -import {STRINGS} from '../../../config'; - -const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; -const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; - -describe('util/aggregation-helper: ', () => { - describe('aggregateInputsIntoOne(): ', () => { - it('throws error if aggregation method is none.', () => { - const inputs: PluginParams[] = []; - const metrics: string[] = ['cpu/number-cores']; - const isTemporal = false; - - expect.assertions(2); - - try { - aggregateInputsIntoOne(inputs, metrics, isTemporal); - } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationMethodError); - - if (error instanceof InvalidAggregationMethodError) { - expect(error.message).toEqual(INVALID_AGGREGATION_METHOD(metrics[0])); - } - } - }); - - it('throws error if aggregation criteria is not found in input.', () => { - const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; - const metrics: string[] = ['cpu/utilization']; - const isTemporal = false; - - expect.assertions(2); - - try { - aggregateInputsIntoOne(inputs, metrics, isTemporal); - } catch (error) { - expect(error).toBeInstanceOf(MissingAggregationParamError); - - if (error instanceof MissingAggregationParamError) { - expect(error.message).toEqual(METRIC_MISSING(metrics[0], 0)); - } - } - }); - - it('passes `timestamp`, `duration` to aggregator if aggregation is temporal.', () => { - const inputs: PluginParams[] = [ - {timestamp: '', duration: 10, carbon: 10}, - {timestamp: '', duration: 10, carbon: 20}, - ]; - const metrics: string[] = ['carbon']; - const isTemporal = true; - - const expectedValue = { - timestamp: '', - duration: 10, - carbon: inputs[0].carbon + inputs[1].carbon, - }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); - expect(aggregated).toEqual(expectedValue); - }); - - it('skips `timestamp`, `duration` if aggregation is not temporal.', () => { - const inputs: PluginParams[] = [ - {timestamp: '', duration: 10, carbon: 10}, - {timestamp: '', duration: 10, carbon: 20}, - ]; - const metrics: string[] = ['carbon']; - const isTemporal = false; - - const expectedValue = { - carbon: inputs[0].carbon + inputs[1].carbon, - }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); - expect(aggregated).toEqual(expectedValue); - }); - - it('calculates average of metrics.', () => { - const inputs: PluginParams[] = [ - {timestamp: '', duration: 10, 'cpu/utilization': 10}, - {timestamp: '', duration: 10, 'cpu/utilization': 90}, - ]; - const metrics: string[] = ['cpu/utilization']; - const isTemporal = false; - - const expectedValue = { - 'cpu/utilization': - (inputs[0]['cpu/utilization'] + inputs[1]['cpu/utilization']) / - inputs.length, - }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); - expect(aggregated).toEqual(expectedValue); - expect(aggregated.timestamp).toBeUndefined(); - expect(aggregated.duration).toBeUndefined(); - }); - }); -}); diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts deleted file mode 100644 index f4238cbce..000000000 --- a/src/__tests__/unit/util/args.test.ts +++ /dev/null @@ -1,522 +0,0 @@ -const processRunningPath = process.cwd(); - -jest.mock('../../../util/fs', () => ({ - isFileExists: () => { - if (process.env.fileExists === 'true') { - return true; - } - return false; - }, - isDirectoryExists: () => { - if (process.env.directoryExists === 'true') { - return true; - } - return false; - }, -})); - -jest.mock('ts-command-line-args', () => ({ - __esModule: true, - parse: () => { - switch (process.env.result) { - case 'throw-error-object': - throw new Error(MANIFEST_IS_MISSING); - case 'error': - throw MANIFEST_IS_MISSING; - case 'manifest-is-missing': - return {}; - case 'manifest': - return { - manifest: 'manifest-mock.yml', - }; - case 'absolute-path': - return { - manifest: path.normalize(`${processRunningPath}/manifest-mock.yml`), - }; - case 'manifest-output': - return { - manifest: 'manifest-mock.yml', - output: 'output-mock.yml', - }; - case 'override-params': - return { - manifest: 'manifest-mock.yml', - 'override-params': 'override-params-mock.yml', - }; - case 'not-yaml': - return { - manifest: 'mock.notyaml', - }; - case 'stdout': - return { - manifest: 'manifest-mock.yaml', - stdout: true, - }; - /** If-diff mocks */ - case 'only-target': - return { - target: 'target-mock.yml', - }; - case 'target-is-not-yaml': - return { - target: 'target-mock', - }; - case 'source-is-not-yaml': - return { - target: 'target-mock.yml', - source: 'source-mock', - }; - case 'target-source': - return { - target: 'target-mock.yml', - source: 'source-mock.yml', - }; - case 'diff-throw-error': - throw new Error('mock-error'); - case 'diff-throw': - throw 'mock-error'; - /** If-env mocks */ - case 'manifest-install-provided': - return { - install: true, - manifest: 'mock-manifest.yaml', - }; - case 'manifest-is-not-yaml': - return {manifest: 'manifest'}; - case 'manifest-path-invalid': - throw new Error(MANIFEST_NOT_FOUND); - case 'env-throw-error': - throw new Error('mock-error'); - case 'env-throw': - throw 'mock-error'; - /** If-check */ - case 'manifest-is-provided': - return {manifest: 'mock-manifest.yaml'}; - case 'directory-is-provided': - return {directory: '/mock-directory'}; - case 'flags-are-not-provided': - return {manifest: undefined, directory: undefined}; - default: - return { - manifest: 'mock-manifest.yaml', - output: 'mock-output', - }; - } - }, -})); - -import * as path from 'node:path'; -import {ERRORS} from '@grnsft/if-core/utils'; - -import { - parseIEProcessArgs, - parseIfCheckArgs, - parseIfDiffArgs, - parseIfEnvArgs, -} from '../../../util/args'; - -import {STRINGS} from '../../../config'; - -const { - CliSourceFileError, - ParseCliParamsError, - InvalidDirectoryError, - MissingCliFlagsError, -} = ERRORS; - -const { - MANIFEST_IS_MISSING, - TARGET_IS_NOT_YAML, - INVALID_TARGET, - SOURCE_IS_NOT_YAML, - MANIFEST_NOT_FOUND, - DIRECTORY_NOT_FOUND, - IF_CHECK_FLAGS_MISSING, -} = STRINGS; - -describe('util/args: ', () => { - const originalEnv = process.env; - - describe('parseIEProcessArgs(): ', () => { - it('throws error if there is no argument passed.', () => { - expect.assertions(5); - - process.env.result = 'error'; // used for mocking - - try { - parseIEProcessArgs(); - } catch (error) { - expect(error).toEqual(MANIFEST_IS_MISSING); - } - - process.env.result = 'throw-error-object'; - - try { - parseIEProcessArgs(); - } catch (error) { - expect(error).toBeInstanceOf(ParseCliParamsError); - expect(error).toEqual(new ParseCliParamsError(MANIFEST_IS_MISSING)); - } - - process.env.result = 'manifest-is-missing'; - - try { - parseIEProcessArgs(); - } catch (error) { - expect(error).toBeInstanceOf(CliSourceFileError); - expect(error).toEqual(new CliSourceFileError(MANIFEST_IS_MISSING)); - } - }); - - it('returns manifest path.', () => { - expect.assertions(1); - - process.env.result = 'manifest'; - - const result = parseIEProcessArgs(); - const manifestPath = 'manifest-mock.yml'; - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - outputOptions: { - stdout: undefined, - }, - }; - - expect(result).toEqual(expectedResult); - }); - - it('returns manifest with absolute path.', () => { - expect.assertions(1); - - process.env.result = 'absolute-path'; - - const result = parseIEProcessArgs(); - const manifestPath = 'manifest-mock.yml'; - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - outputOptions: {}, - }; - - expect(result).toEqual(expectedResult); - }); - - it('returns manifest with `paramPath`.', () => { - expect.assertions(1); - - process.env.result = 'override-params'; - - const result = parseIEProcessArgs(); - const manifestPath = 'manifest-mock.yml'; - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - paramPath: 'override-params-mock.yml', - outputOptions: {}, - }; - - expect(result).toEqual(expectedResult); - }); - - it('returns manifest and output path.', () => { - expect.assertions(1); - - process.env.result = 'manifest-output'; - - const result = parseIEProcessArgs(); - const manifestPath = 'manifest-mock.yml'; - const outputPath = 'output-mock.yml'; - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - outputOptions: { - outputPath: path.normalize(`${processRunningPath}/${outputPath}`), - stdout: undefined, - }, - }; - - expect(result).toEqual(expectedResult); - }); - - it('throws error if file is not yaml.', () => { - expect.assertions(2); - - process.env.result = 'not-yaml'; - - try { - parseIEProcessArgs(); - } catch (error) { - expect(error).toBeInstanceOf(CliSourceFileError); - expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); - } - }); - - it('returns stdout and manifest.', () => { - expect.assertions(1); - - process.env.result = 'stdout'; - const manifestPath = 'manifest-mock.yaml'; - - const response = parseIEProcessArgs(); - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - outputOptions: { - stdout: true, - }, - }; - - expect(response).toEqual(expectedResult); - }); - }); - - describe('parseIfDiffArgs(): ', () => { - it('throws error if `target` is missing.', () => { - expect.assertions(1); - - try { - parseIfDiffArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError(INVALID_TARGET)); - } - } - }); - - it('throws error if `target` is not a yaml.', () => { - process.env.result = 'target-is-not-yaml'; - expect.assertions(1); - - try { - parseIfDiffArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError(TARGET_IS_NOT_YAML)); - } - } - }); - - it('returns `target`s full path.', () => { - process.env.result = 'only-target'; - expect.assertions(1); - - const response = parseIfDiffArgs(); - expect(response).toHaveProperty('targetPath'); - }); - - it('throws error if source is not a yaml.', () => { - process.env.result = 'source-is-not-yaml'; - expect.assertions(1); - - try { - parseIfDiffArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError(SOURCE_IS_NOT_YAML)); - } - } - }); - - it('returns target and source full paths.', () => { - process.env.result = 'target-source'; - expect.assertions(2); - - const response = parseIfDiffArgs(); - expect(response).toHaveProperty('targetPath'); - expect(response).toHaveProperty('sourcePath'); - }); - - it('throws error if parsing failed.', () => { - process.env.result = 'diff-throw-error'; - expect.assertions(1); - - try { - parseIfDiffArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError('mock-error')); - } - } - }); - - it('throws error if parsing failed (not instance of error).', () => { - process.env.result = 'diff-throw'; - expect.assertions(1); - - try { - parseIfDiffArgs(); - } catch (error) { - expect(error).toEqual('mock-error'); - } - }); - }); - - describe('parseIfEnvArgs(): ', () => { - it('executes if `manifest` is missing.', async () => { - process.env.fileExists = 'true'; - process.env.result = 'manifest-is-missing'; - const response = await parseIfEnvArgs(); - - expect.assertions(1); - - expect(response).toEqual({install: undefined}); - }); - - it('executes if `manifest` and `install` are provided.', async () => { - process.env.fileExists = 'true'; - process.env.result = 'manifest-install-provided'; - - const response = await parseIfEnvArgs(); - - expect.assertions(2); - expect(response).toHaveProperty('install'); - expect(response).toHaveProperty('manifest'); - }); - - it('throws an error if `manifest` is not a yaml.', async () => { - process.env.fileExists = 'true'; - process.env.result = 'manifest-is-not-yaml'; - expect.assertions(1); - - try { - await parseIfEnvArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); - } - } - }); - - it('throws an error if `manifest` path is invalid.', async () => { - process.env.fileExists = 'false'; - expect.assertions(1); - - try { - await parseIfEnvArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); - } - } - }); - - it('throws an error if parsing failed.', async () => { - process.env.result = 'env-throw-error'; - expect.assertions(1); - - try { - await parseIfEnvArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError('mock-error')); - } - } - }); - - it('throws error if parsing failed (not instance of error).', async () => { - process.env.result = 'env-throw'; - expect.assertions(1); - - try { - await parseIfEnvArgs(); - } catch (error) { - expect(error).toEqual('mock-error'); - } - }); - }); - - describe('parseIfCheckArgs(): ', () => { - it('executes when `manifest` is provided.', async () => { - process.env.fileExists = 'true'; - process.env.result = 'manifest-is-provided'; - const response = await parseIfCheckArgs(); - - expect.assertions(1); - - expect(response).toEqual({manifest: 'mock-manifest.yaml'}); - }); - - it('executes when the `directory` is provided.', async () => { - process.env.directoryExists = 'true'; - process.env.result = 'directory-is-provided'; - - const response = await parseIfCheckArgs(); - - expect.assertions(1); - - expect(response).toEqual({directory: '/mock-directory'}); - }); - - it('throws an error when the `directory` does not exist.', async () => { - process.env.directoryExists = 'false'; - process.env.result = 'directory-is-provided'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - expect(error).toEqual(new InvalidDirectoryError(DIRECTORY_NOT_FOUND)); - } - }); - - it('throws an error when both `manifest` and `directory` flags are not provided.', async () => { - process.env.result = 'flags-are-not-provided'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - expect(error).toEqual(new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING)); - } - }); - - it('throws an error if `manifest` is not a yaml.', async () => { - process.env.fileExists = 'true'; - process.env.result = 'manifest-is-not-yaml'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); - } - } - }); - - it('throws an error if `manifest` path is invalid.', async () => { - process.env.fileExists = 'false'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); - } - } - }); - - it('throws an error if parsing failed.', async () => { - process.env.result = 'env-throw-error'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - if (error instanceof Error) { - expect(error).toEqual(new ParseCliParamsError('mock-error')); - } - } - }); - - it('throws error if parsing failed (not instance of error).', async () => { - process.env.result = 'env-throw'; - expect.assertions(1); - - try { - await parseIfCheckArgs(); - } catch (error) { - expect(error).toEqual('mock-error'); - } - }); - }); - - process.env = originalEnv; -}); diff --git a/src/__tests__/unit/util/debug-logger.test.ts b/src/__tests__/unit/util/debug-logger.test.ts deleted file mode 100644 index 63bafa0af..000000000 --- a/src/__tests__/unit/util/debug-logger.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -const logSpy = jest.spyOn(console, 'log'); -const infoSpy = jest.spyOn(console, 'info'); -const warnSpy = jest.spyOn(console, 'warn'); -const errorSpy = jest.spyOn(console, 'error'); -const debugSpy = jest.spyOn(console, 'debug'); - -import {debugLogger} from '../../../util/debug-logger'; - -describe('util/debug-logger: ', () => { - beforeEach(() => { - debugLogger.overrideConsoleMethods(true); - }); - - afterEach(() => { - logSpy.mockRestore(); - infoSpy.mockRestore(); - warnSpy.mockRestore(); - errorSpy.mockRestore(); - debugSpy.mockRestore(); - }); - - afterEach(() => { - debugLogger.setExecutingPluginName(); - }); - - it('overrides console methods and log messages with INFO level.', () => { - console.log('Starting IF'); - - expect(infoSpy).toHaveBeenCalledWith(expect.stringContaining('INFO:')); - }); - - it('does not override console method if the message starts with `# start`.', () => { - console.log('# start'); - - expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('# start')); - }); - - it('logs messages with WARN level.', () => { - console.warn('Test warn message'); - - expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('WARN:')); - }); - - it('logs messages with ERROR level.', () => { - console.error('Test error message'); - - expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('ERROR:')); - }); - - it('logs messages with DEBUG level.', () => { - console.debug('Test debug message'); - - expect(debugSpy).toHaveBeenCalledWith(expect.stringContaining('DEBUG:')); - }); - - it('includes plugin name in log messages when set.', () => { - debugLogger.setExecutingPluginName('TestPlugin'); - - console.log('Test message with plugin'); - - expect(infoSpy).toHaveBeenCalledWith( - expect.stringContaining('TestPlugin:') - ); - }); - - it('not includes plugin name in log messages when removed.', () => { - debugLogger.setExecutingPluginName(); - - console.log('Test message without plugin'); - - expect(infoSpy).not.toHaveBeenCalledWith( - expect.stringContaining('TestPlugin:') - ); - }); - - it('not logs messages when debugMode is false.', () => { - debugLogger.overrideConsoleMethods(false); - console.log('Test message when debugMode is false'); - - expect(infoSpy).not.toHaveBeenCalled(); - }); - - it('drops off the log message with DEBUG level when the `debug` command is not provided.', () => { - debugLogger.overrideConsoleMethods(false); - console.debug('Test debug message'); - - expect(debugSpy).not.toHaveBeenCalled(); - }); - - it('drops off the log message from the STRINGS when the `debug` command is not provided.', () => { - debugLogger.overrideConsoleMethods(false); - console.info('Starting Impact framework'); - - expect(debugSpy).not.toHaveBeenCalled(); - }); -}); diff --git a/src/__tests__/unit/util/fs.test.ts b/src/__tests__/unit/util/fs.test.ts deleted file mode 100644 index 77b3c0370..000000000 --- a/src/__tests__/unit/util/fs.test.ts +++ /dev/null @@ -1,144 +0,0 @@ -import * as fs from 'fs/promises'; - -import { - getFileName, - isDirectoryExists, - isFileExists, - getYamlFiles, - removeFileIfExists, -} from '../../../util/fs'; - -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -describe('util/fs: ', () => { - describe('isFileExists(): ', () => { - it('returns true if the file exists.', async () => { - const result = await isFileExists('true'); - - expect.assertions(1); - expect(result).toEqual(true); - }); - - it('returns fale if the file does not exist.', async () => { - const result = await isFileExists('false'); - - expect.assertions(1); - expect(result).toEqual(false); - }); - }); - - describe('isDirectoryExists(): ', () => { - it('returns true if directory exists.', async () => { - const result = await isDirectoryExists('true'); - - expect.assertions(1); - expect(result).toEqual(true); - }); - - it('returns false if directory does not exist.', async () => { - const result = await isDirectoryExists('false'); - - expect.assertions(1); - expect(result).toEqual(false); - }); - }); - - describe('getFileName(): ', () => { - it('returns the file name without extension for a file with an extension.', () => { - const filePath = '/path/to/file/example.yaml'; - const result = getFileName(filePath); - - expect.assertions(1); - expect(result).toBe('example'); - }); - - it('returns the file name without extension for a file with multiple dots.', () => { - const filePath = '/path/to/file/example.test.yaml'; - const result = getFileName(filePath); - expect(result).toBe('example.test'); - }); - - it('returns the file name as is if there is no extension.', () => { - const filePath = '/path/to/file/example'; - const result = getFileName(filePath); - expect(result).toBe('example'); - }); - - it('handles file names with special characters.', () => { - const filePath = - '/path/to/file/complex-file.name.with-multiple.parts.yaml'; - const result = getFileName(filePath); - expect(result).toBe('complex-file.name.with-multiple.parts'); - }); - - it('handles file names with no path.', () => { - const filePath = 'example.yaml'; - const result = getFileName(filePath); - expect(result).toBe('example'); - }); - - it('handles empty string as file path.', () => { - const filePath = ''; - const result = getFileName(filePath); - expect(result).toBe(''); - }); - }); - - describe('getYamlFiles(): ', () => { - it('returns an empty array if the directory is empty.', async () => { - const fsReaddirSpy = jest.spyOn(fs, 'readdir'); - const result = await getYamlFiles('/mock-empty-directory'); - - expect(result).toEqual([]); - expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-empty-directory'); - }); - - it('returns YAML files in the directory', async () => { - const fsReaddirSpy = jest.spyOn(fs, 'readdir'); - jest - .spyOn(fs, 'lstat') - .mockResolvedValue({isDirectory: () => false} as any); - - const result = await getYamlFiles('/mock-directory'); - expect.assertions(2); - expect(result).toEqual([ - '/mock-directory/file1.yaml', - '/mock-directory/file2.yml', - ]); - expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); - }); - - it('recursively finds YAML files in nested directories.', async () => { - const fsReaddirSpy = jest.spyOn(fs, 'readdir'); - jest - .spyOn(fs, 'lstat') - .mockResolvedValue({isDirectory: () => false} as any); - const result = await getYamlFiles('/mock-sub-directory'); - - expect.assertions(2); - expect(result).toEqual([ - '/mock-sub-directory/subdir/file2.yml', - '/mock-sub-directory/file1.yaml', - ]); - expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); - }); - }); - - describe('removeFileIfExists(): ', () => { - it('successfully delete file if exists.', async () => { - await isFileExists('true'); - const result = await removeFileIfExists('mock-path'); - - expect.assertions(1); - expect(result).toEqual(undefined); - }); - - it('does not throw an error if the file not exists.', async () => { - await isFileExists('false'); - const result = await removeFileIfExists('mock-path'); - - expect.assertions(1); - expect(result).toEqual(undefined); - }); - }); -}); diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts deleted file mode 100644 index ed46dc0d9..000000000 --- a/src/__tests__/unit/util/helpers.test.ts +++ /dev/null @@ -1,687 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -const mockWarn = jest.fn(); -const mockError = jest.fn(); - -jest.mock('node:readline/promises', () => - require('../../../__mocks__/readline') -); -jest.mock('../../../util/logger', () => ({ - logger: { - warn: mockWarn, - error: mockError, - }, -})); - -jest.mock('path', () => { - const actualPath = jest.requireActual('path') as Record; - return { - __esModule: true, - ...actualPath, - dirname: jest.fn(() => './mock-path'), - }; -}); - -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -jest.mock('../../../lib/load', () => ({ - load: jest.fn(() => { - if (process.env.manifest === 'true') { - return { - rawManifest: { - name: 'divide', - initialize: { - plugins: { - 'cloud-metadata': { - path: '@grnsft/if-plugins', - method: 'CloudMetadata', - }, - divide: { - path: 'builtin', - method: 'Divide', - 'global-config': { - numerator: 'vcpus-allocated', - denominator: 2, - output: 'cpu/number-cores', - }, - }, - }, - }, - execution: { - environment: { - dependencies: [ - '@grnsft/if-core@0.0.7', - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models', - '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', - ], - }, - }, - }, - }; - } - return { - rawManifest: { - initialize: { - plugins: {'@grnsft/if-plugins': '1.0.0'}, - }, - execution: { - environment: { - dependencies: [], - }, - }, - }, - }; - }), -})); - -const initPackage = jest.fn(() => Promise.resolve('mock-path')); -const updatePackage = jest.fn(() => Promise.resolve(true)); -const installdeps = jest.fn(); -const updatedeps = jest.fn(); -jest.mock('../../../util/npm', () => { - const actualNPMUtil = jest.requireActual('../../../util/npm'); - - return { - ...actualNPMUtil, - initPackageJsonIfNotExists: (folderPath: string) => { - if (process.env.NPM_MOCK === 'true') { - return initPackage(); - } - - if (process.env.NPM_MOCK === 'error') { - throw new Error('mock-error'); - } - - return actualNPMUtil.initPackageJsonIfNotExists(folderPath); - }, - updatePackageJsonProperties: ( - newPackageJsonPath: string, - appendDependencies: boolean - ) => { - if (process.env.NPM_MOCK === 'true') { - return updatePackage(); - } - - return actualNPMUtil.updatePackageJsonProperties( - newPackageJsonPath, - appendDependencies - ); - }, - installDependencies: ( - folderPath: string, - dependencies: {[path: string]: string} - ) => { - if (process.env.NPM_MOCK === 'true') { - return installdeps(); - } - - return actualNPMUtil.installDependencies(folderPath, dependencies); - }, - updatePackageJsonDependencies: ( - packageJsonPath: string, - dependencies: any, - cwd: boolean - ) => { - if (process.env.NPM_MOCK === 'true') { - return updatedeps(); - } - - return actualNPMUtil.updatePackageJsonDependencies( - packageJsonPath, - dependencies, - cwd - ); - }, - }; -}); - -import {ERRORS} from '@grnsft/if-core/utils'; - -import { - andHandle, - checkIfEqual, - formatNotMatchingLog, - mergeObjects, - oneIsPrimitive, - parseManifestFromStdin, - getOptionsFromArgs, - addTemplateManifest, - initializeAndInstallLibs, - logStdoutFailMessage, -} from '../../../util/helpers'; -import {CONFIG} from '../../../config'; -import {Difference} from '../../../types/lib/compare'; - -const {IF_ENV} = CONFIG; -const {FAILURE_MESSAGE_DEPENDENCIES, FAILURE_MESSAGE} = IF_ENV; - -const {WriteFileError} = ERRORS; - -describe('util/helpers: ', () => { - describe('andHandle(): ', () => { - afterEach(() => { - mockWarn.mockReset(); - mockError.mockReset(); - }); - - it('logs error in case of error is unknown.', () => { - const message = 'mock-message'; - - andHandle(new WriteFileError(message)); - expect(mockWarn).toHaveBeenCalledTimes(0); - expect(mockError).toHaveBeenCalledTimes(1); - }); - }); - - describe('mergeObjects(): ', () => { - it('does not override input.', () => { - expect.assertions(1); - - const input = { - a: 1, - b: false, - c: 'testInput', - }; - - const defaults = { - c: 'testDefault', - }; - const result = mergeObjects(defaults, input); - - expect(result).toEqual(input); - }); - - it('overrides null/undefined inputs.', () => { - expect.assertions(1); - - const input = { - a: 1, - b: false, - c: 'testInput', - d: null, - e: undefined, - }; - - const defaults = { - c: 'testDefault', - d: 'testDefault', - e: 'testDefault', - }; - const result = mergeObjects(defaults, input); - const expectedResult = { - a: 1, - b: false, - c: 'testInput', - d: 'testDefault', - e: 'testDefault', - }; - - expect(result).toEqual(expectedResult); - }); - - it('adds only properties missing in input.', () => { - expect.assertions(1); - - const input = { - a: 1, - b: false, - c: 'testInput', - }; - - const defaults = { - b: true, - c: 'testDefault', - d: 25, - }; - - const result = mergeObjects(defaults, input); - const expectedResult = { - a: 1, - b: false, - c: 'testInput', - d: 25, - }; - - expect(result).toEqual(expectedResult); - }); - - it('keeps values from input in case of nested objects.', () => { - expect.assertions(1); - - const input = { - a: 1, - b: false, - c: 'testInput', - d: { - e: 1, - }, - }; - - const defaults = { - b: true, - c: 'testDefault1', - d: { - e: 25, - f: 'testDefault2', - }, - }; - - const result = mergeObjects(defaults, input); - const expectedResult = { - a: 1, - b: false, - c: 'testInput', - d: { - e: 1, - }, - }; - - expect(result).toEqual(expectedResult); - }); - - it('keeps value from input in case of arrays.', () => { - expect.assertions(1); - - const input = { - a: 1, - b: false, - c: 'testInput1', - d: [1, 2, 3, 4], - e: 'testInput2', - }; - - const defaults = { - b: true, - c: 'testDefault1', - d: [5, 6, 7, 8, 9], - e: [1, 2, 3], - }; - - const result = mergeObjects(defaults, input); - const expectedResult = { - a: 1, - b: false, - c: 'testInput1', - d: [1, 2, 3, 4], - e: 'testInput2', - }; - - expect(result).toEqual(expectedResult); - }); - }); - - describe('formatNotMatchingLog(): ', () => { - const actualLogger = console.log; - const mockLogger = jest.fn(); - console.log = mockLogger; - - beforeEach(() => { - mockLogger.mockReset(); - }); - - it('logs the message.', () => { - const difference: Difference = { - message: 'mock-message', - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(1); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - }); - - it('logs message and path.', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(2); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - }); - - it('logs message, path and formatted source/target (one is missing).', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: 'mock-source', - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith('target: missing'); - }); - - it('logs message, path and formatted source/target.', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: 'mock-source', - target: 'mock-target', - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); - }); - - it('logs message, path and formatted source/target (numbers).', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: 10, - target: 0, - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); - }); - - it('logs message, path and formatted source/target (booleans).', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: true, - target: false, - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); - }); - - it('logs message, path and formatted source/target (objects).', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: {}, - target: false, - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); - }); - - it('logs message, path and formatted source/target (empty string).', () => { - const difference: Difference = { - message: 'mock-message', - path: 'mock.path', - source: '', - target: false, - }; - - formatNotMatchingLog(difference); - expect(mockLogger).toHaveBeenCalledTimes(4); - expect(mockLogger).toHaveBeenCalledWith(difference.message); - expect(mockLogger).toHaveBeenCalledWith(difference.path); - expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); - expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); - }); - - afterAll(() => { - console.log = actualLogger; - }); - }); - - describe('oneIsPrimitive(): ', () => { - it('returns true if values are nullish.', () => { - const source = null; - const target = undefined; - - const result = oneIsPrimitive(source, target); - expect(result).toBeTruthy(); - }); - - it('returns true if values are string or number.', () => { - const source = 'string'; - const target = 10; - - const result = oneIsPrimitive(source, target); - expect(result).toBeTruthy(); - }); - - it('returns false if one of values is object.', () => { - const source = 'string'; - const target = {}; - - const result = oneIsPrimitive(source, target); - expect(result).toBeFalsy(); - }); - }); - - describe('parseManifestFromStdin(): ', () => { - it('returns empty string if there is no data in stdin.', async () => { - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - }); - - it('returns empty string if nothing is piped.', async () => { - const originalIsTTY = process.stdin.isTTY; - process.stdin.isTTY = true; - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - process.stdin.isTTY = originalIsTTY; - }); - - it('throws error if there is no manifest in stdin.', async () => { - process.env.readline = 'no_manifest'; - expect.assertions(1); - - const response = await parseManifestFromStdin(); - - expect(response).toEqual(''); - }); - - it('returns empty string if there is no data in stdin.', async () => { - process.env.readline = 'manifest'; - const response = await parseManifestFromStdin(); - const expectedMessage = ` -name: mock-name -description: mock-description -`; - - expect(response).toEqual(expectedMessage); - }); - }); - - describe('checkIfEqual(): ', () => { - it('checks if values are equal.', () => { - const a = 'mock'; - const b = 'mock'; - - const response = checkIfEqual(a, b); - expect(response).toBeTruthy(); - }); - - it('returns true if one of the values is wildcard.', () => { - const a = 'mock'; - const b = '*'; - - const response = checkIfEqual(a, b); - expect(response).toBeTruthy(); - }); - - it('returns false for number and string with the same value.', () => { - const a = 5; - const b = '5'; - - const response = checkIfEqual(a, b); - expect(response).toBeFalsy(); - }); - }); - - describe('getOptionsFromArgs(): ', () => { - it('returns the correct options when dependencies are present.', async () => { - const commandArgs = { - manifest: '/path/to/mock-manifest.json', - install: false, - }; - - process.env.manifest = 'true'; - - const result = await getOptionsFromArgs(commandArgs); - expect.assertions(1); - - expect(result).toEqual({ - folderPath: './mock-path', - dependencies: { - '@grnsft/if-plugins': '^v0.3.2', - }, - install: false, - }); - }); - - it('throws an error when there are no dependencies.', async () => { - const commandArgs = { - manifest: '/path/to/mock-manifest.json', - install: false, - }; - - process.env.manifest = 'false'; - - expect.assertions(1); - try { - await getOptionsFromArgs(commandArgs); - } catch (error) { - expect(error).toEqual(new Error(FAILURE_MESSAGE_DEPENDENCIES)); - } - }); - }); - - describe('addTemplateManifest(): ', () => { - it('successfully adds the template manifest to the directory.', async () => { - await addTemplateManifest('./'); - - expect.assertions(1); - }); - - it('throws an error when the manifest is not added into the directory.', async () => { - expect.assertions(1); - - try { - await addTemplateManifest(''); - } catch (error) { - const logSpy = jest.spyOn(global.console, 'log'); - expect(logSpy).toEqual(FAILURE_MESSAGE); - } - }); - }); - - describe('initializeAndInstallLibs(): ', () => { - beforeEach(() => { - initPackage.mockReset(); - updatePackage.mockReset(); - installdeps.mockReset(); - updatedeps.mockReset(); - }); - - it('installs dependencies if install flag is truthy.', async () => { - process.env.NPM_MOCK = 'true'; - // @ts-ignore - process.exit = (code: any) => code; - const options = { - folderPath: 'mock-folderPath', - install: true, - cwd: true, - dependencies: { - mock: 'mock-dependencies', - }, - }; - - expect.assertions(4); - await initializeAndInstallLibs(options); - - expect(initPackage).toHaveBeenCalledTimes(1); - expect(updatePackage).toHaveBeenCalledTimes(1); - expect(installdeps).toHaveBeenCalledTimes(1); - expect(updatedeps).toHaveBeenCalledTimes(0); - }); - - it('updates dependencies if install flag is falsy.', async () => { - process.env.NPM_MOCK = 'true'; - // @ts-ignore - process.exit = (code: any) => code; - const options = { - folderPath: 'mock-folderPath', - install: false, - cwd: true, - dependencies: { - mock: 'mock-dependencies', - }, - }; - - expect.assertions(4); - await initializeAndInstallLibs(options); - - expect(initPackage).toHaveBeenCalledTimes(1); - expect(updatePackage).toHaveBeenCalledTimes(1); - expect(installdeps).toHaveBeenCalledTimes(0); - expect(updatedeps).toHaveBeenCalledTimes(1); - }); - - it('exits process if error is thrown.', async () => { - process.env.NPM_MOCK = 'error'; - const originalProcessExit = process.exit; - const mockExit = jest.fn(); - // @ts-ignore - process.exit = mockExit; - const options = { - folderPath: 'mock-folderPath', - install: false, - cwd: true, - dependencies: { - mock: 'mock-dependencies', - }, - }; - - expect.assertions(5); - await initializeAndInstallLibs(options); - - expect(initPackage).toHaveBeenCalledTimes(0); - expect(updatePackage).toHaveBeenCalledTimes(0); - expect(installdeps).toHaveBeenCalledTimes(0); - expect(updatedeps).toHaveBeenCalledTimes(0); - expect(mockExit).toHaveBeenCalledTimes(1); - - process.exit = originalProcessExit; - }); - }); - - describe('logStdoutFailMessage(): ', () => { - it('successfully logs the failed message.', () => { - const errorMessage = {stdout: '\n\nmock error message'}; - const mockFilename = 'mock-filename.yaml'; - const logSpy = jest.spyOn(global.console, 'log'); - logStdoutFailMessage(errorMessage, mockFilename); - - expect.assertions(2); - - expect(logSpy).toHaveBeenCalledWith( - `✖ if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` - ); - - expect(logSpy).toHaveBeenCalledWith('mock error message'); - }); - }); -}); diff --git a/src/__tests__/unit/util/json.test.ts b/src/__tests__/unit/util/json.test.ts deleted file mode 100644 index 1bb1cd451..000000000 --- a/src/__tests__/unit/util/json.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -import {readAndParseJson} from '../../../util/json'; - -describe('util/json: ', () => { - describe('readAndParseJson(): ', () => { - it('returns file content from path.', async () => { - const path = 'mock/path/json'; - expect.assertions(1); - - const response = await readAndParseJson(path); - expect(response).toEqual(path); - }); - - it('throws error if path does not exist.', async () => { - const path = 'mock/path/json-reject'; - expect.assertions(1); - - try { - await readAndParseJson(path); - } catch (error) { - expect(error).toBeInstanceOf(Error); - } - }); - }); -}); diff --git a/src/__tests__/unit/util/log-memoize.test.ts b/src/__tests__/unit/util/log-memoize.test.ts deleted file mode 100644 index 275ad9c22..000000000 --- a/src/__tests__/unit/util/log-memoize.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {LeveledLogMethod} from 'winston'; -import {memoizedLog} from '../../../util/log-memoize'; - -describe('util/log-memoize: ', () => { - describe('momoizedLog(): ', () => { - it('should call logger.', () => { - const message = 'mock-message'; - const logger = jest.fn( - (message: string) => message - ) as unknown as LeveledLogMethod; - - memoizedLog(logger, message); - - expect(logger).toHaveBeenCalledTimes(1); - - (logger as jest.Mock).mockReset(); - }); - - it('wont call logger since its cached.', () => { - const message = 'mock-message'; - const logger = jest.fn( - (message: string) => message - ) as unknown as LeveledLogMethod; - - memoizedLog(logger, message); - memoizedLog(logger, message); - - expect(logger).toHaveBeenCalledTimes(0); - }); - }); -}); diff --git a/src/__tests__/unit/util/logger.test.ts b/src/__tests__/unit/util/logger.test.ts deleted file mode 100644 index 9eebb4314..000000000 --- a/src/__tests__/unit/util/logger.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {Logger} from 'winston'; - -import {logger} from '../../../util/logger'; - -describe('util/logger: ', () => { - describe('logger(): ', () => { - it('is instance of winston logger.', () => { - expect(logger).toBeInstanceOf(Logger); - }); - }); -}); diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts deleted file mode 100644 index 6d1476b42..000000000 --- a/src/__tests__/unit/util/npm.test.ts +++ /dev/null @@ -1,265 +0,0 @@ -import * as fs from 'fs/promises'; -import * as path from 'path'; - -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -const mockInfo = jest.fn(); - -jest.mock('node:readline/promises', () => - require('../../../__mocks__/readline') -); -jest.mock('../../../util/logger', () => ({ - logger: { - info: mockInfo, - }, -})); - -jest.mock('../../../util/helpers', () => { - const originalModule = jest.requireActual('../../../util/helpers'); - return { - ...originalModule, - execPromise: async (param: any) => { - switch (process.env.NPM_INSTALL) { - case 'true': - expect(param).toEqual('npm install @grnsft/if@0.3.3-beta.0'); - break; - case 'npm init -y': - expect(param).toEqual('npm init -y'); - break; - case 'if-check': - expect(param).toEqual( - "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" - ); - break; - } - return; - }, - }; -}); - -import { - installDependencies, - initPackageJsonIfNotExists, - updatePackageJsonDependencies, - extractPathsWithVersion, - updatePackageJsonProperties, - executeCommands, -} from '../../../util/npm'; -import {isFileExists} from '../../../util/fs'; - -import {STRINGS} from '../../../config/strings'; -import {ManifestPlugin} from '../../../types/npm'; - -const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; - -describe('util/npm: ', () => { - const folderPath = path.resolve(__dirname, 'npm-test'); - - describe('initPackageJsonIfNotExists(): ', () => { - it('initializes package.json if it does not exist.', async () => { - process.env.NPM_INSTALL = 'npm init -y'; - isFileExists('true'); - - await initPackageJsonIfNotExists(folderPath); - - expect.assertions(2); - expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); - }); - - it('returns the package.json path if it exists.', async () => { - const packageJsonPath = path.resolve(folderPath, 'package.json'); - isFileExists('false'); - - const result = await initPackageJsonIfNotExists(folderPath); - - expect.assertions(2); - expect(result).toBe(packageJsonPath); - }); - }); - - describe('installDependencies(): ', () => { - const dependencies = { - '@grnsft/if': '^0.3.3-beta.0', - }; - - it('calls execPromise with the correct arguments.', async () => { - process.env.NPM_INSTALL = 'true'; - expect.assertions(1); - - await installDependencies(folderPath, dependencies); - }); - - it('logs the installation message.', async () => { - const dependencies = { - '@grnsft/if': '^0.3.3-beta.0', - }; - - await installDependencies(folderPath, dependencies); - - expect.assertions(2); - expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); - }); - }); - - describe('updatePackageJsonDependencies(): ', () => { - it('successfully updates the package.json dependencies when cwd is false.', async () => { - const dependencies = { - '@grnsft/if-plugins': '^0.3.3-beta.0', - }; - const packageJsonPath = path.join(folderPath, 'package.json-npm'); - - const expectedPackageJsonContent = JSON.stringify( - { - dependencies: { - '@grnsft/if-plugins': '^0.3.3-beta.0', - }, - }, - null, - 2 - ); - - const fsReadSpy = jest - .spyOn(fs, 'readFile') - .mockResolvedValue(expectedPackageJsonContent); - await updatePackageJsonDependencies(packageJsonPath, dependencies, false); - - expect.assertions(2); - - expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); - }); - - it('successfully updates the package.json dependencies when cwd is true.', async () => { - const dependencies = { - '@grnsft/if-plugins': '^0.3.3-beta.0', - }; - const packageJsonPath = path.join(folderPath, 'package.json-npm'); - - const expectedPackageJsonContent = JSON.stringify( - { - dependencies: { - '@grnsft/if-plugins': '^0.3.3-beta.0', - }, - }, - null, - 2 - ); - - const fsReadSpy = jest - .spyOn(fs, 'readFile') - .mockResolvedValue(expectedPackageJsonContent); - await updatePackageJsonDependencies(packageJsonPath, dependencies, true); - - expect.assertions(2); - - expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); - }); - }); - - describe('extractPathsWithVersion(): ', () => { - it('extracts paths with correct versions.', () => { - const plugins: ManifestPlugin = { - 'cloud-metadata': { - path: '@grnsft/if-plugins', - method: 'CloudMetadata', - }, - divide: { - path: 'builtin', - method: 'Divide', - }, - 'boavizta-cpu': { - path: '@grnsft/if-unofficial-plugins', - method: 'BoaviztaCpuOutput', - }, - }; - const dependencies = [ - '@babel/core@7.22.10', - '@babel/preset-typescript@7.23.3', - '@commitlint/cli@18.6.0', - '@commitlint/config-conventional@18.6.0', - '@grnsft/if-core@0.0.7', - '@grnsft/if-plugins@v0.3.2', - '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', - '@jest/globals@29.7.0', - ]; - - const result = extractPathsWithVersion(plugins, dependencies); - - expect.assertions(1); - expect(result).toEqual({ - '@grnsft/if-plugins': '^v0.3.2', - '@grnsft/if-unofficial-plugins': '^v0.3.0', - }); - }); - - it('returns an empty object if no matches found', () => { - const plugins: ManifestPlugin = { - 'cloud-metadata': { - path: '@grnsft/if-plugins', - method: 'CloudMetadata', - }, - divide: { - path: 'builtin', - method: 'Divide', - }, - 'boavizta-cpu': { - path: '@grnsft/if-unofficial-plugins', - method: 'BoaviztaCpuOutput', - }, - }; - const dependencies = [ - '@babel/core@7.22.10', - '@babel/preset-typescript@7.23.3', - ]; - - expect.assertions(1); - const result = extractPathsWithVersion(plugins, dependencies); - expect(result).toEqual({}); - }); - }); - - describe('updatePackageJsonProperties(): ', () => { - it('updates the package.json properties correctly.', async () => { - const packageJsonPath = path.join(folderPath, 'package.json-npm1'); - - const expectedPackageJsonContent = JSON.stringify( - { - name: 'if-environment', - description: 'mock-description', - author: {}, - bugs: {}, - engines: {}, - homepage: 'mock-homepage', - dependencies: { - '@grnsft/if-plugins': '^0.3.3-beta.0', - }, - }, - null, - 2 - ); - - const fsReadSpy = jest - .spyOn(fs, 'readFile') - .mockResolvedValue(expectedPackageJsonContent); - await updatePackageJsonProperties(packageJsonPath, true); - - expect.assertions(8); - - expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); - }); - }); - - describe('executeCommands(): ', () => { - it('successfully executes with correct commands.', async () => { - process.env.NPM_INSTALL = 'if-check'; - const manifest = './src/__mocks__/mock-manifest.yaml'; - const logSpy = jest.spyOn(global.console, 'log'); - - await executeCommands(manifest, false); - - expect.assertions(2); - expect(logSpy).toHaveBeenCalledWith( - '✔ if-check successfully verified mock-manifest.yaml\n' - ); - }); - }); -}); diff --git a/src/__tests__/unit/util/os-checker.test.ts b/src/__tests__/unit/util/os-checker.test.ts deleted file mode 100644 index d01a7a8da..000000000 --- a/src/__tests__/unit/util/os-checker.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* eslint-disable no-restricted-properties */ -jest.mock('os', () => ({ - platform: () => { - if (process.env.KIND === 'darwin') return 'darwin'; - if (process.env.KIND === 'linux') return 'linux'; - if (process.env.KIND === 'win32') return 'win32'; - - return 'sunos'; - }, - release: () => 'm.m.m', -})); -jest.mock('../../../util/helpers', () => ({ - execPromise: async () => { - if (process.env.KIND === 'darwin' && process.env.REJECT === 'true') - return { - stdout: '', - }; - if (process.env.KIND === 'linux' && process.env.REJECT === 'true') { - return { - stdout: '', - }; - } - if (process.env.KIND === 'win32' && process.env.REJECT === 'true') - return { - stdout: '', - }; - if (process.env.KIND === 'darwin') { - return { - stdout: ` -ProductName: macOS -ProductVersion: 14.3.1 -BuildVersion: 23D60 - `, - }; - } - - if (process.env.KIND === 'linux') { - return { - stdout: ` -Distributor ID: Ubuntu -Description: Ubuntu 22.04.4 LTS -Release: 22.04 -Codename: jammy - `, - }; - } - - if (process.env.KIND === 'win32') { - return { - stdout: ` -OS Name: Microsoft Windows 11 Enterprise -OS Version: 10.0.22631 N/A Build 22631 - `, - }; - } - - return ''; - }, -})); - -import {osInfo} from '../../../util/os-checker'; - -describe('util/os-checker: ', () => { - describe('osInfo(): ', () => { - it('returns object with `os` and `os-version` properties.', async () => { - const response = await osInfo(); - expect.assertions(2); - - expect(response).toHaveProperty('os'); - expect(response).toHaveProperty('os-version'); - }); - - it('returns mac os information.', async () => { - process.env.KIND = 'darwin'; - expect.assertions(1); - - const expectedResponse = { - os: 'macOS', - 'os-version': '14.3.1', - }; - const response = await osInfo(); - expect(response).toEqual(expectedResponse); - }); - - it('returns windows information.', async () => { - process.env.KIND = 'win32'; - expect.assertions(1); - - const expectedResponse = { - os: 'Microsoft Windows 11 Enterprise', - 'os-version': '10.0.22631 N/A Build 22631', - }; - const response = await osInfo(); - expect(response).toEqual(expectedResponse); - }); - - it('returns linux information.', async () => { - process.env.KIND = 'linux'; - expect.assertions(1); - - const expectedResponse = { - os: 'Ubuntu', - 'os-version': '22.04.4 LTS', - }; - const response = await osInfo(); - expect(response).toEqual(expectedResponse); - }); - - it('returns default information.', async () => { - process.env.KIND = 'other'; - expect.assertions(2); - - const response = await osInfo(); - expect(typeof response.os).toEqual('string'); - expect(typeof response['os-version']).toEqual('string'); - }); - - it('returns info from node os on linux.', async () => { - process.env.KIND = 'linux'; - process.env.REJECT = 'true'; - - const response = await osInfo(); - const expectedOS = 'linux'; - const expectedOSVersion = 'm.m.m'; - expect(response.os).toEqual(expectedOS); - expect(response['os-version']).toEqual(expectedOSVersion); - }); - - it('returns info from node os on darwin.', async () => { - process.env.KIND = 'darwin'; - process.env.REJECT = 'true'; - - const response = await osInfo(); - const expectedOS = 'darwin'; - const expectedOSVersion = 'm.m.m'; - expect(response.os).toEqual(expectedOS); - expect(response['os-version']).toEqual(expectedOSVersion); - }); - - it('returns info from node os on win32.', async () => { - process.env.KIND = 'win32'; - process.env.REJECT = 'true'; - - const response = await osInfo(); - const expectedOS = 'win32'; - const expectedOSVersion = 'm.m.m'; - expect(response.os).toEqual(expectedOS); - expect(response['os-version']).toEqual(expectedOSVersion); - }); - }); -}); diff --git a/src/__tests__/unit/util/plugin-storage.test.ts b/src/__tests__/unit/util/plugin-storage.test.ts deleted file mode 100644 index 8b76f36cd..000000000 --- a/src/__tests__/unit/util/plugin-storage.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {pluginStorage} from '../../../util/plugin-storage'; - -const {PluginInitializationError} = ERRORS; - -describe('util/pluginStorage: ', () => { - describe('pluginStorage(): ', () => { - describe('init(): ', () => { - it('should have get and set properties after initalization.', () => { - const storage = pluginStorage(); - - expect(storage).toHaveProperty('get'); - expect(storage).toHaveProperty('set'); - expect(typeof storage.get).toEqual('function'); - expect(typeof storage.set).toEqual('function'); - }); - }); - - const pluginName = 'mock-plugin'; - const pluginBody = { - execute: () => [{}], - metadata: {kind: 'mock-kind'}, - }; - - describe('get(): ', () => { - it('throws error if record is not found.', () => { - const storage = pluginStorage(); - const pluginName = 'mock-plugin'; - - try { - storage.get(pluginName); - } catch (error) { - expect(error).toBeInstanceOf(PluginInitializationError); - - if (error instanceof PluginInitializationError) { - expect(error.message).toEqual; - } - } - }); - - it('gets data if there is stored one.', () => { - const storage = pluginStorage(); - storage.set(pluginName, pluginBody); - - const plugin = storage.get(pluginName); - - expect(plugin).toEqual(pluginBody); - }); - }); - - describe('set(): ', () => { - it('returns storage instance.', () => { - const storage = pluginStorage(); - const instance = storage.set(pluginName, pluginBody); - - expect(instance).toEqual(storage); - }); - - it('stores given data.', () => { - const storage = pluginStorage(); - const instance = storage.set(pluginName, pluginBody); - - expect(instance.get(pluginName)).toEqual(pluginBody); - }); - }); - }); -}); diff --git a/src/__tests__/unit/util/yaml.test.ts b/src/__tests__/unit/util/yaml.test.ts deleted file mode 100644 index 532ff3fd5..000000000 --- a/src/__tests__/unit/util/yaml.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -import { - checkIfFileIsYaml, - openYamlFileAsObject, - saveYamlFileAs, -} from '../../../util/yaml'; - -describe('util/yaml: ', () => { - describe('checkIfFileIsYaml(): ', () => { - it('returns false, in case of not yaml file.', () => { - const fileName = 'mock-filename'; - - const check = checkIfFileIsYaml(fileName); - expect(check).toBeFalsy(); - }); - - it('returns true, in case of `yml` file.', () => { - const fileName = 'mock-filename.yml'; - - const check = checkIfFileIsYaml(fileName); - expect(check).toBeTruthy(); - }); - - it('returns true, in case of `yaml` file.', () => { - const fileName = 'mock-filename.yaml'; - - const check = checkIfFileIsYaml(fileName); - expect(check).toBeTruthy(); - }); - }); - - describe('openYamlFileAsObject(): ', () => { - it('should load and serve yaml as object.', async () => { - expect.assertions(2); - - const result = await openYamlFileAsObject('mock'); - const expectedType = 'object'; - const expectedYamlName = 'gsf-demo'; - - expect(typeof result).toBe(expectedType); - expect(result.name).toBe(expectedYamlName); - }); - }); - - describe('saveYamlFileAs(): ', () => { - it('saves yaml file with passed object and path.', async () => { - const object = { - name: 'mock-name', - }; - const pathToFile = 'mock-pathToFile'; - - await saveYamlFileAs(object, pathToFile); - }); - - it('throws error in case if something wrong with path.', async () => { - const object = { - name: 'mock-name', - }; - const pathToFile = 'reject'; // Mock value for rejection. - - const expectedErrorMessage = 'Wrong file path'; - - try { - await saveYamlFileAs(object, pathToFile); - } catch (error) { - if (error instanceof Error) { - expect(error).toBeInstanceOf(Error); - expect(error.message).toBe(expectedErrorMessage); - } - } - }); - }); -}); From d1772b6a3f8d3bf217d0a95268393f0c85b11458 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:20:08 +0400 Subject: [PATCH 325/863] test(util): init if-run tests --- .../if-run/util/aggregation-helper.test.ts | 100 ++++++++++ src/__tests__/if-run/util/args.test.ts | 187 ++++++++++++++++++ src/__tests__/if-run/util/helpers.test.ts | 169 ++++++++++++++++ src/__tests__/if-run/util/json.test.ts | 26 +++ src/__tests__/if-run/util/log-memoize.test.ts | 32 +++ src/__tests__/if-run/util/os-checker.test.ts | 151 ++++++++++++++ .../if-run/util/plugin-storage.test.ts | 68 +++++++ 7 files changed, 733 insertions(+) create mode 100644 src/__tests__/if-run/util/aggregation-helper.test.ts create mode 100644 src/__tests__/if-run/util/args.test.ts create mode 100644 src/__tests__/if-run/util/helpers.test.ts create mode 100644 src/__tests__/if-run/util/json.test.ts create mode 100644 src/__tests__/if-run/util/log-memoize.test.ts create mode 100644 src/__tests__/if-run/util/os-checker.test.ts create mode 100644 src/__tests__/if-run/util/plugin-storage.test.ts diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts new file mode 100644 index 000000000..78c8c4aeb --- /dev/null +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -0,0 +1,100 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; + +import {STRINGS} from '../../../if-run/config'; + +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; +const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; + +describe('util/aggregation-helper: ', () => { + describe('aggregateInputsIntoOne(): ', () => { + it('throws error if aggregation method is none.', () => { + const inputs: PluginParams[] = []; + const metrics: string[] = ['cpu/number-cores']; + const isTemporal = false; + + expect.assertions(2); + + try { + aggregateInputsIntoOne(inputs, metrics, isTemporal); + } catch (error) { + expect(error).toBeInstanceOf(InvalidAggregationMethodError); + + if (error instanceof InvalidAggregationMethodError) { + expect(error.message).toEqual(INVALID_AGGREGATION_METHOD(metrics[0])); + } + } + }); + + it('throws error if aggregation criteria is not found in input.', () => { + const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; + const metrics: string[] = ['cpu/utilization']; + const isTemporal = false; + + expect.assertions(2); + + try { + aggregateInputsIntoOne(inputs, metrics, isTemporal); + } catch (error) { + expect(error).toBeInstanceOf(MissingAggregationParamError); + + if (error instanceof MissingAggregationParamError) { + expect(error.message).toEqual(METRIC_MISSING(metrics[0], 0)); + } + } + }); + + it('passes `timestamp`, `duration` to aggregator if aggregation is temporal.', () => { + const inputs: PluginParams[] = [ + {timestamp: '', duration: 10, carbon: 10}, + {timestamp: '', duration: 10, carbon: 20}, + ]; + const metrics: string[] = ['carbon']; + const isTemporal = true; + + const expectedValue = { + timestamp: '', + duration: 10, + carbon: inputs[0].carbon + inputs[1].carbon, + }; + const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + expect(aggregated).toEqual(expectedValue); + }); + + it('skips `timestamp`, `duration` if aggregation is not temporal.', () => { + const inputs: PluginParams[] = [ + {timestamp: '', duration: 10, carbon: 10}, + {timestamp: '', duration: 10, carbon: 20}, + ]; + const metrics: string[] = ['carbon']; + const isTemporal = false; + + const expectedValue = { + carbon: inputs[0].carbon + inputs[1].carbon, + }; + const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + expect(aggregated).toEqual(expectedValue); + }); + + it('calculates average of metrics.', () => { + const inputs: PluginParams[] = [ + {timestamp: '', duration: 10, 'cpu/utilization': 10}, + {timestamp: '', duration: 10, 'cpu/utilization': 90}, + ]; + const metrics: string[] = ['cpu/utilization']; + const isTemporal = false; + + const expectedValue = { + 'cpu/utilization': + (inputs[0]['cpu/utilization'] + inputs[1]['cpu/utilization']) / + inputs.length, + }; + const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + expect(aggregated).toEqual(expectedValue); + expect(aggregated.timestamp).toBeUndefined(); + expect(aggregated.duration).toBeUndefined(); + }); + }); +}); diff --git a/src/__tests__/if-run/util/args.test.ts b/src/__tests__/if-run/util/args.test.ts new file mode 100644 index 000000000..62b0bf922 --- /dev/null +++ b/src/__tests__/if-run/util/args.test.ts @@ -0,0 +1,187 @@ +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + case 'throw-error-object': + throw new Error(MANIFEST_IS_MISSING); + case 'error': + throw MANIFEST_IS_MISSING; + case 'manifest-is-missing': + return {}; + case 'manifest': + return { + manifest: 'manifest-mock.yml', + }; + case 'absolute-path': + return { + manifest: path.normalize(`${processRunningPath}/manifest-mock.yml`), + }; + case 'manifest-output': + return { + manifest: 'manifest-mock.yml', + output: 'output-mock.yml', + }; + case 'override-params': + return { + manifest: 'manifest-mock.yml', + 'override-params': 'override-params-mock.yml', + }; + case 'not-yaml': + return { + manifest: 'mock.notyaml', + }; + case 'stdout': + return { + manifest: 'manifest-mock.yaml', + stdout: true, + }; + default: + return { + manifest: 'mock-manifest.yaml', + output: 'mock-output', + }; + } + }, +})); + +const processRunningPath = process.cwd(); +import * as path from 'node:path'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {parseIfRunProcessArgs} from '../../../if-run/util/args'; + +import {STRINGS as COMMON_STRINGS} from '../../../common/config'; + +const {SOURCE_IS_NOT_YAML, MANIFEST_IS_MISSING} = COMMON_STRINGS; +const {CliSourceFileError, ParseCliParamsError} = ERRORS; + +describe('if-run/util/args: ', () => { + describe('parseIfRunProcessArgs(): ', () => { + it('throws error if there is no argument passed.', () => { + expect.assertions(4); + + process.env.result = 'error'; // used for mocking + + try { + parseIfRunProcessArgs(); + } catch (error) { + expect(error).toEqual(MANIFEST_IS_MISSING); + } + + process.env.result = 'throw-error-object'; + + try { + parseIfRunProcessArgs(); + } catch (error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_IS_MISSING)); + } + + process.env.result = 'manifest-is-missing'; + + try { + parseIfRunProcessArgs(); + } catch (error) { + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(MANIFEST_IS_MISSING)); + } + }); + + it('returns manifest path.', () => { + expect.assertions(1); + + process.env.result = 'manifest'; + + const result = parseIfRunProcessArgs(); + const manifestPath = 'manifest-mock.yml'; + const expectedResult = { + inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), + outputOptions: { + stdout: undefined, + }, + }; + + expect(result).toEqual(expectedResult); + }); + + it('returns manifest with absolute path.', () => { + expect.assertions(1); + + process.env.result = 'absolute-path'; + + const result = parseIfRunProcessArgs(); + const manifestPath = 'manifest-mock.yml'; + const expectedResult = { + inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), + outputOptions: {}, + }; + + expect(result).toEqual(expectedResult); + }); + + it('returns manifest with `paramPath`.', () => { + expect.assertions(1); + + process.env.result = 'override-params'; + + const result = parseIfRunProcessArgs(); + const manifestPath = 'manifest-mock.yml'; + const expectedResult = { + inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), + paramPath: 'override-params-mock.yml', + outputOptions: {}, + }; + + expect(result).toEqual(expectedResult); + }); + + it('returns manifest and output path.', () => { + expect.assertions(1); + + process.env.result = 'manifest-output'; + + const result = parseIfRunProcessArgs(); + const manifestPath = 'manifest-mock.yml'; + const outputPath = 'output-mock.yml'; + const expectedResult = { + inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), + outputOptions: { + outputPath: path.normalize(`${processRunningPath}/${outputPath}`), + stdout: undefined, + }, + }; + + expect(result).toEqual(expectedResult); + }); + + it('throws error if file is not yaml.', () => { + expect.assertions(2); + + process.env.result = 'not-yaml'; + + try { + parseIfRunProcessArgs(); + } catch (error) { + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + }); + + it('returns stdout and manifest.', () => { + expect.assertions(1); + + process.env.result = 'stdout'; + const manifestPath = 'manifest-mock.yaml'; + + const response = parseIfRunProcessArgs(); + const expectedResult = { + inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), + outputOptions: { + stdout: true, + }, + }; + + expect(response).toEqual(expectedResult); + }); + }); +}); diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts new file mode 100644 index 000000000..35b60a01b --- /dev/null +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -0,0 +1,169 @@ +const mockWarn = jest.fn(); +const mockError = jest.fn(); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {andHandle, mergeObjects} from '../../../if-run/util/helpers'; + +const {WriteFileError} = ERRORS; + +jest.mock('../../../common/util/logger', () => ({ + logger: { + warn: mockWarn, + error: mockError, + }, +})); + +describe('if-run/util/helpers: ', () => { + describe('andHandle(): ', () => { + afterEach(() => { + mockWarn.mockReset(); + mockError.mockReset(); + }); + + it('logs error in case of error is unknown.', () => { + const message = 'mock-message'; + + andHandle(new WriteFileError(message)); + expect(mockWarn).toHaveBeenCalledTimes(0); + expect(mockError).toHaveBeenCalledTimes(1); + }); + }); + + describe('mergeObjects(): ', () => { + it('does not override input.', () => { + expect.assertions(1); + + const input = { + a: 1, + b: false, + c: 'testInput', + }; + + const defaults = { + c: 'testDefault', + }; + const result = mergeObjects(defaults, input); + + expect(result).toEqual(input); + }); + + it('overrides null/undefined inputs.', () => { + expect.assertions(1); + + const input = { + a: 1, + b: false, + c: 'testInput', + d: null, + e: undefined, + }; + + const defaults = { + c: 'testDefault', + d: 'testDefault', + e: 'testDefault', + }; + const result = mergeObjects(defaults, input); + const expectedResult = { + a: 1, + b: false, + c: 'testInput', + d: 'testDefault', + e: 'testDefault', + }; + + expect(result).toEqual(expectedResult); + }); + + it('adds only properties missing in input.', () => { + expect.assertions(1); + + const input = { + a: 1, + b: false, + c: 'testInput', + }; + + const defaults = { + b: true, + c: 'testDefault', + d: 25, + }; + + const result = mergeObjects(defaults, input); + const expectedResult = { + a: 1, + b: false, + c: 'testInput', + d: 25, + }; + + expect(result).toEqual(expectedResult); + }); + + it('keeps values from input in case of nested objects.', () => { + expect.assertions(1); + + const input = { + a: 1, + b: false, + c: 'testInput', + d: { + e: 1, + }, + }; + + const defaults = { + b: true, + c: 'testDefault1', + d: { + e: 25, + f: 'testDefault2', + }, + }; + + const result = mergeObjects(defaults, input); + const expectedResult = { + a: 1, + b: false, + c: 'testInput', + d: { + e: 1, + }, + }; + + expect(result).toEqual(expectedResult); + }); + + it('keeps value from input in case of arrays.', () => { + expect.assertions(1); + + const input = { + a: 1, + b: false, + c: 'testInput1', + d: [1, 2, 3, 4], + e: 'testInput2', + }; + + const defaults = { + b: true, + c: 'testDefault1', + d: [5, 6, 7, 8, 9], + e: [1, 2, 3], + }; + + const result = mergeObjects(defaults, input); + const expectedResult = { + a: 1, + b: false, + c: 'testInput1', + d: [1, 2, 3, 4], + e: 'testInput2', + }; + + expect(result).toEqual(expectedResult); + }); + }); +}); diff --git a/src/__tests__/if-run/util/json.test.ts b/src/__tests__/if-run/util/json.test.ts new file mode 100644 index 000000000..5836c677a --- /dev/null +++ b/src/__tests__/if-run/util/json.test.ts @@ -0,0 +1,26 @@ +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +import {readAndParseJson} from '../../../if-run/util/json'; + +describe('util/json: ', () => { + describe('readAndParseJson(): ', () => { + it('returns file content from path.', async () => { + const path = 'mock/path/json'; + expect.assertions(1); + + const response = await readAndParseJson(path); + expect(response).toEqual(path); + }); + + it('throws error if path does not exist.', async () => { + const path = 'mock/path/json-reject'; + expect.assertions(1); + + try { + await readAndParseJson(path); + } catch (error) { + expect(error).toBeInstanceOf(Error); + } + }); + }); +}); diff --git a/src/__tests__/if-run/util/log-memoize.test.ts b/src/__tests__/if-run/util/log-memoize.test.ts new file mode 100644 index 000000000..a5d73b15b --- /dev/null +++ b/src/__tests__/if-run/util/log-memoize.test.ts @@ -0,0 +1,32 @@ +import {LeveledLogMethod} from 'winston'; + +import {memoizedLog} from '../../../if-run/util/log-memoize'; + +describe('util/log-memoize: ', () => { + describe('momoizedLog(): ', () => { + it('should call logger.', () => { + const message = 'mock-message'; + const logger = jest.fn( + (message: string) => message + ) as unknown as LeveledLogMethod; + + memoizedLog(logger, message); + + expect(logger).toHaveBeenCalledTimes(1); + + (logger as jest.Mock).mockReset(); + }); + + it('wont call logger since its cached.', () => { + const message = 'mock-message'; + const logger = jest.fn( + (message: string) => message + ) as unknown as LeveledLogMethod; + + memoizedLog(logger, message); + memoizedLog(logger, message); + + expect(logger).toHaveBeenCalledTimes(0); + }); + }); +}); diff --git a/src/__tests__/if-run/util/os-checker.test.ts b/src/__tests__/if-run/util/os-checker.test.ts new file mode 100644 index 000000000..20d5ffea0 --- /dev/null +++ b/src/__tests__/if-run/util/os-checker.test.ts @@ -0,0 +1,151 @@ +/* eslint-disable no-restricted-properties */ +jest.mock('os', () => ({ + platform: () => { + if (process.env.KIND === 'darwin') return 'darwin'; + if (process.env.KIND === 'linux') return 'linux'; + if (process.env.KIND === 'win32') return 'win32'; + + return 'sunos'; + }, + release: () => 'm.m.m', +})); +jest.mock('../../../common/util/helpers', () => ({ + execPromise: async () => { + if (process.env.KIND === 'darwin' && process.env.REJECT === 'true') + return { + stdout: '', + }; + if (process.env.KIND === 'linux' && process.env.REJECT === 'true') { + return { + stdout: '', + }; + } + if (process.env.KIND === 'win32' && process.env.REJECT === 'true') + return { + stdout: '', + }; + if (process.env.KIND === 'darwin') { + return { + stdout: ` +ProductName: macOS +ProductVersion: 14.3.1 +BuildVersion: 23D60 + `, + }; + } + + if (process.env.KIND === 'linux') { + return { + stdout: ` +Distributor ID: Ubuntu +Description: Ubuntu 22.04.4 LTS +Release: 22.04 +Codename: jammy + `, + }; + } + + if (process.env.KIND === 'win32') { + return { + stdout: ` +OS Name: Microsoft Windows 11 Enterprise +OS Version: 10.0.22631 N/A Build 22631 + `, + }; + } + + return ''; + }, +})); + +import {osInfo} from '../../../if-run/util/os-checker'; + +describe('util/os-checker: ', () => { + describe('osInfo(): ', () => { + it('returns object with `os` and `os-version` properties.', async () => { + const response = await osInfo(); + expect.assertions(2); + + expect(response).toHaveProperty('os'); + expect(response).toHaveProperty('os-version'); + }); + + it('returns mac os information.', async () => { + process.env.KIND = 'darwin'; + expect.assertions(1); + + const expectedResponse = { + os: 'macOS', + 'os-version': '14.3.1', + }; + const response = await osInfo(); + expect(response).toEqual(expectedResponse); + }); + + it('returns windows information.', async () => { + process.env.KIND = 'win32'; + expect.assertions(1); + + const expectedResponse = { + os: 'Microsoft Windows 11 Enterprise', + 'os-version': '10.0.22631 N/A Build 22631', + }; + const response = await osInfo(); + expect(response).toEqual(expectedResponse); + }); + + it('returns linux information.', async () => { + process.env.KIND = 'linux'; + expect.assertions(1); + + const expectedResponse = { + os: 'Ubuntu', + 'os-version': '22.04.4 LTS', + }; + const response = await osInfo(); + expect(response).toEqual(expectedResponse); + }); + + it('returns default information.', async () => { + process.env.KIND = 'other'; + expect.assertions(2); + + const response = await osInfo(); + expect(typeof response.os).toEqual('string'); + expect(typeof response['os-version']).toEqual('string'); + }); + + it('returns info from node os on linux.', async () => { + process.env.KIND = 'linux'; + process.env.REJECT = 'true'; + + const response = await osInfo(); + const expectedOS = 'linux'; + const expectedOSVersion = 'm.m.m'; + expect(response.os).toEqual(expectedOS); + expect(response['os-version']).toEqual(expectedOSVersion); + }); + + it('returns info from node os on darwin.', async () => { + process.env.KIND = 'darwin'; + process.env.REJECT = 'true'; + + const response = await osInfo(); + const expectedOS = 'darwin'; + const expectedOSVersion = 'm.m.m'; + expect(response.os).toEqual(expectedOS); + expect(response['os-version']).toEqual(expectedOSVersion); + }); + + it('returns info from node os on win32.', async () => { + process.env.KIND = 'win32'; + process.env.REJECT = 'true'; + + const response = await osInfo(); + const expectedOS = 'win32'; + const expectedOSVersion = 'm.m.m'; + expect(response.os).toEqual(expectedOS); + expect(response['os-version']).toEqual(expectedOSVersion); + }); + }); +}); diff --git a/src/__tests__/if-run/util/plugin-storage.test.ts b/src/__tests__/if-run/util/plugin-storage.test.ts new file mode 100644 index 000000000..885ccb107 --- /dev/null +++ b/src/__tests__/if-run/util/plugin-storage.test.ts @@ -0,0 +1,68 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {pluginStorage} from '../../../if-run/util/plugin-storage'; + +const {PluginInitializationError} = ERRORS; + +describe('util/pluginStorage: ', () => { + describe('pluginStorage(): ', () => { + describe('init(): ', () => { + it('should have get and set properties after initalization.', () => { + const storage = pluginStorage(); + + expect(storage).toHaveProperty('get'); + expect(storage).toHaveProperty('set'); + expect(typeof storage.get).toEqual('function'); + expect(typeof storage.set).toEqual('function'); + }); + }); + + const pluginName = 'mock-plugin'; + const pluginBody = { + execute: () => [{}], + metadata: {kind: 'mock-kind'}, + }; + + describe('get(): ', () => { + it('throws error if record is not found.', () => { + const storage = pluginStorage(); + const pluginName = 'mock-plugin'; + + try { + storage.get(pluginName); + } catch (error) { + expect(error).toBeInstanceOf(PluginInitializationError); + + if (error instanceof PluginInitializationError) { + expect(error.message).toEqual; + } + } + }); + + it('gets data if there is stored one.', () => { + const storage = pluginStorage(); + storage.set(pluginName, pluginBody); + + const plugin = storage.get(pluginName); + + expect(plugin).toEqual(pluginBody); + }); + }); + + describe('set(): ', () => { + it('returns storage instance.', () => { + const storage = pluginStorage(); + const instance = storage.set(pluginName, pluginBody); + + expect(instance).toEqual(storage); + }); + + it('stores given data.', () => { + const storage = pluginStorage(); + const instance = storage.set(pluginName, pluginBody); + + expect(instance.get(pluginName)).toEqual(pluginBody); + }); + }); + }); +}); From 3037b5f5aa3bde4419cf7e91363f347491d9ebf0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:20:22 +0400 Subject: [PATCH 326/863] test(lib): init if-run tests --- src/__tests__/if-run/lib/aggregate.test.ts | 202 +++++++++++++++ src/__tests__/if-run/lib/compute.test.ts | 237 ++++++++++++++++++ src/__tests__/if-run/lib/environment.test.ts | 36 +++ src/__tests__/if-run/lib/exhaust.test.ts | 91 +++++++ src/__tests__/if-run/lib/initialize.test.ts | 182 ++++++++++++++ src/__tests__/if-run/lib/parameterize.test.ts | 114 +++++++++ 6 files changed, 862 insertions(+) create mode 100644 src/__tests__/if-run/lib/aggregate.test.ts create mode 100644 src/__tests__/if-run/lib/compute.test.ts create mode 100644 src/__tests__/if-run/lib/environment.test.ts create mode 100644 src/__tests__/if-run/lib/exhaust.test.ts create mode 100644 src/__tests__/if-run/lib/initialize.test.ts create mode 100644 src/__tests__/if-run/lib/parameterize.test.ts diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts new file mode 100644 index 000000000..76de6300c --- /dev/null +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -0,0 +1,202 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +import {aggregate} from '../../../if-run/lib/aggregate'; + +describe('lib/aggregate: ', () => { + describe('aggregate(): ', () => { + it('returns tree if aggregation is missing.', () => { + const tree = {}; + const aggregation = undefined; + + const aggregatedTree = aggregate(tree, aggregation); + expect(aggregatedTree).toEqual(tree); + }); + + it('returns tree if aggregation.type is missing.', () => { + const tree = {}; + const aggregation = { + metrics: [], + }; + + // @ts-ignore + const aggregatedTree = aggregate(tree, aggregation); + expect(aggregatedTree).toEqual(tree); + }); + + it('does horizontal aggregation.', () => { + const tree = { + children: { + mocks: { + outputs: [ + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + ], + }, + }, + }; + + const aggregatedTree = aggregate(tree, { + metrics: ['carbon'], + type: 'horizontal', + }); + const expectedAggregated = { + carbon: + tree.children.mocks.outputs[0].carbon + + tree.children.mocks.outputs[1].carbon, + }; + expect(aggregatedTree.children.mocks.aggregated).toEqual( + expectedAggregated + ); + }); + + it('does vertical aggregation.', () => { + const tree = { + children: { + 'mocks-1': { + outputs: [ + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + ], + }, + 'mocks-2': { + outputs: [ + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 20, + }, + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 20, + }, + ], + }, + }, + }; + + const aggregatedTree = aggregate(tree, { + metrics: ['carbon'], + type: 'vertical', + }); + const expectedOutputs = [ + { + carbon: 30, + timestamp: 'mock-timestamp', + duration: 'mock-duration', + }, + { + carbon: 30, + timestamp: 'mock-timestamp', + duration: 'mock-duration', + }, + ]; + const expectedAggregated = { + carbon: + tree.children['mocks-1'].outputs[0].carbon + + tree.children['mocks-2'].outputs[0].carbon + + tree.children['mocks-1'].outputs[1].carbon + + tree.children['mocks-2'].outputs[1].carbon, + }; + expect(aggregatedTree.outputs).toEqual(expectedOutputs); + expect(aggregatedTree.aggregated).toEqual(expectedAggregated); + }); + + it('does both aggregations.', () => { + const tree = { + children: { + 'mocks-1': { + outputs: [ + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 10, + }, + ], + }, + 'mocks-2': { + outputs: [ + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 20, + }, + { + timestamp: 'mock-timestamp', + duration: 'mock-duration', + carbon: 20, + }, + ], + }, + }, + }; + + const aggregatedTree = aggregate(tree, { + metrics: ['carbon'], + type: 'both', + }); + + // horizontal aggregation + const expectedNode1Horizontal = { + carbon: + tree.children['mocks-1'].outputs[0].carbon + + tree.children['mocks-1'].outputs[1].carbon, + }; + expect(aggregatedTree.children['mocks-1'].aggregated).toEqual( + expectedNode1Horizontal + ); + const expectedNode2Horizontal = { + carbon: + tree.children['mocks-2'].outputs[0].carbon + + tree.children['mocks-2'].outputs[1].carbon, + }; + expect(aggregatedTree.children['mocks-2'].aggregated).toEqual( + expectedNode2Horizontal + ); + + // vertical aggregation + const expectedOutputs = [ + { + carbon: 30, + timestamp: 'mock-timestamp', + duration: 'mock-duration', + }, + { + carbon: 30, + timestamp: 'mock-timestamp', + duration: 'mock-duration', + }, + ]; + expect(aggregatedTree.outputs).toEqual(expectedOutputs); + const expectedAggregated = { + carbon: + tree.children['mocks-1'].outputs[0].carbon + + tree.children['mocks-2'].outputs[0].carbon + + tree.children['mocks-1'].outputs[1].carbon + + tree.children['mocks-2'].outputs[1].carbon, + }; + expect(aggregatedTree.aggregated).toEqual(expectedAggregated); + }); + }); +}); diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts new file mode 100644 index 000000000..4ed48b5a5 --- /dev/null +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -0,0 +1,237 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +import {compute} from '../../../if-run/lib/compute'; +import {ComputeParams} from '../../../if-run/types/compute'; +import {pluginStorage} from '../../../if-run/util/plugin-storage'; + +describe('lib/compute: ', () => { + /** + * Mock plugins. + */ + const mockExecutePlugin = () => ({ + execute: (inputs: any) => + inputs.map((input: any) => { + input.newField = 'mock-newField'; + + return input; + }), + metadata: { + kind: 'execute', + }, + }); + const mockGroupByPlugin = () => ({ + execute: (inputs: any) => ({children: inputs}), + metadata: { + kind: 'groupby', + }, + }); + /** + * Compute params. + */ + const paramsExecute: ComputeParams = { + // @ts-ignore + context: { + name: 'mock-name', + initialize: { + plugins: { + mock: { + path: 'mockavizta', + method: 'Mockavizta', + }, + }, + }, + }, + pluginStorage: pluginStorage().set('mock', mockExecutePlugin()), + }; + const params: ComputeParams = { + // @ts-ignore + context: { + name: 'mock-name', + initialize: { + plugins: { + mock: { + path: 'mockavizta', + method: 'Mockavizta', + }, + }, + }, + }, + pluginStorage: pluginStorage().set('mock', mockGroupByPlugin()), + }; + + describe('compute(): ', () => { + it('computes simple tree with execute plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + }, + }; + + const response = await compute(tree, paramsExecute); + const expectedResult = mockExecutePlugin().execute( + tree.children.mockChild.inputs + ); + + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); + + it('computes simple tree with groupby plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + }, + }; + const response = await compute(tree, params); + const expectedResult = mockGroupByPlugin().execute( + tree.children.mockChild.inputs + ); + + expect(response.children.mockChild.children).toEqual(expectedResult); + }); + + it('computes simple tree with defaults and execute plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + defaults: { + 'cpu/name': 'Intel CPU', + }, + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResult = mockExecutePlugin().execute( + tree.children.mockChild.inputs.map((input: any) => { + input['cpu/name'] = 'Intel CPU'; + + return input; + }) + ); + + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); + + it('computes nested tree with defaults and execute plugin.', async () => { + const tree = { + children: { + mockChild1: { + pipeline: ['mock'], + defaults: { + 'cpu/name': 'Intel CPU', + }, + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + mockChild2: { + children: { + mockChild21: { + pipeline: ['mock'], + defaults: { + 'cpu/name': 'Intel CPU', + }, + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + }, + }, + }, + }; + const response = await compute(tree, paramsExecute); + + const mapper = (input: any) => { + input['cpu/name'] = 'Intel CPU'; + + return input; + }; + const expectedResult1 = mockExecutePlugin().execute( + tree.children.mockChild1.inputs.map(mapper) + ); + const expectedResult21 = mockExecutePlugin().execute( + tree.children.mockChild2.children.mockChild21.inputs.map(mapper) + ); + + expect(response.children.mockChild1.outputs).toEqual(expectedResult1); + expect(response.children.mockChild2.children.mockChild21.outputs).toEqual( + expectedResult21 + ); + }); + + it('computes simple tree with no defaults and no inputs with execue plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + defaults: {}, + inputs: [], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResult: any[] = []; + + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); + + it('computes simple tree with defaults and no inputs with execue plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + defaults: { + carbon: 10, + }, + input: [], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResult: any[] = [{carbon: 10, newField: 'mock-newField'}]; + + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); + + it('computes simple tree with node config and execute plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + config: { + 'cpu/name': 'Intel CPU', + }, + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResult = mockExecutePlugin().execute( + tree.children.mockChild.inputs + ); + + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); + }); +}); diff --git a/src/__tests__/if-run/lib/environment.test.ts b/src/__tests__/if-run/lib/environment.test.ts new file mode 100644 index 000000000..90d575e3e --- /dev/null +++ b/src/__tests__/if-run/lib/environment.test.ts @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +import {injectEnvironment} from '../../../if-run/lib/environment'; + +describe('lib/envirnoment: ', () => { + describe('injectEnvironment(): ', () => { + const context = {}; + + it('checks response to have `execution` property.', async () => { + // @ts-ignore + const response = await injectEnvironment(context); + expect(response).toHaveProperty('execution'); + }); + + it('checks `execution` to have `command` and `environment` props.', async () => { + // @ts-ignore + const response = await injectEnvironment(context); + const {execution} = response; + + expect(execution).toHaveProperty('command'); + expect(execution).toHaveProperty('environment'); + }); + + it('checks environment response type.', async () => { + // @ts-ignore + const response = await injectEnvironment(context); + const environment = response.execution!.environment!; + + expect(typeof environment['date-time']).toEqual('string'); + expect(Array.isArray(environment.dependencies)).toBeTruthy(); + expect(typeof environment['node-version']).toEqual('string'); + expect(typeof environment.os).toEqual('string'); + expect(typeof environment['os-version']).toEqual('string'); + }); + }); +}); diff --git a/src/__tests__/if-run/lib/exhaust.test.ts b/src/__tests__/if-run/lib/exhaust.test.ts new file mode 100644 index 000000000..b2be6ebcc --- /dev/null +++ b/src/__tests__/if-run/lib/exhaust.test.ts @@ -0,0 +1,91 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +jest.mock('fs', () => require('../../../__mocks__/fs')); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../../if-run/config'; +import {exhaust} from '../../../if-run/lib/exhaust'; + +const {ExhaustOutputArgError, InvalidExhaustPluginError} = ERRORS; +const {INVALID_EXHAUST_PLUGIN, OUTPUT_REQUIRED} = STRINGS; + +describe('lib/exhaust: ', () => { + describe('exhaust(): ', () => { + const spy = jest.spyOn(global.console, 'log'); + + beforeEach(() => { + spy.mockReset(); + }); + + it('returns void if no exhaust plugin selected.', async () => { + const tree = {}; + const context = { + initialize: { + outputs: null, + }, + }; + + // @ts-ignore + const result = await exhaust(tree, context, {}); + + expect(result).toBeUndefined(); + }); + + it('uses log exhaust plugin as export.', async () => { + const tree = {}; + const context = { + initialize: {}, + }; + + // @ts-ignore + await exhaust(tree, context, {stdout: true}); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('rejects with cli input error if output path is not provided with yaml.', async () => { + const tree = {}; + const context = { + initialize: { + outputs: ['yaml'], + }, + }; + + expect.assertions(2); + + try { + // @ts-ignore + await exhaust(tree, context, {}); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + + if (error instanceof ExhaustOutputArgError) { + expect(error.message).toEqual(OUTPUT_REQUIRED); + } + } + }); + + it('rejects with module init error if output module is not supported.', async () => { + const tree = {}; + const context = { + initialize: { + outputs: ['mock'], + }, + }; + + expect.assertions(2); + + try { + // @ts-ignore + await exhaust(tree, context, {}); + } catch (error) { + expect(error).toBeInstanceOf(InvalidExhaustPluginError); + + if (error instanceof InvalidExhaustPluginError) { + expect(error.message).toEqual( + INVALID_EXHAUST_PLUGIN(context.initialize.outputs[0]) + ); + } + } + }); + }); +}); diff --git a/src/__tests__/if-run/lib/initialize.test.ts b/src/__tests__/if-run/lib/initialize.test.ts new file mode 100644 index 000000000..f00142260 --- /dev/null +++ b/src/__tests__/if-run/lib/initialize.test.ts @@ -0,0 +1,182 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +jest.mock('mockavizta', () => require('../../../__mocks__/plugin'), { + virtual: true, +}); +jest.mock( + '../../../if-run/builtins', + () => require('../../../__mocks__/plugin'), + { + virtual: true, + } +); +const mockLog = jest.fn(); +jest.mock('../../../if-run/util/log-memoize', () => ({ + memoizedLog: mockLog, +})); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {initialize} from '../../../if-run/lib/initialize'; +import {STRINGS} from '../../../if-run/config'; +import {GlobalPlugins} from '../../../common/types/manifest'; + +const { + MissingPluginPathError, + MissingPluginMethodError, + PluginInitializationError, +} = ERRORS; +const {MISSING_METHOD, MISSING_PATH, INVALID_MODULE_PATH} = STRINGS; + +describe('lib/initalize: ', () => { + describe('initalize(): ', () => { + it('creates instance with get and set methods.', async () => { + const plugins = {}; + const response = await initialize(plugins); + + expect(response).toHaveProperty('get'); + expect(response).toHaveProperty('set'); + expect(typeof response.get).toEqual('function'); + expect(typeof response.set).toEqual('function'); + }); + + it('checks if plugin is initalized, warning is logged and plugin has execute and metadata props.', async () => { + const plugins: GlobalPlugins = { + mockavizta: { + path: 'mockavizta', + method: 'Mockavizta', + }, + }; + const storage = await initialize(plugins); + + const pluginName = Object.keys(plugins)[0]; + const module = storage.get(pluginName); + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + expect(mockLog).toHaveBeenCalledTimes(1); // checks if logger is called + }); + + it('checks if plugin is initalized with global config and has execute and metadata.', async () => { + const plugins: GlobalPlugins = { + mockavizta: { + path: 'mockavizta', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + const storage = await initialize(plugins); + + const pluginName = Object.keys(plugins)[0]; + const module = storage.get(pluginName); + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + }); + + it('throws error if plugin does not have path property.', async () => { + const plugins: GlobalPlugins = { + // @ts-ignore + mockavizta: { + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + + try { + await initialize(plugins); + } catch (error) { + expect(error).toBeInstanceOf(MissingPluginPathError); + + if (error instanceof MissingPluginPathError) { + expect(error.message).toEqual(MISSING_PATH); + } + } + }); + + it('throws error if plugin does not have path property.', async () => { + const plugins: GlobalPlugins = { + // @ts-ignore + mockavizta: { + path: 'mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + + try { + await initialize(plugins); + } catch (error) { + expect(error).toBeInstanceOf(MissingPluginMethodError); + + if (error instanceof MissingPluginMethodError) { + expect(error.message).toEqual(MISSING_METHOD); + } + } + }); + + it('checks if builtin plugin is initalized.', async () => { + const plugins: GlobalPlugins = { + mockavizta: { + path: 'builtin', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + const storage = await initialize(plugins); + + const pluginName = Object.keys(plugins)[0]; + const module = storage.get(pluginName); + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + }); + + it('checks if github plugin is initalized.', async () => { + const plugins: GlobalPlugins = { + mockavizta: { + path: 'https://github.com/mockavizta', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + const storage = await initialize(plugins); + + const pluginName = Object.keys(plugins)[0]; + const module = storage.get(pluginName); + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + }); + + it('throws error if plugin path is invalid.', async () => { + const plugins: GlobalPlugins = { + mockavizta: { + path: 'failing-mock', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, + }; + + try { + await initialize(plugins); + } catch (error: any) { + expect(error).toBeInstanceOf(PluginInitializationError); + expect(error.message).toEqual( + INVALID_MODULE_PATH( + plugins.mockavizta.path, + new Error( + "Cannot find module 'failing-mock' from 'src/if-run/lib/initialize.ts'" + ) + ) + ); + } + }); + }); +}); diff --git a/src/__tests__/if-run/lib/parameterize.test.ts b/src/__tests__/if-run/lib/parameterize.test.ts new file mode 100644 index 000000000..ed3a4b948 --- /dev/null +++ b/src/__tests__/if-run/lib/parameterize.test.ts @@ -0,0 +1,114 @@ +import {LeveledLogMethod} from 'winston'; + +const mockLog = jest.fn((message: string) => message); + +jest.mock('../../../if-run/util/log-memoize', () => ({ + memoizedLog: mockLog, +})); +jest.mock('../../../common/util/logger', () => ({ + logger: { + warn: mockLog, + debug: mockLog, + }, +})); + +import {PARAMETERS} from '../../../if-run/config'; +import {parameterize} from '../../../if-run/lib/parameterize'; + +import {STRINGS} from '../../../if-run/config'; + +import {ManifestParameter} from '../../../common/types/manifest'; + +const {REJECTING_OVERRIDE, CHECKING_AGGREGATION_METHOD} = STRINGS; + +describe('lib/parameterize: ', () => { + afterEach(() => { + (mockLog as jest.Mock).mockReset(); + }); + + describe('getAggregationMethod(): ', () => { + it('returns method for average aggregation method metric.', () => { + const metric = 'cpu/utilization'; + const method = parameterize.getAggregationMethod(metric); + + const expectedMethod = 'avg'; + + expect(method).toEqual(expectedMethod); + }); + + it('returns method for unknown aggregation method metric.', () => { + const metric = 'mock/metric'; + const method = parameterize.getAggregationMethod(metric); + + const expectedMethod = 'sum'; + + expect(method).toEqual(expectedMethod); + expect(mockLog as unknown as LeveledLogMethod).toHaveBeenCalledTimes(2); + }); + + it('prints debug log for first input.', () => { + const unitName = 'timestamp'; + + parameterize.getAggregationMethod(unitName); + + expect(mockLog as typeof console.debug).toHaveBeenCalledWith( + console.debug, + CHECKING_AGGREGATION_METHOD(unitName) + ); + }); + }); + + describe('combine(): ', () => { + it('checks if return type is undefined.', () => { + const params = {}; + const response = parameterize.combine(null, params); + + expect(response).toBeUndefined(); + }); + + it('checks if uninitialized custom param is requested, then returns fallback `sum` method.', () => { + const name = 'mock-name'; + const method = parameterize.getAggregationMethod(name); + + const expectedMethodName = 'sum'; + expect(method).toEqual(expectedMethodName); + }); + + it('checks if custom params are inserted successfully.', () => { + const params = [ + { + name: 'mock-name', + description: 'mock-description', + unit: 'mock/sq', + aggregation: 'none', + }, + ] as ManifestParameter[]; + const object = {}; + + parameterize.combine(params, object); + const method = parameterize.getAggregationMethod(params[0].name); + + expect(method).toEqual(params[0].aggregation); + }); + + it('rejects on default param override.', () => { + const params = [ + { + name: 'carbon', + description: 'mock-description', + unit: 'mock/co', + aggregation: 'none', + }, + ] as ManifestParameter[]; + + parameterize.combine(params, PARAMETERS); + const method = parameterize.getAggregationMethod(params[0].name); + + const expectedMethodName = 'sum'; + const expectedMessage = REJECTING_OVERRIDE(params[0]); + + expect(method).toEqual(expectedMethodName); + expect(mockLog).toHaveBeenCalledWith(expectedMessage); + }); + }); +}); From 3ed40e18ed9347953e8800f21ed50f10ebdbc5bc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:20:32 +0400 Subject: [PATCH 327/863] test(builtins): init if-run tests --- .../if-run/builtins/CommonGenerator.test.ts | 41 + .../if-run/builtins/RandIntGenerator.test.ts | 60 ++ .../if-run/builtins/coefficient.test.ts | 127 +++ .../if-run/builtins/copy-param.test.ts | 124 +++ .../if-run/builtins/csv-lookup.test.ts | 514 ++++++++++++ src/__tests__/if-run/builtins/divide.test.ts | 183 ++++ .../if-run/builtins/exponent.test.ts | 118 +++ .../if-run/builtins/export-csv-raw.test.ts | 77 ++ .../if-run/builtins/export-csv.test.ts | 236 ++++++ .../if-run/builtins/export-log.test.ts | 36 + .../if-run/builtins/export-yaml.test.ts | 51 ++ .../if-run/builtins/group-by.test.ts | 177 ++++ .../if-run/builtins/interpolation.test.ts | 221 +++++ .../if-run/builtins/mock-observations.test.ts | 326 ++++++++ .../if-run/builtins/multiply.test.ts | 101 +++ src/__tests__/if-run/builtins/regex.test.ts | 152 ++++ .../if-run/builtins/sci-embodied.test.ts | 306 +++++++ src/__tests__/if-run/builtins/sci.test.ts | 165 ++++ src/__tests__/if-run/builtins/shell.test.ts | 97 +++ .../if-run/builtins/subtract.test.ts | 101 +++ src/__tests__/if-run/builtins/sum.test.ts | 127 +++ .../if-run/builtins/time-sync.test.ts | 781 ++++++++++++++++++ 22 files changed, 4121 insertions(+) create mode 100644 src/__tests__/if-run/builtins/CommonGenerator.test.ts create mode 100644 src/__tests__/if-run/builtins/RandIntGenerator.test.ts create mode 100644 src/__tests__/if-run/builtins/coefficient.test.ts create mode 100644 src/__tests__/if-run/builtins/copy-param.test.ts create mode 100644 src/__tests__/if-run/builtins/csv-lookup.test.ts create mode 100644 src/__tests__/if-run/builtins/divide.test.ts create mode 100644 src/__tests__/if-run/builtins/exponent.test.ts create mode 100644 src/__tests__/if-run/builtins/export-csv-raw.test.ts create mode 100644 src/__tests__/if-run/builtins/export-csv.test.ts create mode 100644 src/__tests__/if-run/builtins/export-log.test.ts create mode 100644 src/__tests__/if-run/builtins/export-yaml.test.ts create mode 100644 src/__tests__/if-run/builtins/group-by.test.ts create mode 100644 src/__tests__/if-run/builtins/interpolation.test.ts create mode 100644 src/__tests__/if-run/builtins/mock-observations.test.ts create mode 100644 src/__tests__/if-run/builtins/multiply.test.ts create mode 100644 src/__tests__/if-run/builtins/regex.test.ts create mode 100644 src/__tests__/if-run/builtins/sci-embodied.test.ts create mode 100644 src/__tests__/if-run/builtins/sci.test.ts create mode 100644 src/__tests__/if-run/builtins/shell.test.ts create mode 100644 src/__tests__/if-run/builtins/subtract.test.ts create mode 100644 src/__tests__/if-run/builtins/sum.test.ts create mode 100644 src/__tests__/if-run/builtins/time-sync.test.ts diff --git a/src/__tests__/if-run/builtins/CommonGenerator.test.ts b/src/__tests__/if-run/builtins/CommonGenerator.test.ts new file mode 100644 index 000000000..87b8457a8 --- /dev/null +++ b/src/__tests__/if-run/builtins/CommonGenerator.test.ts @@ -0,0 +1,41 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {CommonGenerator} from '../../../if-run/builtins/mock-observations/helpers/common-generator'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/mock-observations/CommonGenerator: ', () => { + describe('initialize: ', () => { + it('throws an error when config is not empty object.', async () => { + const commonGenerator = CommonGenerator({}); + + expect.assertions(1); + + try { + commonGenerator.next([]); + } catch (error) { + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + } + }); + }); + + describe('next(): ', () => { + it('returns a result with valid data.', async () => { + const config: Record = { + key1: 'value1', + key2: 'value2', + }; + const commonGenerator = CommonGenerator(config); + + expect.assertions(1); + + expect(commonGenerator.next([])).toEqual({ + key1: 'value1', + key2: 'value2', + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/RandIntGenerator.test.ts b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts new file mode 100644 index 000000000..05fdb37f2 --- /dev/null +++ b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts @@ -0,0 +1,60 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {RandIntGenerator} from '../../../if-run/builtins/mock-observations/helpers/rand-int-generator'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError} = ERRORS; +const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/mock-observations/RandIntGenerator: ', () => { + describe('initialize', () => { + it('throws an error when the generator name is empty string.', async () => { + expect.assertions(1); + try { + RandIntGenerator('', {}); + } catch (error) { + expect(error).toEqual(new GlobalConfigError(INVALID_NAME)); + } + }); + + it('throws an error when config is empty object.', async () => { + expect.assertions(1); + try { + RandIntGenerator('generator-name', {}); + } catch (error) { + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + } + }); + + it('throws an error `min` is missing from the config.', async () => { + const config = {max: 90}; + + expect.assertions(1); + + try { + RandIntGenerator('random', config); + } catch (error) { + expect(error).toEqual(new GlobalConfigError(MISSING_MIN_MAX)); + } + }); + }); + + describe('next(): ', () => { + it('returns a result with valid data.', async () => { + const config: Record = { + min: 10, + max: 90, + }; + const randIntGenerator = RandIntGenerator('random', config); + const result = randIntGenerator.next([]) as {random: number}; + + expect.assertions(4); + + expect(result).toBeInstanceOf(Object); + expect(result).toHaveProperty('random'); + expect(result.random).toBeGreaterThanOrEqual(10); + expect(result.random).toBeLessThanOrEqual(90); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts new file mode 100644 index 000000000..1660edffe --- /dev/null +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -0,0 +1,127 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Coefficient} from '../../../if-run/builtins/coefficient'; + +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/coefficient: ', () => { + describe('Coefficient: ', () => { + const globalConfig = { + 'input-parameter': 'carbon', + coefficient: 3, + 'output-parameter': 'carbon-product', + }; + const coefficient = Coefficient(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(coefficient).toHaveProperty('metadata'); + expect(coefficient).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies coefficient strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + carbon: 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 coefficient = Coefficient(config!); + + expect.assertions(1); + + try { + coefficient.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing `input-parameter` param in input.', () => { + const invalidConfig = { + 'input-parameter': '', + coefficient: 3, + 'output-parameter': 'carbon-product', + }; + const coefficient = Coefficient(invalidConfig); + const expectedMessage = + '"input-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; + + expect.assertions(1); + + try { + coefficient.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError(expectedMessage) + ); + } + }); + + it('throws an error on missing `output-parameter` param in input.', () => { + const invalidConfig = { + 'input-parameter': 'carbon', + coefficient: 10, + 'output-parameter': '', + }; + const coefficient = Coefficient(invalidConfig); + const expectedMessage = + '"output-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; + + expect.assertions(1); + try { + coefficient.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError(expectedMessage) + ); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts new file mode 100644 index 000000000..8ac621538 --- /dev/null +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -0,0 +1,124 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Copy} from '../../../if-run/builtins/copy-param'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/copy: ', () => { + describe('Copy: ', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(copy).toHaveProperty('metadata'); + expect(copy).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Copy strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + original: '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 copy = Copy(config!); + + expect.assertions(1); + + try { + copy.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + original: 1, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + expect.assertions(1); + + try { + copy.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"original" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + it('does not persist the original value when keep-existing==false.', () => { + expect.assertions(1); + const globalConfig = { + 'keep-existing': false, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + const expectedResult = [ + { + duration: 3600, + 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); + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts new file mode 100644 index 000000000..b89c7572e --- /dev/null +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -0,0 +1,514 @@ +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +import axios from 'axios'; +import AxiosMockAdapter from 'axios-mock-adapter'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {CSVLookup} from '../../../if-run/builtins'; + +import {STRINGS} from '../../../if-run/config'; + +const { + GlobalConfigError, + ReadFileError, + FetchingFileError, + QueryDataNotFoundError, + MissingCSVColumnError, + CSVParseError, +} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; + +describe('builtins/CSVLookup: ', () => { + const mock = new AxiosMockAdapter(axios); + + describe('CSVLookup: ', () => { + afterEach(() => { + mock.reset(); + }); + + describe('init: ', () => { + it('successfully initalized.', () => { + const globalConfig = { + filepath: '', + query: { + 'cpu-cores-available': 'cpu/available', + }, + output: ['cpu-tdp', 'tdp'], + }; + const csvLookup = CSVLookup(globalConfig); + expect(csvLookup).toHaveProperty('metadata'); + expect(csvLookup).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies CSVLookup `url` strategy to given input.', async () => { + expect.assertions(1); + const globalConfig = { + filepath: + 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + const csvLookup = CSVLookup(globalConfig); + + 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 +16,16,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.4xlarge,EBS-Only,32,32,November 2018,0`; + mock.onGet(globalConfig.filepath).reply(200, responseData); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + tdp: 150, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('successfully applies CSVLookup `local file` strategy to given input.', 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 csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + tdp: 150, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('rejects with file not found error.', async () => { + const globalConfig = { + filepath: './file-fail.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + const csvLookup = CSVLookup(globalConfig); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ReadFileError); + } + } + }); + + it('rejects with file not found error.', async () => { + const globalConfig = { + filepath: './file-fail.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + const csvLookup = CSVLookup(globalConfig); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ReadFileError); + } + } + }); + + it('rejects with axios error.', async () => { + const globalConfig = { + filepath: + 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + mock.onGet(globalConfig.filepath).reply(404); + + const csvLookup = CSVLookup(globalConfig); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(FetchingFileError); + } + } + }); + + it('successfully applies CSVLookup if output is `*`.', 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: '*', + }; + const csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + 'gpu-count': 'N/A', + 'gpu-model-name': 'N/A', + 'instance-class': 'a1.4xlarge', + 'instance-storage': 'EBS-Only', + 'memory-available': 32, + 'platform-memory': 32, + 'release-date': 'November 2018', + 'storage-drives': 'nan', + 'Hardware Information on AWS Documentation & Comments': + 'AWS Graviton (ARM)', + 'cpu-model-name': 'AWS Graviton', + 'cpu-tdp': 150, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('successfully applies CSVLookup if output is matrix.', 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: [ + ['gpu-count', 'gpuc'], + ['gpu-model-name', 'gpumodel'], + ], + }; + const csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + gpuc: 'N/A', + gpumodel: 'N/A', + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('successfully applies CSVLookup if output is exact string.', 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: 'gpu-count', + }; + const csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + 'gpu-count': 'N/A', + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('rejects with query data not found.', async () => { + expect.assertions(2); + const globalConfig = { + filepath: './file.csv', + query: { + 'fail-cpu-cores-available': 'cpu/available', + 'fail-cpu-cores-utilized': 'cpu/utilized', + 'fail-cpu-manufacturer': 'cpu/manufacturer', + }, + output: ['cpu-tdp', 'tdp'], + }; + + const csvLookup = CSVLookup(globalConfig); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(QueryDataNotFoundError); + expect(error.message).toEqual(NO_QUERY_DATA); + } + } + }); + + it('rejects with config not found error.', async () => { + expect.assertions(2); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const csvLookup = CSVLookup(); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error.message).toEqual(MISSING_GLOBAL_CONFIG); + } + } + }); + + it('rejects with no such column in csv error.', async () => { + expect.assertions(2); + + const globalConfig = { + filepath: './file.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: 'mock', + }; + const csvLookup = CSVLookup(globalConfig); + const input = [ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]; + + try { + await csvLookup.execute(input); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(MissingCSVColumnError); + expect(error.message).toEqual( + MISSING_CSV_COLUMN(globalConfig.output) + ); + } + } + }); + + it('successfully applies CSVLookup if output is array with string.', 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: ['gpu-count'], + }; + const csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + 'gpu-count': 'N/A', + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + it('successfully applies CSVLookup if output is matrix with strings.', 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: [['gpu-count']], + }; + const csvLookup = CSVLookup(globalConfig); + + 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + 'gpu-count': 'N/A', + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + }); + + it('rejects with CSV parse error', async () => { + process.env.csv = 'fail'; + expect.assertions(1); + const globalConfig = { + filepath: './fail-csv-reader.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: [['gpu-count']], + }; + const csvLookup = CSVLookup(globalConfig); + + try { + await csvLookup.execute([ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(CSVParseError); + } + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts new file mode 100644 index 000000000..b9d1d9456 --- /dev/null +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -0,0 +1,183 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Divide} from '../../../if-run/builtins'; + +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; + +describe('builtins/divide: ', () => { + describe('Divide: ', () => { + const globalConfig = { + numerator: 'vcpus-allocated', + denominator: 2, + output: 'cpu/number-cores', + }; + const divide = Divide(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(divide).toHaveProperty('metadata'); + expect(divide).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Divide strategy to given input.', async () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'vcpus-allocated': 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 = { + numerator: 'vcpus-allocated', + denominator: 'duration', + output: 'vcpus-allocated-per-second', + }; + const divide = Divide(globalConfig); + + const input = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]; + const response = await divide.execute(input); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + 'vcpus-allocated-per-second': 24 / 3600, + }, + ]; + + expect(response).toEqual(expectedResult); + }); + + it('throws an error on missing params in input.', async () => { + const expectedMessage = + '"vcpus-allocated" parameter is required. Error code: invalid_type.'; + + const globalConfig = { + numerator: 'vcpus-allocated', + denominator: 3600, + output: 'vcpus-allocated-per-second', + }; + const divide = Divide(globalConfig); + + expect.assertions(1); + + try { + await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError(expectedMessage) + ); + } + }); + }); + + it('throws an error on missing global config.', async () => { + const config = undefined; + const divide = Divide(config!); + + expect.assertions(1); + + try { + await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error when `denominator` is 0.', async () => { + const globalConfig = { + numerator: 'vcpus-allocated', + denominator: 0, + output: 'vcpus-allocated-per-second', + }; + const divide = Divide(globalConfig); + + expect.assertions(1); + + const response = await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]); + + expect(response).toEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + 'vcpus-allocated-per-second': 24, + }, + ]); + }); + + it('throws an error when `denominator` is string.', async () => { + const globalConfig = { + numerator: 'vcpus-allocated', + denominator: '10', + output: 'vcpus-allocated-per-second', + }; + const divide = Divide(globalConfig); + + expect.assertions(1); + + try { + await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new MissingInputDataError( + MISSING_INPUT_DATA(globalConfig.denominator) + ) + ); + } + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts new file mode 100644 index 000000000..3b88df0cb --- /dev/null +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -0,0 +1,118 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Exponent} from '../../../if-run/builtins/exponent'; + +const {InputValidationError} = ERRORS; + +describe('builtins/exponent: ', () => { + describe('Exponent: ', () => { + const globalConfig = { + 'input-parameter': 'energy/base', + exponent: 3, + 'output-parameter': 'energy', + }; + const exponent = Exponent(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(exponent).toHaveProperty('metadata'); + expect(exponent).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Exponent strategy to given input.', async () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'energy/base': 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); + + try { + await exponent.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"input-parameter" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws an error on input param value not numeric.', async () => { + expect.assertions(1); + const input = [ + { + duration: 3600, + 'energy/base': 'i-am-not-a-number', + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + try { + await exponent.execute(input); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"input-parameter" parameter is expected number, received string. Error code: invalid_type.' + ) + ); + } + }); + + it('returns a result with input params not related to energy.', async () => { + expect.assertions(1); + const newConfig = { + 'input-parameter': 'carbon/base', + exponent: 4, + 'output-parameter': 'carbon', + }; + const exponent = Exponent(newConfig); + + const data = [ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + 'carbon/base': 2, + }, + ]; + const response = await exponent.execute(data); + + const expectedResult = [ + { + duration: 3600, + 'carbon/base': 2, + carbon: 16, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + expect(response).toEqual(expectedResult); + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/export-csv-raw.test.ts b/src/__tests__/if-run/builtins/export-csv-raw.test.ts new file mode 100644 index 000000000..c6a577e4e --- /dev/null +++ b/src/__tests__/if-run/builtins/export-csv-raw.test.ts @@ -0,0 +1,77 @@ +import * as fs from 'fs/promises'; + +import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {ExportCSVRaw} from '../../../if-run/builtins/export-csv-raw'; + +import {STRINGS} from '../../../if-run/config'; + +import {tree, context, outputs} from '../../../__mocks__/builtins/export-csv'; + +const {ExhaustOutputArgError} = ERRORS; +const {WRITE_CSV_ERROR, OUTPUT_REQUIRED} = STRINGS; + +jest.mock('fs/promises', () => ({ + __esModule: true, + writeFile: jest.fn<() => Promise>().mockResolvedValue(), +})); + +describe('builtins/export-csv-raw: ', () => { + describe('ExportCSVRaw: ', () => { + const exportCSVRaw = ExportCSVRaw(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('init GroupBy: ', () => { + it('initalizes object with properties.', async () => { + expect(exportCSVRaw).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output#carbon'; + const content = + "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,8000.000004051243,"; + + await exportCSVRaw.execute(tree, context, outputPath); + + expect(fs.writeFile).toHaveBeenCalledWith(`${outputPath}.csv`, content); + }); + + it('throws an error when the CSV file could not be created.', async () => { + const outputPath = 'output#carbon'; + const expectedMessage = 'Could not write CSV file.'; + + expect.assertions(1); + + jest.spyOn(fs, 'writeFile').mockRejectedValue(expectedMessage); + + await expect( + exportCSVRaw.execute(tree, context, outputPath) + ).rejects.toThrow( + new ExhaustOutputArgError( + WRITE_CSV_ERROR(outputPath, expectedMessage) + ) + ); + }); + + it('throws an error when output path is empty.', async () => { + const outputPath = ''; + + context.initialize = Object.assign({}, context.initialize, outputs); + + expect.assertions(2); + try { + await exportCSVRaw.execute(tree, context, outputPath); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/export-csv.test.ts b/src/__tests__/if-run/builtins/export-csv.test.ts new file mode 100644 index 000000000..74d2e42dc --- /dev/null +++ b/src/__tests__/if-run/builtins/export-csv.test.ts @@ -0,0 +1,236 @@ +import * as fs from 'fs/promises'; + +import {stringify} from 'csv-stringify/sync'; +import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {ExportCSV} from '../../../if-run/builtins/export-csv'; + +import {STRINGS} from '../../../if-run/config'; + +import { + tree, + context, + outputs, + aggregated, + aggregation, +} from '../../../__mocks__/builtins/export-csv'; + +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED, CSV_EXPORT} = STRINGS; + +jest.mock('fs/promises', () => ({ + writeFile: jest.fn<() => Promise>().mockResolvedValue(), +})); + +describe('builtins/export-csv: ', () => { + describe('ExportCSV: ', () => { + const exportCSV = ExportCSV(); + + describe('init GroupBy: ', () => { + it('initalizes object with properties.', async () => { + expect(exportCSV).toMatchObject({metadata: {kind: 'exhaust'}}); + expect(exportCSV).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output#carbon'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + const reformedContext = Object.assign({}, context, {outputs}); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + await exportCSV.execute(reformedTree, reformedContext, outputPath); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when the `outputs` type is missing.', async () => { + const outputPath = 'output#carbon'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + await exportCSV.execute(reformedTree, context, outputPath); + + expect.assertions(1); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when `aggregation` persists.', async () => { + const outputPath = 'output#carbon'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedContext = Object.assign( + {}, + context, + {outputs}, + {aggregation} + ); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + await exportCSV.execute(reformedTree, reformedContext, outputPath); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when `aggregation` is missing.', async () => { + const outputPath = 'output#carbon'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedContext = Object.assign({}, context, {outputs}); + + await exportCSV.execute(tree, reformedContext, outputPath); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('throws an error when output path is empty.', async () => { + const outputPath = ''; + + context.initialize = Object.assign({}, context.initialize, outputs); + + try { + await exportCSV.execute(tree, context, outputPath); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); + } + }); + + it('throws an error when output path does not contains `#`.', async () => { + const outputPath = 'output.csv'; + + context.initialize = Object.assign({}, context.initialize, outputs); + + try { + await exportCSV.execute(tree, context, outputPath); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); + } + }); + + it('throws an error when output path does not contains a criteria.', async () => { + const outputPath = 'output.csv#'; + + context.initialize = Object.assign({}, context.initialize, outputs); + + try { + await exportCSV.execute(tree, context, outputPath); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/export-log.test.ts b/src/__tests__/if-run/builtins/export-log.test.ts new file mode 100644 index 000000000..48de3b49d --- /dev/null +++ b/src/__tests__/if-run/builtins/export-log.test.ts @@ -0,0 +1,36 @@ +import * as YAML from 'js-yaml'; + +import {ExportLog} from '../../../if-run/builtins/export-log'; +import {tree, context} from '../../../__mocks__/builtins/export-csv'; + +describe('builtins/export-log:', () => { + describe('ExportLog: ', () => { + it('successfully logs output manifest in console.', async () => { + const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(); + await ExportLog().execute(tree, context); + + const expectedMessage = `# start +${YAML.dump({...context, tree}, {noRefs: true})} +# end`; + + expect(mockConsoleLog).toHaveBeenCalled(); + expect(mockConsoleLog).toHaveBeenCalledWith(expectedMessage); + + mockConsoleLog.mockRestore(); + }); + + it('successfully logs output manifest if tree is an empty object.', async () => { + const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(); + await ExportLog().execute({}, context); + + const expectedMessage = `# start +${YAML.dump({...context, tree: {}}, {noRefs: true})} +# end`; + + expect(mockConsoleLog).toHaveBeenCalled(); + expect(mockConsoleLog).toHaveBeenCalledWith(expectedMessage); + + mockConsoleLog.mockRestore(); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/export-yaml.test.ts b/src/__tests__/if-run/builtins/export-yaml.test.ts new file mode 100644 index 000000000..6d1e84d8b --- /dev/null +++ b/src/__tests__/if-run/builtins/export-yaml.test.ts @@ -0,0 +1,51 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {ExportYaml} from '../../../if-run/builtins/export-yaml'; +import {saveYamlFileAs} from '../../../common/util/yaml'; + +import {STRINGS} from '../../../if-run/config'; + +import {tree, context} from '../../../__mocks__/builtins/export-csv'; + +jest.mock('../../../common/util/yaml', () => ({ + saveYamlFileAs: jest.fn(), +})); + +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED} = STRINGS; + +describe('builtins/export-yaml: ', () => { + describe('ExportYaml: ', () => { + const exportYaml = ExportYaml(); + + describe('init ExportYaml: ', () => { + it('initalizes object with properties.', async () => { + expect(exportYaml).toHaveProperty('execute'); + }); + }); + + describe('execute', () => { + it('returns result with correct arguments', async () => { + const outputPath = 'outputPath.yaml'; + + await exportYaml.execute(tree, context, outputPath); + + expect(saveYamlFileAs).toHaveBeenCalledWith( + {...context, tree}, + `${outputPath.split('#')[0]}.yaml` + ); + }); + + it('throws an error if outputPath is not provided.', async () => { + expect.assertions(2); + + try { + await exportYaml.execute({}, context, ''); + } catch (error) { + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/group-by.test.ts b/src/__tests__/if-run/builtins/group-by.test.ts new file mode 100644 index 000000000..b59da6836 --- /dev/null +++ b/src/__tests__/if-run/builtins/group-by.test.ts @@ -0,0 +1,177 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {GroupBy} from '../../../if-run/builtins/group-by'; + +import {STRINGS} from '../../../if-run/config'; + +const {InvalidGroupingError, InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, INVALID_GROUP_BY} = STRINGS; + +describe('builtins/group-by: ', () => { + describe('GroupBy: ', () => { + const plugin = GroupBy(); + + describe('init GroupBy: ', () => { + it('initalizes object with properties.', async () => { + expect(plugin).toHaveProperty('metadata'); + expect(plugin).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('groups inputs correctly.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + const config = { + group: ['region', 'cloud/instance-type'], + }; + + const expectedOutput = { + 'uk-west': { + children: { + A1: { + inputs: [ + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T00:00', + }, + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T05:00', + }, + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T10:00', + }, + ], + }, + }, + }, + }; + + const result = plugin.execute(inputs, config); + expect(result).toEqual(expectedOutput); + }); + + it('throws an error when config is not provided.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + + const config = undefined; + + expect.assertions(2); + try { + plugin.execute(inputs, config!); + } catch (error) { + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + } + }); + + it('throws an error if `group` is an empty array.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + const config = { + group: ['region', 'cloud/instance-type'], + }; + + expect.assertions(2); + try { + plugin.execute(inputs, config); + } catch (error) { + expect(error).toBeInstanceOf(InvalidGroupingError); + expect(error).toEqual( + new InvalidGroupingError('Invalid group region.') + ); + } + }); + + it('throws an error if group type is missing from the input.', () => { + const inputs = [ + {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, + ]; + const config = { + group: [], + }; + + expect.assertions(2); + try { + plugin.execute(inputs, config); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"group" parameter is array must contain at least 1 element(s). Error code: too_small.' + ) + ); + } + }); + + it('throws an error if input does not have required group type.', () => { + const inputs = [ + {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, + ]; + const config = { + group: ['region', 'cloud/instance-type', 'unknown'], + }; + + expect.assertions(2); + try { + plugin.execute(inputs, config); + } catch (error) { + expect(error).toBeInstanceOf(InvalidGroupingError); + expect(error).toEqual( + new InvalidGroupingError(INVALID_GROUP_BY(config.group[2])) + ); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts new file mode 100644 index 000000000..8dbd1295c --- /dev/null +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -0,0 +1,221 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {Method} from '@grnsft/if-core/types'; + +import {Interpolation} from '../../../if-run/builtins'; + +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + WITHIN_THE_RANGE, + ARRAY_LENGTH_NON_EMPTY, + X_Y_EQUAL, +} = STRINGS; + +describe('builtins/interpolation: ', () => { + describe('Interpolation: ', () => { + 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/utilization': 45, + }, + ]; + const plugin = Interpolation(globalConfig); + + describe('init Interpolation: ', () => { + it('initalizes object with properties.', async () => { + expect(plugin).toHaveProperty('metadata'); + expect(plugin).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('returns result when all parameters are valid.', () => { + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + 'interpolation-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], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': 'cpu/utilization', + 'output-parameter': 'interpolation-result', + }; + const plugin = Interpolation(globalConfig); + + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + 'interpolation-result': 0.69625, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('returns result when the `method` is `spline`.', () => { + const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); + const plugin = Interpolation(config); + + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + 'interpolation-result': 0.7169698932926829, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('returns result when the `method` is `polynomial`.', () => { + const config = Object.assign({}, globalConfig, { + method: Method.POLYNOMIAL, + }); + const plugin = Interpolation(config); + + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + 'interpolation-result': 0.7187374999999999, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('returns result when the elements of `x` is not in acsending order.', () => { + const config = Object.assign({}, globalConfig, { + x: [0, 10, 100, 50], + }); + const plugin = Interpolation(config); + + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + 'interpolation-result': 0.69625, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('returns result when the `cpu/utilization` is equal to one of the `x` points element.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 50, + }, + ]; + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 50, + 'interpolation-result': 0.75, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('throws an when the global config is not provided.', () => { + const config = undefined; + const plugin = Interpolation(config!); + + expect.assertions(2); + try { + plugin.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + } + }); + + it('throws an error when `x` and `y` points not equal.', () => { + const config = Object.assign({}, globalConfig, { + x: [0, 10, 100], + }); + + const plugin = Interpolation(config); + + expect.assertions(2); + try { + plugin.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual(new InputValidationError(X_Y_EQUAL)); + } + }); + + it('throws an error when `cpu/utilization` is out of the range of `x` elements.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 105, + }, + ]; + expect.assertions(2); + try { + plugin.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual(new InputValidationError(WITHIN_THE_RANGE)); + } + }); + it('throws an error when the the length of the input arrays is <2', () => { + const globalConfig = { + x: [0], + y: [0.12], + 'input-parameter': 'cpu/utilization', + 'output-parameter': 'interpolation-result', + }; + const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); + const plugin = Interpolation(config); + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 105, + }, + ]; + expect.assertions(2); + try { + plugin.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError(ARRAY_LENGTH_NON_EMPTY) + ); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts new file mode 100644 index 000000000..6b0fb22bd --- /dev/null +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -0,0 +1,326 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {MockObservations} from '../../../if-run/builtins/mock-observations'; + +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const {INVALID_MIN_MAX} = STRINGS; + +describe('builtins/mock-observations: ', () => { + describe('init: ', () => { + it('successfully initalized.', () => { + const mockObservations = MockObservations({ + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }); + + expect(mockObservations).toHaveProperty('metadata'); + expect(mockObservations).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('executes successfully.', 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 mockObservations = MockObservations(config); + 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/utilization': 10, + }, + { + timestamp: '2023-07-06T00:00:30.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'A1', + region: 'uk-west', + 'cpu/utilization': 10, + }, + { + timestamp: '2023-07-06T00:00:00.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'B1', + region: 'uk-west', + 'cpu/utilization': 10, + }, + { + timestamp: '2023-07-06T00:00:30.000Z', + duration: 30, + 'common-key': 'common-val', + 'instance-type': 'B1', + region: 'uk-west', + 'cpu/utilization': 10, + }, + ]); + }); + + it('throws an error when the `min` is greater then `max` of `randint` config.', 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: 20, max: 11}, + }, + }, + }; + + expect.assertions(2); + + const mockObservations = MockObservations(config); + try { + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual( + new GlobalConfigError(INVALID_MIN_MAX('cpu/utilization')) + ); + } + }); + + it('throws when `generators` are not provided.', async () => { + const config = { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + }; + + expect.assertions(2); + + try { + const mockObservations = MockObservations(config); + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"generators" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws when `components` are not provided.', async () => { + const errorMessage = + '"components" parameter is required. Error code: invalid_type.'; + const config = { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }; + + expect.assertions(2); + + try { + const mockObservations = MockObservations(config); + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual(new InputValidationError(errorMessage)); + } + }); + + it('throws when `duration` is not provided.', async () => { + expect.assertions(2); + + try { + const mockObservations = MockObservations({ + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }); + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"duration" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws when `timestamp-to` is not provided.', async () => { + expect.assertions(2); + + try { + const mockObservations = MockObservations({ + 'timestamp-from': '2023-07-06T00:00', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }); + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"timestamp-to" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws when `timestamp-from` is missing.', async () => { + expect.assertions(2); + + try { + const mockObservations = MockObservations({ + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }); + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"timestamp-from" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws an error when `randInt` is not valid.', 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: null, + }, + }; + const mockObservations = MockObservations(config); + + expect.assertions(2); + + try { + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"generators.randint" parameter is expected object, received null. Error code: invalid_type.' + ) + ); + } + }); + + it('throws an error when `common` is not valid.', 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: null, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, + }, + }; + const mockObservations = MockObservations(config); + + expect.assertions(2); + + try { + await mockObservations.execute([]); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"generators.common" parameter is expected object, received null. Error code: invalid_type.' + ) + ); + } + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts new file mode 100644 index 000000000..07dedf5ea --- /dev/null +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -0,0 +1,101 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Multiply} from '../../../if-run/builtins/multiply'; + +const {InputValidationError} = ERRORS; + +describe('builtins/multiply: ', () => { + describe('Multiply: ', () => { + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; + const multiply = Multiply(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(multiply).toHaveProperty('metadata'); + expect(multiply).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Multiply strategy to given input.', async () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + energy: 8, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = await multiply.execute([ + { + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('throws an error on missing params in input.', async () => { + expect.assertions(1); + + try { + await multiply.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('returns a result with input params not related to energy.', async () => { + expect.assertions(1); + const newConfig = { + 'input-parameters': ['carbon', 'other-carbon'], + 'output-parameter': 'carbon-product', + }; + const multiply = Multiply(newConfig); + + const data = [ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + 'other-carbon': 2, + }, + ]; + const response = await multiply.execute(data); + + const expectedResult = [ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + 'other-carbon': 2, + 'carbon-product': 6, + }, + ]; + + expect(response).toEqual(expectedResult); + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts new file mode 100644 index 000000000..6ac6bd4e9 --- /dev/null +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -0,0 +1,152 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Regex} from '../../../if-run/builtins/regex'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; + +describe('builtins/regex: ', () => { + describe('Regex: ', () => { + const globalConfig = { + parameter: 'physical-processor', + match: '^[^,]+', + output: 'cpu/name', + }; + const regex = Regex(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(regex).toHaveProperty('metadata'); + expect(regex).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Regex strategy to given input.', 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'; + expect.assertions(1); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': physicalProcessor, + 'cpu/name': 'Intel® Xeon® Platinum 8272CL', + }, + ]; + + const result = await regex.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': physicalProcessor, + }, + ]); + + 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'; + expect.assertions(1); + + const globalConfig = { + parameter: 'physical-processor', + match: '[^,]+/', + output: 'cpu/name', + }; + const regex = Regex(globalConfig); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': physicalProcessor, + 'cpu/name': 'Intel® Xeon® Platinum 8272CL', + }, + ]; + + const result = await regex.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': physicalProcessor, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('throws an error when `parameter` does not match to `match`.', 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'; + + const globalConfig = { + parameter: 'physical-processor', + match: '^(^:)+', + output: 'cpu/name', + }; + const regex = Regex(globalConfig); + + expect.assertions(1); + + try { + await regex.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'physical-processor': physicalProcessor, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new RegexMismatchError( + REGEX_MISMATCH(physicalProcessor, '/^(^:)+/') + ) + ); + } + }); + + it('throws an error on missing global config.', async () => { + const config = undefined; + const regex = Regex(config!); + + expect.assertions(1); + + try { + await regex.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', async () => { + expect.assertions(1); + + try { + await regex.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new MissingInputDataError(MISSING_INPUT_DATA('physical-processor')) + ); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts new file mode 100644 index 000000000..0c1b504ac --- /dev/null +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -0,0 +1,306 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {SciEmbodied} from '../../../if-run/builtins/sci-embodied'; + +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError} = ERRORS; +const {SCI_EMBODIED_ERROR} = STRINGS; + +describe('builtins/sci-embodied:', () => { + describe('SciEmbodied: ', () => { + const sciEmbodied = SciEmbodied(); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(sciEmbodied).toHaveProperty('metadata'); + expect(sciEmbodied).toHaveProperty('execute'); + }); + }); + + describe('execute():', () => { + it('returns a result with valid inputs.', async () => { + 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/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + 'carbon-embodied': 4.10958904109589, + }, + { + 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, + 'carbon-embodied': 4.10958904109589 * 2, + }, + ]); + }); + + it('returns a result when `vcpus-allocated` and `vcpus-total` are in the input.', async () => { + 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, + 'vcpus-allocated': 1, + 'vcpus-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/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + 'carbon-embodied': 4.10958904109589, + }, + ]); + }); + + it('returns a result when `vcpus-allocated` and `vcpus-total` are preferred to `resources-reserved` and `resources-total`.', async () => { + 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': 2, + 'resources-total': 2, + 'vcpus-allocated': 1, + 'vcpus-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, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + 'resources-reserved': 2, + 'resources-total': 2, + }, + ]; + + const result = await sciEmbodied.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + 'carbon-embodied': 4.10958904109589, + 'resources-reserved': 2, + 'resources-total': 2, + }, + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30 * 2, + 'device/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + 'carbon-embodied': 4.10958904109589 * 2, + 'resources-reserved': 2, + 'resources-total': 2, + }, + ]); + }); + + it('returns a result when `vcpus-allocated` and `vcpus-total` are miised.', async () => { + 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/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'carbon-embodied': 4.10958904109589, + '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, + 'carbon-embodied': 4.10958904109589 * 2, + 'resources-reserved': 1, + 'resources-total': 1, + }, + ]); + }); + + it('throws an error when `device/emissions-embodied` is string.', async () => { + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': '10,00', + '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, + }, + ]; + + expect.assertions(2); + try { + await sciEmbodied.execute(inputs); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); + expect(error).toBeInstanceOf(InputValidationError); + } + }); + + it('throws an exception on missing `device/emissions-embodied`.', async () => { + const errorMessage = + '"device/emissions-embodied" parameter is required. Error code: invalid_union.'; + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + }, + ]; + + expect.assertions(2); + + try { + await sciEmbodied.execute(inputs); + } catch (error) { + expect(error).toStrictEqual(new InputValidationError(errorMessage)); + expect(error).toBeInstanceOf(InputValidationError); + } + }); + + it('throws an exception on missing `device/expected-lifespan`.', async () => { + const errorMessage = + '"device/expected-lifespan" parameter is required. Error code: invalid_union.'; + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': 200, + 'vcpus-allocated': 1, + 'vcpus-total': 1, + }, + ]; + + expect.assertions(2); + + try { + await sciEmbodied.execute(inputs); + } catch (error) { + expect(error).toStrictEqual(new InputValidationError(errorMessage)); + expect(error).toBeInstanceOf(InputValidationError); + } + }); + + it('throws an exception on invalid values.', async () => { + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 60 * 60 * 24 * 30, + 'device/emissions-embodied': '200', + 'vcpus-allocated': true, + 'vcpus-total': 1, + }, + ]; + + expect.assertions(2); + + try { + await sciEmbodied.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); + } + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts new file mode 100644 index 000000000..2d75ea170 --- /dev/null +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -0,0 +1,165 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Sci} from '../../../if-run/builtins/sci'; + +const {MissingInputDataError} = ERRORS; + +describe('builtins/sci:', () => { + describe('Sci: ', () => { + const sci = Sci({'functional-unit': 'users'}); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(sci).toHaveProperty('metadata'); + expect(sci).toHaveProperty('execute'); + }); + }); + + describe('execute():', () => { + it('returns a result with valid inputs.', async () => { + const sci = Sci({ + 'functional-unit': 'users', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + duration: 1, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + duration: 1, + sci: 0.050199999999999995, + }, + ]); + }); + + it('returns the same result regardless of input duration.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 1, + requests: 10, + }, + { + timestamp: '2021-01-01T00:01:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 100, + requests: 10, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 1, + requests: 10, + sci: 0.020499999999999997, + }, + { + timestamp: '2021-01-01T00:01:00Z', + carbon: 0.205, + 'carbon-embodied': 0.05, + 'carbon-operational': 0.2, + duration: 100, + requests: 10, + sci: 0.020499999999999997, + }, + ]); + }); + + it('throws exception on invalid functional unit data.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.002, + 'carbon-embodied': 0.0005, + duration: 1, + }, + ]; + + expect.assertions(1); + + try { + await sci.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(MissingInputDataError); + } + }); + + it('throws exception if functional unit value is not positive integer.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.002, + 'carbon-embodied': 0.0005, + duration: 1, + requests: -5, + }, + ]; + + expect.assertions(1); + + try { + await sci.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(MissingInputDataError); + } + }); + }); + + it('fallbacks to carbon value, if functional unit is 0.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 1, + requests: 0, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts new file mode 100644 index 000000000..379863052 --- /dev/null +++ b/src/__tests__/if-run/builtins/shell.test.ts @@ -0,0 +1,97 @@ +import {spawnSync} from 'child_process'; +import {loadAll} from 'js-yaml'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Shell} from '../../../if-run/builtins/shell'; + +const {InputValidationError, ProcessExecutionError} = ERRORS; + +jest.mock('child_process'); +jest.mock('js-yaml'); + +describe('builtins/shell', () => { + describe('Shell', () => { + const shell = Shell({}); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(shell).toHaveProperty('metadata'); + expect(shell).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('execute with valid inputs and command', async () => { + const shell = Shell({command: 'python3 /path/to/script.py'}); + const mockSpawnSync = spawnSync as jest.MockedFunction< + typeof spawnSync + >; + mockSpawnSync.mockReturnValueOnce({stdout: 'mocked stdout'} as any); + + const mockLoadAll = loadAll as jest.MockedFunction; + mockLoadAll.mockReturnValueOnce(['mocked output'] as any); + + const inputs = [ + { + duration: 3600, + timestamp: '2022-01-01T00:00:00Z', + }, + ]; + + expect.assertions(2); + + await shell.execute(inputs); + + expect(mockSpawnSync).toHaveBeenCalledWith( + 'python3', + ['/path/to/script.py'], + { + encoding: 'utf8', + } + ); + expect(mockLoadAll).toHaveBeenCalledWith('mocked stdout'); + }); + + it('throw an error if validation fails', async () => { + const invalidInputs = [ + {duration: 3600, timestamp: '2022-01-01T00:00:00Z', command: 123}, + ]; + + try { + await shell.execute(invalidInputs); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + '"command" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throw an error when shell could not run command.', async () => { + const shell = Shell({command: 'python3 /path/to/script.py'}); + (spawnSync as jest.Mock).mockImplementation(() => { + throw new InputValidationError('Could not run the command'); + }); + + const inputs = [ + { + duration: 3600, + timestamp: '2022-01-01T00:00:00Z', + }, + ]; + expect.assertions(2); + + try { + await shell.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(ProcessExecutionError); + expect(error).toStrictEqual( + new ProcessExecutionError('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 new file mode 100644 index 000000000..33ba137ab --- /dev/null +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -0,0 +1,101 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Subtract} from '../../../if-run/builtins/subtract'; + +const {InputValidationError} = ERRORS; + +describe('builtins/subtract: ', () => { + describe('Subtract: ', () => { + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy/diff', + }; + const subtract = Subtract(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(subtract).toHaveProperty('metadata'); + expect(subtract).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Subtract strategy to given input.', async () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 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); + + try { + await subtract.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('returns a result with input params not related to energy.', async () => { + expect.assertions(1); + const newConfig = { + 'input-parameters': ['carbon', 'other-carbon'], + 'output-parameter': 'carbon-diff', + }; + const subtract = Subtract(newConfig); + + const data = [ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 3, + 'other-carbon': 2, + }, + ]; + const response = await subtract.execute(data); + + const expectedResult = [ + { + duration: 3600, + carbon: 3, + 'other-carbon': 2, + 'carbon-diff': 1, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + expect(response).toEqual(expectedResult); + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts new file mode 100644 index 000000000..d7530827c --- /dev/null +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -0,0 +1,127 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Sum} from '../../../if-run/builtins/sum'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/sum: ', () => { + describe('Sum: ', () => { + const globalConfig = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; + const sum = Sum(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(sum).toHaveProperty('metadata'); + expect(sum).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Sum strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + energy: 3, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + 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!); + + expect.assertions(1); + + try { + sum.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', () => { + expect.assertions(1); + + try { + sum.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('returns a result with input params not related to energy.', () => { + expect.assertions(1); + const newConfig = { + 'input-parameters': ['carbon', 'other-carbon'], + 'output-parameter': 'carbon-sum', + }; + const sum = Sum(newConfig); + + const data = [ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + carbon: 1, + 'other-carbon': 2, + }, + ]; + const response = sum.execute(data); + + const expectedResult = [ + { + duration: 3600, + carbon: 1, + 'other-carbon': 2, + 'carbon-sum': 3, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + expect(response).toEqual(expectedResult); + }); + }); + }); +}); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts new file mode 100644 index 000000000..ab58b3e34 --- /dev/null +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -0,0 +1,781 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {Settings, DateTime} from 'luxon'; + +import {TimeSync} from '../../../if-run/builtins/time-sync'; + +import {STRINGS} from '../../../if-run/config'; + +Settings.defaultZone = 'utc'; +const { + InputValidationError, + InvalidPaddingError, + InvalidDateInInputError, + InvalidInputError, + GlobalConfigError, +} = ERRORS; + +const { + INVALID_OBSERVATION_OVERLAP, + INVALID_TIME_NORMALIZATION, + AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, +} = STRINGS; + +jest.mock('luxon', () => { + const originalModule = jest.requireActual('luxon'); + return { + ...originalModule, + Interval: { + ...originalModule.Interval, + fromDateTimes: jest.fn((start, end) => ({ + start, + end, + splitBy: jest.fn(() => { + const intervals = []; + let current = start; + + while (current < end) { + intervals.push({ + start: process.env.MOCK_INTERVAL === 'true' ? null : current, + end: current.plus({seconds: 1}), + }); + + current = current.plus({seconds: 1}); + } + + return intervals; + }), + })), + }, + }; +}); + +describe('builtins/time-sync:', () => { + describe('time-sync: ', () => { + const basicConfig = { + 'start-time': '2023-12-12T00:01:00.000Z', + 'end-time': '2023-12-12T00:01:00.000Z', + interval: 5, + 'allow-padding': true, + }; + + const timeSync = TimeSync(basicConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(timeSync).toHaveProperty('metadata'); + 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, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + + 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, + }; + + const timeModel = TimeSync(basicConfig); + + 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 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, + }; + + 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('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, + }; + + const timeModel = TimeSync(basicConfig); + + 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 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, + }; + + 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('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, + }; + + 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('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, + }; + + 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('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, + }; + + 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); + }); +}); From 74a1709d1a8dee6d1976e1fa836254a054928e88 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:20:45 +0400 Subject: [PATCH 328/863] test(util): init if-diff tests --- src/__tests__/if-diff/util/args.test.ts | 133 +++++++++++ src/__tests__/if-diff/util/helpers.test.ts | 235 +++++++++++++++++++ src/__tests__/if-env/util/args.test.ts | 124 ++++++++++ src/__tests__/if-env/util/npm.test.ts | 250 +++++++++++++++++++++ 4 files changed, 742 insertions(+) create mode 100644 src/__tests__/if-diff/util/args.test.ts create mode 100644 src/__tests__/if-diff/util/helpers.test.ts create mode 100644 src/__tests__/if-env/util/args.test.ts create mode 100644 src/__tests__/if-env/util/npm.test.ts diff --git a/src/__tests__/if-diff/util/args.test.ts b/src/__tests__/if-diff/util/args.test.ts new file mode 100644 index 000000000..2f43ec6ab --- /dev/null +++ b/src/__tests__/if-diff/util/args.test.ts @@ -0,0 +1,133 @@ +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + case 'only-target': + return { + target: 'target-mock.yml', + }; + case 'target-is-not-yaml': + return { + target: 'target-mock', + }; + case 'source-is-not-yaml': + return { + target: 'target-mock.yml', + source: 'source-mock', + }; + case 'target-source': + return { + target: 'target-mock.yml', + source: 'source-mock.yml', + }; + case 'diff-throw-error': + throw new Error('mock-error'); + case 'diff-throw': + throw 'mock-error'; + default: + return { + manifest: 'mock-manifest.yaml', + output: 'mock-output', + }; + } + }, +})); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {parseIfDiffArgs} from '../../../if-diff/util/args'; + +import {STRINGS as COMMON_STRINGS} from '../../../common/config'; +import {STRINGS} from '../../../if-diff/config'; + +const {ParseCliParamsError} = ERRORS; + +const {TARGET_IS_NOT_YAML, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; +const {INVALID_TARGET} = STRINGS; + +describe('util/args: ', () => { + const originalEnv = process.env; + + describe('parseIfDiffArgs(): ', () => { + it('throws error if `target` is missing.', () => { + expect.assertions(1); + + try { + parseIfDiffArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(INVALID_TARGET)); + } + } + }); + + it('throws error if `target` is not a yaml.', () => { + process.env.result = 'target-is-not-yaml'; + expect.assertions(1); + + try { + parseIfDiffArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(TARGET_IS_NOT_YAML)); + } + } + }); + + it('returns `target`s full path.', () => { + process.env.result = 'only-target'; + expect.assertions(1); + + const response = parseIfDiffArgs(); + expect(response).toHaveProperty('targetPath'); + }); + + it('throws error if source is not a yaml.', () => { + process.env.result = 'source-is-not-yaml'; + expect.assertions(1); + + try { + parseIfDiffArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('returns target and source full paths.', () => { + process.env.result = 'target-source'; + expect.assertions(2); + + const response = parseIfDiffArgs(); + expect(response).toHaveProperty('targetPath'); + expect(response).toHaveProperty('sourcePath'); + }); + + it('throws error if parsing failed.', () => { + process.env.result = 'diff-throw-error'; + expect.assertions(1); + + try { + parseIfDiffArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', () => { + process.env.result = 'diff-throw'; + expect.assertions(1); + + try { + parseIfDiffArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + + process.env = originalEnv; +}); diff --git a/src/__tests__/if-diff/util/helpers.test.ts b/src/__tests__/if-diff/util/helpers.test.ts new file mode 100644 index 000000000..a7d25599e --- /dev/null +++ b/src/__tests__/if-diff/util/helpers.test.ts @@ -0,0 +1,235 @@ +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); + +import {Difference} from '../../../if-diff/types/compare'; +import { + checkIfEqual, + formatNotMatchingLog, + oneIsPrimitive, + parseManifestFromStdin, +} from '../../../if-diff/util/helpers'; + +describe('if-diff/util/helpers: ', () => { + describe('checkIfEqual(): ', () => { + it('checks if values are equal.', () => { + const a = 'mock'; + const b = 'mock'; + + const response = checkIfEqual(a, b); + expect(response).toBeTruthy(); + }); + + it('returns true if one of the values is wildcard.', () => { + const a = 'mock'; + const b = '*'; + + const response = checkIfEqual(a, b); + expect(response).toBeTruthy(); + }); + + it('returns false for number and string with the same value.', () => { + const a = 5; + const b = '5'; + + const response = checkIfEqual(a, b); + expect(response).toBeFalsy(); + }); + }); + + describe('oneIsPrimitive(): ', () => { + it('returns true if values are nullish.', () => { + const source = null; + const target = undefined; + + const result = oneIsPrimitive(source, target); + expect(result).toBeTruthy(); + }); + + it('returns true if values are string or number.', () => { + const source = 'string'; + const target = 10; + + const result = oneIsPrimitive(source, target); + expect(result).toBeTruthy(); + }); + + it('returns false if one of values is object.', () => { + const source = 'string'; + const target = {}; + + const result = oneIsPrimitive(source, target); + expect(result).toBeFalsy(); + }); + }); + + describe('formatNotMatchingLog(): ', () => { + const actualLogger = console.log; + const mockLogger = jest.fn(); + console.log = mockLogger; + + beforeEach(() => { + mockLogger.mockReset(); + }); + + it('logs the message.', () => { + const difference: Difference = { + message: 'mock-message', + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(1); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + }); + + it('logs message and path.', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(2); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + }); + + it('logs message, path and formatted source/target (one is missing).', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: 'mock-source', + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith('target: missing'); + }); + + it('logs message, path and formatted source/target.', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: 'mock-source', + target: 'mock-target', + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); + }); + + it('logs message, path and formatted source/target (numbers).', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: 10, + target: 0, + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); + }); + + it('logs message, path and formatted source/target (booleans).', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: true, + target: false, + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); + }); + + it('logs message, path and formatted source/target (objects).', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: {}, + target: false, + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); + }); + + it('logs message, path and formatted source/target (empty string).', () => { + const difference: Difference = { + message: 'mock-message', + path: 'mock.path', + source: '', + target: false, + }; + + formatNotMatchingLog(difference); + expect(mockLogger).toHaveBeenCalledTimes(4); + expect(mockLogger).toHaveBeenCalledWith(difference.message); + expect(mockLogger).toHaveBeenCalledWith(difference.path); + expect(mockLogger).toHaveBeenCalledWith(`source: ${difference.source}`); + expect(mockLogger).toHaveBeenCalledWith(`target: ${difference.target}`); + }); + + afterAll(() => { + console.log = actualLogger; + }); + }); + + describe('parseManifestFromStdin(): ', () => { + it('returns empty string if there is no data in stdin.', async () => { + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + }); + + it('returns empty string if nothing is piped.', async () => { + const originalIsTTY = process.stdin.isTTY; + process.stdin.isTTY = true; + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + process.stdin.isTTY = originalIsTTY; + }); + + it('throws error if there is no manifest in stdin.', async () => { + process.env.readline = 'no_manifest'; + expect.assertions(1); + + const response = await parseManifestFromStdin(); + + expect(response).toEqual(''); + }); + + it('returns empty string if there is no data in stdin.', async () => { + process.env.readline = 'manifest'; + const response = await parseManifestFromStdin(); + const expectedMessage = ` +name: mock-name +description: mock-description +`; + + expect(response).toEqual(expectedMessage); + }); + }); +}); diff --git a/src/__tests__/if-env/util/args.test.ts b/src/__tests__/if-env/util/args.test.ts new file mode 100644 index 000000000..2b0dd13f9 --- /dev/null +++ b/src/__tests__/if-env/util/args.test.ts @@ -0,0 +1,124 @@ +jest.mock('../../../common/util/fs', () => ({ + isFileExists: () => { + if (process.env.fileExists === 'true') { + return true; + } + return false; + }, +})); + +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + case 'manifest-is-missing': + return {}; + case 'manifest-install-provided': + return { + install: true, + manifest: 'mock-manifest.yaml', + }; + case 'manifest-is-not-yaml': + return {manifest: 'manifest'}; + case 'env-throw-error': + throw new Error('mock-error'); + case 'env-throw': + throw 'mock-error'; + default: + return { + manifest: 'mock-manifest.yaml', + output: 'mock-output', + }; + } + }, +})); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {parseIfEnvArgs} from '../../../if-env/util/args'; + +import {STRINGS} from '../../../common/config'; + +const {CliSourceFileError, ParseCliParamsError} = ERRORS; + +const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = STRINGS; + +describe('util/args: ', () => { + const originalEnv = process.env; + + describe('parseIfEnvArgs(): ', () => { + it('executes if `manifest` is missing.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-missing'; + const response = await parseIfEnvArgs(); + + expect.assertions(1); + + expect(response).toEqual({install: undefined}); + }); + + it('executes if `manifest` and `install` are provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-install-provided'; + + const response = await parseIfEnvArgs(); + + expect.assertions(2); + expect(response).toHaveProperty('install'); + expect(response).toHaveProperty('manifest'); + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + + process.env = originalEnv; +}); diff --git a/src/__tests__/if-env/util/npm.test.ts b/src/__tests__/if-env/util/npm.test.ts new file mode 100644 index 000000000..be922f07c --- /dev/null +++ b/src/__tests__/if-env/util/npm.test.ts @@ -0,0 +1,250 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +const mockInfo = jest.fn(); + +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); +jest.mock('../../../common/util/logger', () => ({ + logger: { + info: mockInfo, + }, +})); + +jest.mock('../../../common/util/helpers', () => { + const originalModule = jest.requireActual('../../../if-run/util/helpers'); + + return { + ...originalModule, + execPromise: async (param: any) => { + switch (process.env.NPM_INSTALL) { + case 'true': + expect(param).toEqual('npm install @grnsft/if@0.3.3-beta.0'); + break; + case 'npm init -y': + expect(param).toEqual('npm init -y'); + break; + case 'if-check': + expect(param).toEqual( + "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" + ); + break; + } + return; + }, + }; +}); + +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, +} from '../../../if-env/util/npm'; +import {isFileExists} from '../../../common/util/fs'; + +import {STRINGS} from '../../../if-env/config'; +import {ManifestPlugin} from '../../../if-env/types/npm'; + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; + +describe('util/npm: ', () => { + const folderPath = path.resolve(__dirname, 'npm-test'); + + describe('initPackageJsonIfNotExists(): ', () => { + it('initializes package.json if it does not exist.', async () => { + process.env.NPM_INSTALL = 'npm init -y'; + isFileExists('true'); + + await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); + }); + + it('returns the package.json path if it exists.', async () => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + isFileExists('false'); + + const result = await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(result).toBe(packageJsonPath); + }); + }); + + describe('installDependencies(): ', () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + it('calls execPromise with the correct arguments.', async () => { + process.env.NPM_INSTALL = 'true'; + expect.assertions(1); + + await installDependencies(folderPath, dependencies); + }); + + it('logs the installation message.', async () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + await installDependencies(folderPath, dependencies); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); + }); + }); + + describe('updatePackageJsonDependencies(): ', () => { + it('successfully updates the package.json dependencies when cwd is false.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, false); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + + it('successfully updates the package.json dependencies when cwd is true.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, true); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + }); + + describe('extractPathsWithVersion(): ', () => { + it('extracts paths with correct versions.', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + '@commitlint/cli@18.6.0', + '@commitlint/config-conventional@18.6.0', + '@grnsft/if-core@0.0.7', + '@grnsft/if-plugins@v0.3.2', + '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', + '@jest/globals@29.7.0', + ]; + + const result = extractPathsWithVersion(plugins, dependencies); + + expect.assertions(1); + expect(result).toEqual({ + '@grnsft/if-plugins': '^v0.3.2', + '@grnsft/if-unofficial-plugins': '^v0.3.0', + }); + }); + + it('returns an empty object if no matches found', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + ]; + + expect.assertions(1); + const result = extractPathsWithVersion(plugins, dependencies); + expect(result).toEqual({}); + }); + }); + + describe('updatePackageJsonProperties(): ', () => { + it('updates the package.json properties correctly.', async () => { + const packageJsonPath = path.join(folderPath, 'package.json-npm1'); + + const expectedPackageJsonContent = JSON.stringify( + { + name: 'if-environment', + description: 'mock-description', + author: {}, + bugs: {}, + engines: {}, + homepage: 'mock-homepage', + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonProperties(packageJsonPath, true); + + expect.assertions(8); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + }); +}); From b0e1f47461041b7f4e8d2ba9d98fd7095d88b68a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:20:57 +0400 Subject: [PATCH 329/863] test(lib): init if-diff tests --- src/__tests__/if-diff/lib/compare.test.ts | 114 ++++++++++++++++++++++ src/__tests__/if-diff/lib/load.test.ts | 104 ++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 src/__tests__/if-diff/lib/compare.test.ts create mode 100644 src/__tests__/if-diff/lib/load.test.ts diff --git a/src/__tests__/if-diff/lib/compare.test.ts b/src/__tests__/if-diff/lib/compare.test.ts new file mode 100644 index 000000000..f43e7c590 --- /dev/null +++ b/src/__tests__/if-diff/lib/compare.test.ts @@ -0,0 +1,114 @@ +import {compare} from '../../../if-diff/lib/compare'; + +describe('lib/compare: ', () => { + describe('compare(): ', () => { + it('test if empty objects are equal.', () => { + const a = {}; + const b = {}; + + const response = compare(a, b); + expect(Object.keys(response).length).toEqual(0); + }); + + it('tests for nested objects with arrays.', () => { + const a = { + tree: { + inputs: [1, 2], + }, + }; + const b = { + tree: { + inputs: [1, 2], + }, + }; + + const response = compare(a, b); + expect(Object.keys(response).length).toEqual(0); + }); + + it('tests for nested objects with arrays (negative case).', () => { + const a = { + tree: { + inputs: [1, 2], + }, + }; + const b = { + tree: { + inputs: [1], + }, + }; + + const response = compare(a, b); + expect(response.path).toEqual('tree.inputs.1'); + expect(response.source).toEqual(2); + expect(response.target).toBeUndefined(); + }); + + it('checks if execution params are ignored.', () => { + const a = { + tree: { + inputs: [1, 2], + }, + execution: { + a: 'mock-a', + b: 'mock-b', + status: 'success', + }, + }; + const b = { + tree: { + inputs: [1, 2], + }, + execution: { + status: 'success', + }, + }; + + const response = compare(a, b); + expect(Object.keys(response).length).toEqual(0); + }); + + it('checks if error and status are in place, and others are ignored.', () => { + const a = { + tree: { + inputs: [1, 2], + }, + execution: { + a: 'a', + b: 'b', + error: 'mock-error-message', + status: 'fail', + }, + }; + const b = { + tree: { + inputs: [1, 2], + }, + execution: { + error: 'mock-error-message', + status: 'fail', + }, + }; + + const response = compare(a, b); + expect(Object.keys(response).length).toEqual(0); + }); + + it('checks if arrays are equal.', () => { + const a = [1, 2]; + const b = [1, 2]; + + const response = compare(a, b); + expect(Object.keys(response).length).toEqual(0); + }); + + it('checks if arrays are equal (first one is missing some items).', () => { + const a = [1]; + const b = [1, 2]; + + const response = compare(a, b); + const expectedResponse = {path: '1', source: undefined, target: 2}; + expect(response).toEqual(expectedResponse); + }); + }); +}); diff --git a/src/__tests__/if-diff/lib/load.test.ts b/src/__tests__/if-diff/lib/load.test.ts new file mode 100644 index 000000000..f722757e5 --- /dev/null +++ b/src/__tests__/if-diff/lib/load.test.ts @@ -0,0 +1,104 @@ +jest.mock('../../../if-run/util/json', () => + require('../../../__mocks__/json') +); +jest.mock( + 'mockavizta', + () => ({ + __esmodule: true, + Mockavizta: () => ({ + execute: (input: PluginParams) => input, + metadata: { + kind: 'execute', + }, + }), + }), + {virtual: true} +); +jest.mock('../../../if-diff/util/helpers', () => ({ + parseManifestFromStdin: () => { + if (process.env.readline === 'valid-source') { + return ` +name: 'mock-name' +description: 'mock-description' +`; + } + return ''; + }, +})); +jest.mock('../../../common/util/yaml', () => ({ + openYamlFileAsObject: (path: string) => { + switch (path) { + case 'load-default.yml': + return 'raw-manifest'; + case 'source-path.yml': + return 'source-manifest'; + case 'target-path.yml': + return 'target-manifest'; + default: + return ''; + } + }, +})); + +import {PluginParams} from '@grnsft/if-core/types'; + +import {loadIfDiffFiles} from '../../../if-diff/lib/load'; + +import {parseManifestFromStdin} from '../../../if-diff/util/helpers'; + +import {STRINGS} from '../../../if-diff/config'; + +import {LoadDiffParams} from '../../../if-diff/types/args'; + +const {INVALID_SOURCE} = STRINGS; + +describe('if-diff/lib/load: ', () => { + describe('loadIfDiffFiles(): ', () => { + it('rejects with invalid source error.', async () => { + const params = { + sourcePath: '', + targetPath: '', + }; + + try { + await loadIfDiffFiles(params); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe(INVALID_SOURCE); + } + } + }); + + it('successfully loads target, and source from stdin.', async () => { + process.env.readline = 'valid-source'; + const piped = await parseManifestFromStdin(); + const params: LoadDiffParams = { + targetPath: 'target-path.yml', + pipedSourceManifest: piped, + }; + + const response = await loadIfDiffFiles(params); + const expectedSource = { + name: 'mock-name', + description: 'mock-description', + }; + const expectedTarget = 'target-manifest'; + expect(response.rawSourceManifest).toEqual(expectedSource); + expect(response.rawTargetManifest).toEqual(expectedTarget); + }); + + it('successfully loads target, and source from stdin.', async () => { + const params = { + targetPath: 'target-path.yml', + sourcePath: 'source-path.yml', + }; + + const response = await loadIfDiffFiles(params); + const expectedSource = 'source-manifest'; + const expectedTarget = 'target-manifest'; + expect(response.rawSourceManifest).toEqual(expectedSource); + expect(response.rawTargetManifest).toEqual(expectedTarget); + }); + }); +}); From 710563c77297aa9f83c67fded7172b226ab677e1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:21:13 +0400 Subject: [PATCH 330/863] test(util): init if-check tests --- src/__tests__/if-check/util/args.test.ts | 179 ++++++++++++++++++++ src/__tests__/if-check/util/helpers.test.ts | 18 ++ src/__tests__/if-check/util/npm.test.ts | 54 ++++++ 3 files changed, 251 insertions(+) create mode 100644 src/__tests__/if-check/util/args.test.ts create mode 100644 src/__tests__/if-check/util/helpers.test.ts create mode 100644 src/__tests__/if-check/util/npm.test.ts diff --git a/src/__tests__/if-check/util/args.test.ts b/src/__tests__/if-check/util/args.test.ts new file mode 100644 index 000000000..de0f2a045 --- /dev/null +++ b/src/__tests__/if-check/util/args.test.ts @@ -0,0 +1,179 @@ +jest.mock('../../../common/util/fs', () => ({ + isFileExists: () => { + if (process.env.fileExists === 'true') { + return true; + } + return false; + }, + isDirectoryExists: () => { + if (process.env.directoryExists === 'true') { + return true; + } + return false; + }, +})); + +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + case 'manifest-is-provided': + return {manifest: 'mock-manifest.yaml'}; + case 'directory-is-provided': + return {directory: '/mock-directory'}; + case 'flags-are-not-provided': + return {manifest: undefined, directory: undefined}; + default: + return { + manifest: 'mock-manifest.yaml', + output: 'mock-output', + }; + } + }, +})); + +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + /** If-env mocks */ + case 'manifest-is-not-yaml': + return {manifest: 'manifest'}; + case 'env-throw-error': + throw new Error('mock-error'); + case 'env-throw': + throw 'mock-error'; + /** If-check */ + case 'manifest-is-provided': + return {manifest: 'mock-manifest.yaml'}; + case 'directory-is-provided': + return {directory: '/mock-directory'}; + case 'flags-are-not-provided': + return {manifest: undefined, directory: undefined}; + default: + return { + manifest: 'mock-manifest.yaml', + output: 'mock-output', + }; + } + }, +})); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {parseIfCheckArgs} from '../../../if-check/util/args'; + +import {STRINGS} from '../../../if-check/config'; +import {STRINGS as COMMON_STRINGS} from '../../../common/config'; + +const { + InvalidDirectoryError, + MissingCliFlagsError, + CliSourceFileError, + ParseCliParamsError, +} = ERRORS; +const {DIRECTORY_NOT_FOUND, IF_CHECK_FLAGS_MISSING} = STRINGS; +const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = COMMON_STRINGS; + +describe('if-check/util: ', () => { + const originalEnv = process.env; + + describe('parseIfCheckArgs(): ', () => { + it('executes when `manifest` is provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-provided'; + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({manifest: 'mock-manifest.yaml'}); + }); + + it('executes when the `directory` is provided.', async () => { + process.env.directoryExists = 'true'; + process.env.result = 'directory-is-provided'; + + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({directory: '/mock-directory'}); + }); + + it('throws an error when the `directory` does not exist.', async () => { + process.env.directoryExists = 'false'; + process.env.result = 'directory-is-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new InvalidDirectoryError(DIRECTORY_NOT_FOUND)); + } + }); + + it('throws an error when both `manifest` and `directory` flags are not provided.', async () => { + process.env.result = 'flags-are-not-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING)); + } + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + + process.env = originalEnv; +}); diff --git a/src/__tests__/if-check/util/helpers.test.ts b/src/__tests__/if-check/util/helpers.test.ts new file mode 100644 index 000000000..381c7534c --- /dev/null +++ b/src/__tests__/if-check/util/helpers.test.ts @@ -0,0 +1,18 @@ +import {logStdoutFailMessage} from '../../../if-check/util/helpers'; + +describe('logStdoutFailMessage(): ', () => { + it('successfully logs the failed message.', () => { + const errorMessage = {stdout: '\n\nmock error message'}; + const mockFilename = 'mock-filename.yaml'; + const logSpy = jest.spyOn(global.console, 'log'); + logStdoutFailMessage(errorMessage, mockFilename); + + expect.assertions(2); + + expect(logSpy).toHaveBeenCalledWith( + `✖ if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` + ); + + expect(logSpy).toHaveBeenCalledWith('mock error message'); + }); +}); diff --git a/src/__tests__/if-check/util/npm.test.ts b/src/__tests__/if-check/util/npm.test.ts new file mode 100644 index 000000000..4bdffc10f --- /dev/null +++ b/src/__tests__/if-check/util/npm.test.ts @@ -0,0 +1,54 @@ +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +const mockInfo = jest.fn(); + +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); +jest.mock('../../../common/util/logger', () => ({ + logger: { + info: mockInfo, + }, +})); + +jest.mock('../../../common/util/helpers', () => { + const originalModule = jest.requireActual('../../../common/util/helpers'); + return { + ...originalModule, + execPromise: async (param: any) => { + switch (process.env.NPM_INSTALL) { + case 'true': + expect(param).toEqual('npm install @grnsft/if@0.3.3-beta.0'); + break; + case 'npm init -y': + expect(param).toEqual('npm init -y'); + break; + case 'if-check': + expect(param).toEqual( + "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" + ); + break; + } + return; + }, + }; +}); + +import {executeCommands} from '../../../if-check/util/npm'; + +describe('if-check/util/npm: ', () => { + describe('executeCommands(): ', () => { + it('successfully executes with correct commands.', async () => { + process.env.NPM_INSTALL = 'if-check'; + const manifest = './src/__mocks__/mock-manifest.yaml'; + const logSpy = jest.spyOn(global.console, 'log'); + + await executeCommands(manifest, false); + + expect.assertions(2); + expect(logSpy).toHaveBeenCalledWith( + '✔ if-check successfully verified mock-manifest.yaml\n' + ); + }); + }); +}); From 7b993bec7f21e48749f634d631df2bc9e986b372 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:21:25 +0400 Subject: [PATCH 331/863] test(util): init common tests --- .../common/util/debug-logger.test.ts | 96 ++++++++++++ src/__tests__/common/util/fs.test.ts | 144 ++++++++++++++++++ src/__tests__/common/util/logger.test.ts | 11 ++ src/__tests__/common/util/yaml.test.ts | 74 +++++++++ 4 files changed, 325 insertions(+) create mode 100644 src/__tests__/common/util/debug-logger.test.ts create mode 100644 src/__tests__/common/util/fs.test.ts create mode 100644 src/__tests__/common/util/logger.test.ts create mode 100644 src/__tests__/common/util/yaml.test.ts diff --git a/src/__tests__/common/util/debug-logger.test.ts b/src/__tests__/common/util/debug-logger.test.ts new file mode 100644 index 000000000..affdca6c5 --- /dev/null +++ b/src/__tests__/common/util/debug-logger.test.ts @@ -0,0 +1,96 @@ +const logSpy = jest.spyOn(console, 'log'); +const infoSpy = jest.spyOn(console, 'info'); +const warnSpy = jest.spyOn(console, 'warn'); +const errorSpy = jest.spyOn(console, 'error'); +const debugSpy = jest.spyOn(console, 'debug'); + +import {debugLogger} from '../../../common/util/debug-logger'; + +describe('util/debug-logger: ', () => { + beforeEach(() => { + debugLogger.overrideConsoleMethods(true); + }); + + afterEach(() => { + logSpy.mockRestore(); + infoSpy.mockRestore(); + warnSpy.mockRestore(); + errorSpy.mockRestore(); + debugSpy.mockRestore(); + }); + + afterEach(() => { + debugLogger.setExecutingPluginName(); + }); + + it('overrides console methods and log messages with INFO level.', () => { + console.log('Starting IF'); + + expect(infoSpy).toHaveBeenCalledWith(expect.stringContaining('INFO:')); + }); + + it('does not override console method if the message starts with `# start`.', () => { + console.log('# start'); + + expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('# start')); + }); + + it('logs messages with WARN level.', () => { + console.warn('Test warn message'); + + expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('WARN:')); + }); + + it('logs messages with ERROR level.', () => { + console.error('Test error message'); + + expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('ERROR:')); + }); + + it('logs messages with DEBUG level.', () => { + console.debug('Test debug message'); + + expect(debugSpy).toHaveBeenCalledWith(expect.stringContaining('DEBUG:')); + }); + + it('includes plugin name in log messages when set.', () => { + debugLogger.setExecutingPluginName('TestPlugin'); + + console.log('Test message with plugin'); + + expect(infoSpy).toHaveBeenCalledWith( + expect.stringContaining('TestPlugin:') + ); + }); + + it('not includes plugin name in log messages when removed.', () => { + debugLogger.setExecutingPluginName(); + + console.log('Test message without plugin'); + + expect(infoSpy).not.toHaveBeenCalledWith( + expect.stringContaining('TestPlugin:') + ); + }); + + it('not logs messages when debugMode is false.', () => { + debugLogger.overrideConsoleMethods(false); + console.log('Test message when debugMode is false'); + + expect(infoSpy).not.toHaveBeenCalled(); + }); + + it('drops off the log message with DEBUG level when the `debug` command is not provided.', () => { + debugLogger.overrideConsoleMethods(false); + console.debug('Test debug message'); + + expect(debugSpy).not.toHaveBeenCalled(); + }); + + it('drops off the log message from the STRINGS when the `debug` command is not provided.', () => { + debugLogger.overrideConsoleMethods(false); + console.info('Starting Impact framework'); + + expect(debugSpy).not.toHaveBeenCalled(); + }); +}); diff --git a/src/__tests__/common/util/fs.test.ts b/src/__tests__/common/util/fs.test.ts new file mode 100644 index 000000000..643d80df3 --- /dev/null +++ b/src/__tests__/common/util/fs.test.ts @@ -0,0 +1,144 @@ +import * as fs from 'fs/promises'; + +import { + getFileName, + isDirectoryExists, + isFileExists, + getYamlFiles, + removeFileIfExists, +} from '../../../common/util/fs'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +describe('util/fs: ', () => { + describe('isFileExists(): ', () => { + it('returns true if the file exists.', async () => { + const result = await isFileExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns fale if the file does not exist.', async () => { + const result = await isFileExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('isDirectoryExists(): ', () => { + it('returns true if directory exists.', async () => { + const result = await isDirectoryExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns false if directory does not exist.', async () => { + const result = await isDirectoryExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('getFileName(): ', () => { + it('returns the file name without extension for a file with an extension.', () => { + const filePath = '/path/to/file/example.yaml'; + const result = getFileName(filePath); + + expect.assertions(1); + expect(result).toBe('example'); + }); + + it('returns the file name without extension for a file with multiple dots.', () => { + const filePath = '/path/to/file/example.test.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example.test'); + }); + + it('returns the file name as is if there is no extension.', () => { + const filePath = '/path/to/file/example'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles file names with special characters.', () => { + const filePath = + '/path/to/file/complex-file.name.with-multiple.parts.yaml'; + const result = getFileName(filePath); + expect(result).toBe('complex-file.name.with-multiple.parts'); + }); + + it('handles file names with no path.', () => { + const filePath = 'example.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles empty string as file path.', () => { + const filePath = ''; + const result = getFileName(filePath); + expect(result).toBe(''); + }); + }); + + describe('getYamlFiles(): ', () => { + it('returns an empty array if the directory is empty.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + const result = await getYamlFiles('/mock-empty-directory'); + + expect(result).toEqual([]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-empty-directory'); + }); + + it('returns YAML files in the directory', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + + const result = await getYamlFiles('/mock-directory'); + expect.assertions(2); + expect(result).toEqual([ + '/mock-directory/file1.yaml', + '/mock-directory/file2.yml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + + it('recursively finds YAML files in nested directories.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + const result = await getYamlFiles('/mock-sub-directory'); + + expect.assertions(2); + expect(result).toEqual([ + '/mock-sub-directory/subdir/file2.yml', + '/mock-sub-directory/file1.yaml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + }); + + describe('removeFileIfExists(): ', () => { + it('successfully delete file if exists.', async () => { + await isFileExists('true'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + + it('does not throw an error if the file not exists.', async () => { + await isFileExists('false'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + }); +}); diff --git a/src/__tests__/common/util/logger.test.ts b/src/__tests__/common/util/logger.test.ts new file mode 100644 index 000000000..6d7e89ada --- /dev/null +++ b/src/__tests__/common/util/logger.test.ts @@ -0,0 +1,11 @@ +import {Logger} from 'winston'; + +import {logger} from '../../../common/util/logger'; + +describe('util/logger: ', () => { + describe('logger(): ', () => { + it('is instance of winston logger.', () => { + expect(logger).toBeInstanceOf(Logger); + }); + }); +}); diff --git a/src/__tests__/common/util/yaml.test.ts b/src/__tests__/common/util/yaml.test.ts new file mode 100644 index 000000000..7ad06e13f --- /dev/null +++ b/src/__tests__/common/util/yaml.test.ts @@ -0,0 +1,74 @@ +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +import { + checkIfFileIsYaml, + openYamlFileAsObject, + saveYamlFileAs, +} from '../../../common/util/yaml'; + +describe('util/yaml: ', () => { + describe('checkIfFileIsYaml(): ', () => { + it('returns false, in case of not yaml file.', () => { + const fileName = 'mock-filename'; + + const check = checkIfFileIsYaml(fileName); + expect(check).toBeFalsy(); + }); + + it('returns true, in case of `yml` file.', () => { + const fileName = 'mock-filename.yml'; + + const check = checkIfFileIsYaml(fileName); + expect(check).toBeTruthy(); + }); + + it('returns true, in case of `yaml` file.', () => { + const fileName = 'mock-filename.yaml'; + + const check = checkIfFileIsYaml(fileName); + expect(check).toBeTruthy(); + }); + }); + + describe('openYamlFileAsObject(): ', () => { + it('should load and serve yaml as object.', async () => { + expect.assertions(2); + + const result = await openYamlFileAsObject('mock'); + const expectedType = 'object'; + const expectedYamlName = 'gsf-demo'; + + expect(typeof result).toBe(expectedType); + expect(result.name).toBe(expectedYamlName); + }); + }); + + describe('saveYamlFileAs(): ', () => { + it('saves yaml file with passed object and path.', async () => { + const object = { + name: 'mock-name', + }; + const pathToFile = 'mock-pathToFile'; + + await saveYamlFileAs(object, pathToFile); + }); + + it('throws error in case if something wrong with path.', async () => { + const object = { + name: 'mock-name', + }; + const pathToFile = 'reject'; // Mock value for rejection. + + const expectedErrorMessage = 'Wrong file path'; + + try { + await saveYamlFileAs(object, pathToFile); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe(expectedErrorMessage); + } + } + }); + }); +}); From 3e899aab8003a73c4b25410b2d39974727599aea Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:21:37 +0400 Subject: [PATCH 332/863] test(lib): init common tests --- src/__tests__/common/lib/load.test.ts | 89 +++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/__tests__/common/lib/load.test.ts diff --git a/src/__tests__/common/lib/load.test.ts b/src/__tests__/common/lib/load.test.ts new file mode 100644 index 000000000..43f6ee2af --- /dev/null +++ b/src/__tests__/common/lib/load.test.ts @@ -0,0 +1,89 @@ +jest.mock('../../../if-run/util/json', () => + require('../../../__mocks__/json') +); +jest.mock( + 'mockavizta', + () => ({ + __esmodule: true, + Mockavizta: () => ({ + execute: (input: PluginParams) => input, + metadata: { + kind: 'execute', + }, + }), + }), + {virtual: true} +); +jest.mock('../../../if-diff/util/helpers', () => ({ + parseManifestFromStdin: () => { + if (process.env.readline === 'valid-source') { + return ` +name: 'mock-name' +description: 'mock-description' +`; + } + return ''; + }, +})); +jest.mock('../../../common/util/yaml', () => ({ + openYamlFileAsObject: (path: string) => { + switch (path) { + case 'load-default.yml': + return 'raw-manifest'; + case 'source-path.yml': + return 'source-manifest'; + case 'target-path.yml': + return 'target-manifest'; + default: + return ''; + } + }, +})); + +import {PluginParams} from '@grnsft/if-core/types'; + +import {PARAMETERS} from '../../../if-run/config'; +import {load} from '../../../common/lib/load'; + +describe('lib/load: ', () => { + describe('load(): ', () => { + it('loads yaml with default parameters.', async () => { + const inputPath = 'load-default.yml'; + const paramPath = undefined; + + const result = await load(inputPath, paramPath); + + const expectedValue = { + rawManifest: 'raw-manifest', + parameters: PARAMETERS, + }; + + expect(result).toEqual(expectedValue); + }); + + it('loads yaml with custom parameters.', async () => { + const inputPath = 'load-default.yml'; + const paramPath = 'param-mock.json'; + + const result = await load(inputPath, paramPath); + + const expectedValue = { + rawManifest: 'raw-manifest', + parameters: { + 'mock-carbon': { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + aggregation: 'sum', + }, + 'mock-cpu': { + description: 'number of cores available', + unit: 'cores', + aggregation: 'none', + }, + }, + }; + + expect(result).toEqual(expectedValue); + }); + }); +}); From 1c40fb764a84fede70b3bb9c3e3b33d70bb1fd11 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:21:48 +0400 Subject: [PATCH 333/863] revert(src): drop old entry files --- src/check.ts | 89 ---------------------------------------------------- src/diff.ts | 54 ------------------------------- src/env.ts | 50 ----------------------------- src/index.ts | 54 ------------------------------- 4 files changed, 247 deletions(-) delete mode 100644 src/check.ts delete mode 100644 src/diff.ts delete mode 100644 src/env.ts delete mode 100644 src/index.ts diff --git a/src/check.ts b/src/check.ts deleted file mode 100644 index f1e8f0cdd..000000000 --- a/src/check.ts +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-process-exit */ -import * as path from 'path'; - -import {logger} from './util/logger'; -import {logStdoutFailMessage} from './util/helpers'; -import {parseIfCheckArgs} from './util/args'; -import {getYamlFiles, removeFileIfExists} from './util/fs'; - -import {STRINGS} from './config'; -import {executeCommands} from './util/npm'; - -const { - CHECKING, - DIRECTORY_YAML_FILES_NOT_FOUND, - IF_CHECK_VERIFICATION_FAILURES, - IF_CHECK_SUMMARY_LOG, - IF_CHECK_EXECUTING, -} = STRINGS; - -const IfCheck = async () => { - const commandArgs = await parseIfCheckArgs(); - - console.log(`${CHECKING}\n`); - - if (commandArgs.manifest) { - const manifest = commandArgs.manifest; - - try { - await executeCommands(manifest, false); - } catch (error: any) { - const fileName = path.basename(manifest); - const executedFile = manifest - .replace(fileName, `re-${fileName}`) - .replace('yml', 'yaml'); - const manifestDirPath = path.dirname(manifest); - - logStdoutFailMessage(error, fileName); - - await removeFileIfExists(`${manifestDirPath}/package.json`); - await removeFileIfExists(executedFile); - } - } else { - const failedLogs = {count: 0, message: ''}; - const directory = commandArgs.directory; - const files = await getYamlFiles(directory!); - - if (files.length === 0) { - console.log(DIRECTORY_YAML_FILES_NOT_FOUND); - process.exit(1); - } - - for await (const file of files) { - const fileName = path.basename(file); - console.log(IF_CHECK_EXECUTING(fileName)); - - try { - await executeCommands(file, true); - } catch (error: any) { - const fileName = path.basename(file); - const executedFile = file - .replace(fileName, `re-${fileName}`) - .replace('yml', 'yaml'); - - const failedFilesLog = logStdoutFailMessage(error, fileName); - failedLogs.message = failedLogs.message.concat(failedFilesLog); - failedLogs.count++; - - await removeFileIfExists(executedFile); - } - } - - if (failedLogs.count > 0) { - const passedFilesCount = files.length - failedLogs.count; - - console.log(IF_CHECK_VERIFICATION_FAILURES); - console.log(failedLogs.message); - console.log(IF_CHECK_SUMMARY_LOG(passedFilesCount, files.length)); - process.exit(1); - } - } -}; - -IfCheck().catch(error => { - if (error instanceof Error) { - logger.error(error); - process.exit(2); - } -}); diff --git a/src/diff.ts b/src/diff.ts deleted file mode 100644 index aad02482c..000000000 --- a/src/diff.ts +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-process-exit */ -import {loadIfDiffFiles} from './lib/load'; -import {compare} from './lib/compare'; - -import {parseIfDiffArgs} from './util/args'; -import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; -import {validateManifest} from './util/validations'; - -import {logger} from './util/logger'; -import {debugLogger} from './util/debug-logger'; - -import {CONFIG} from './config'; - -const {IF_DIFF} = CONFIG; -const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; - -const IfDiff = async () => { - const pipedSourceManifest = await parseManifestFromStdin(); - const {sourcePath, targetPath} = parseIfDiffArgs(); - - // Call this function with false parameter to prevent log debug messages. - debugLogger.overrideConsoleMethods(false); - - const {rawSourceManifest, rawTargetManifest} = await loadIfDiffFiles({ - targetPath, - sourcePath, - pipedSourceManifest, - }); - const [sourceManifest, targetManifest] = [ - rawSourceManifest, - rawTargetManifest, - ].map(validateManifest); - const result = compare(sourceManifest, targetManifest); - - if (Object.keys(result).length) { - formatNotMatchingLog({ - message: FAILURE_MESSAGE, - ...result, - }); - - process.exit(1); - } - - console.log(SUCCESS_MESSAGE); - process.exit(0); -}; - -IfDiff().catch(error => { - if (error instanceof Error) { - logger.error(error); - process.exit(2); - } -}); diff --git a/src/env.ts b/src/env.ts deleted file mode 100644 index 48b0b76b9..000000000 --- a/src/env.ts +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env node -/* eslint-disable no-process-exit */ -import {parseIfEnvArgs} from './util/args'; -import {logger} from './util/logger'; - -import {CONFIG} from './config'; - -import {EnvironmentOptions} from './types/if-env'; -import { - addTemplateManifest, - getOptionsFromArgs, - initializeAndInstallLibs, -} from './util/helpers'; - -const {IF_ENV} = CONFIG; -const {SUCCESS_MESSAGE} = IF_ENV; - -const IfEnv = async () => { - const commandArgs = await parseIfEnvArgs(); - const options: EnvironmentOptions = { - folderPath: process.env.CURRENT_DIR || process.cwd(), - install: !!commandArgs.install, - dependencies: {}, - cwd: !!commandArgs.cwd, - }; - - if (commandArgs && commandArgs.manifest) { - const {folderPath, install, dependencies} = - await getOptionsFromArgs(commandArgs); - options.folderPath = commandArgs.cwd ? options.folderPath : folderPath; - options.install = !!install; - options.dependencies = {...dependencies}; - } - - await initializeAndInstallLibs(options); - - if (!commandArgs || !commandArgs.manifest) { - await addTemplateManifest(options.folderPath); - } - - console.log(SUCCESS_MESSAGE); - process.exit(0); -}; - -IfEnv().catch(error => { - if (error instanceof Error) { - logger.error(error); - process.exit(2); - } -}); diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index e0d87009c..000000000 --- a/src/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node -import {aggregate} from './lib/aggregate'; -import {compute} from './lib/compute'; -import {injectEnvironment} from './lib/environment'; -import {exhaust} from './lib/exhaust'; -import {initialize} from './lib/initialize'; -import {load} from './lib/load'; -import {parameterize} from './lib/parameterize'; - -import {debugLogger} from './util/debug-logger'; -import {parseIEProcessArgs} from './util/args'; -import {andHandle} from './util/helpers'; -import {logger} from './util/logger'; -import {validateManifest} from './util/validations'; - -import {STRINGS} from './config'; - -const {DISCLAIMER_MESSAGE, EXITING_IF, STARTING_IF} = STRINGS; - -const impactEngine = async () => { - const options = parseIEProcessArgs(); - const {inputPath, paramPath, outputOptions, debug} = options; - - debugLogger.overrideConsoleMethods(!!debug); - - logger.info(DISCLAIMER_MESSAGE); - console.info(STARTING_IF); - - const {rawManifest, parameters} = await load(inputPath, paramPath); - const envManifest = await injectEnvironment(rawManifest); - - try { - const {tree, ...context} = validateManifest(envManifest); - parameterize.combine(context.params, parameters); - const pluginStorage = await initialize(context.initialize.plugins); - const computedTree = await compute(tree, {context, pluginStorage}); - const aggregatedTree = aggregate(computedTree, context.aggregation); - await exhaust(aggregatedTree, context, outputOptions); - } catch (error) { - if (error instanceof Error) { - envManifest.execution!.status = 'fail'; - envManifest.execution!.error = error.toString(); - logger.error(error); - const {tree, ...context} = envManifest; - - if (error.name !== 'ExhaustError') { - exhaust(tree, context, outputOptions); - } - } - } - console.info(EXITING_IF); -}; - -impactEngine().catch(andHandle); From d1076cdb43d980e581bd68a7c7fee23e2a934fb0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:22:08 +0400 Subject: [PATCH 334/863] fix(mocks): import path in export csv --- src/__mocks__/builtins/export-csv.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__mocks__/builtins/export-csv.ts b/src/__mocks__/builtins/export-csv.ts index 1f0e00e73..66ba6ea3c 100644 --- a/src/__mocks__/builtins/export-csv.ts +++ b/src/__mocks__/builtins/export-csv.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import {Context} from '../../types/manifest'; + +import {Context} from '../../common/types/manifest'; export const tree = { children: { From 5a4fc66be5944372df829a82721c88536e21a7c3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:26:01 +0400 Subject: [PATCH 335/863] fix(config): tune jest ignore patterns --- jest.config.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/jest.config.js b/jest.config.js index 016be5863..51f0cf3a6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -10,10 +10,6 @@ module.exports = { }, ], }, - modulePathIgnorePatterns: [ - './build', - './src/__tests__/integration/helpers', - './src/__tests__/integration/test-data', - ], - coveragePathIgnorePatterns: ['src/config', 'src/types'], + modulePathIgnorePatterns: ['./build'], + coveragePathIgnorePatterns: ['src/.*/config/.*', 'src/.*/types/.*'], }; From e40f94bf5e646501fbae913c49dba91520f58d44 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 14:28:51 +0400 Subject: [PATCH 336/863] revert(manifests): drop outputs folder --- outputs/examples/copy.yaml | 69 ------- outputs/examples/generics.yaml | 240 ------------------------ outputs/examples/instance-metadata.yaml | 99 ---------- 3 files changed, 408 deletions(-) delete mode 100644 outputs/examples/copy.yaml delete mode 100644 outputs/examples/generics.yaml delete mode 100644 outputs/examples/instance-metadata.yaml diff --git a/outputs/examples/copy.yaml b/outputs/examples/copy.yaml deleted file mode 100644 index 6b088ab99..000000000 --- a/outputs/examples/copy.yaml +++ /dev/null @@ -1,69 +0,0 @@ -name: copy-param -description: null -tags: null -initialize: - plugins: - copy-param: - path: builtin - method: Copy - global-config: - keep-existing: true - from: original - to: copy - outputs: - - yaml -execution: - command: >- - /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node - /Users/admin/Projects/uk/if/src/index.ts --manifest - manifests/examples/copy.yaml --output outputs/examples/copy - environment: - if-version: 0.4.0 - os: macOS - os-version: 14.3.1 - node-version: 18.19.0 - date-time: 2024-06-30T07:53:07.361Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child-1: - pipeline: - - copy-param - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - original: hello - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - original: hello - copy: hello diff --git a/outputs/examples/generics.yaml b/outputs/examples/generics.yaml deleted file mode 100644 index 2408d6b3d..000000000 --- a/outputs/examples/generics.yaml +++ /dev/null @@ -1,240 +0,0 @@ -name: generics -description: >- - a pipeline that does arbitrary calculations using our generic arithmetic - builtins -tags: null -initialize: - plugins: - interpolate: - path: builtin - method: Interpolation - 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-factor - cpu-factor-to-wattage: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - wattage-times-duration: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - wattage-to-energy-kwh: - path: builtin - method: Divide - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - calculate-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - coefficient: - path: builtin - method: Coefficient - global-config: - input-parameter: cpu-energy-kwh - coefficient: 2 - output-parameter: energy-doubled - multiply: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu/utilization - - duration - output-parameter: cpu-times-duration - outputs: - - yaml -execution: - command: >- - /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node - /Users/admin/Projects/uk/if/src/index.ts --manifest - manifests/examples/generics.yml --output outputs/examples/generics - environment: - if-version: 0.4.0 - os: macOS - os-version: 14.3.1 - node-version: 18.19.0 - date-time: 2024-06-30T07:53:53.523Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child-1: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - coefficient - - multiply - config: null - defaults: - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 50 - network/energy: 10 - energy: 5 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - network/energy: 10 - energy: 5 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 50 - network/energy: 10 - energy: 5 - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0.75 - cpu-wattage: 75 - cpu-wattage-times-duration: 75 - cpu-energy-raw: 0.000020833333333333333 - vcpu-ratio: 8 - cpu-energy-kwh: 0.0000026041666666666666 - energy-doubled: 0.000005208333333333333 - cpu-times-duration: 50 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0.4275 - cpu-wattage: 42.75 - cpu-wattage-times-duration: 213.75 - cpu-energy-raw: 0.000059375 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000007421875 - energy-doubled: 0.00001484375 - cpu-times-duration: 100 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 10 - energy: 5 - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0.37375 - cpu-wattage: 37.375 - cpu-wattage-times-duration: 261.625 - cpu-energy-raw: 0.00007267361111111111 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009084201388888889 - energy-doubled: 0.000018168402777777778 - cpu-times-duration: 105 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - network/energy: 10 - energy: 5 - cpu/thermal-design-power: 100 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0.37375 - cpu-wattage: 37.375 - cpu-wattage-times-duration: 1121.25 - cpu-energy-raw: 0.00031145833333333335 - vcpu-ratio: 8 - cpu-energy-kwh: 0.00003893229166666667 - energy-doubled: 0.00007786458333333334 - cpu-times-duration: 450 diff --git a/outputs/examples/instance-metadata.yaml b/outputs/examples/instance-metadata.yaml deleted file mode 100644 index 41baa0b58..000000000 --- a/outputs/examples/instance-metadata.yaml +++ /dev/null @@ -1,99 +0,0 @@ -name: csv-demo -description: null -tags: null -initialize: - plugins: - cloud-instance-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: cloud/instance-type - output: '*' - extract-processor-name: - path: builtin - method: Regex - global-config: - parameter: cpu-model-name - match: /^([^,])+/g - output: cpu/name - outputs: - - yaml -execution: - command: >- - /Users/admin/.nvm/versions/node/v18.19.0/bin/ts-node - /Users/admin/Projects/uk/if/src/index.ts --manifest - manifests/examples/instance-metadata.yml --output - outputs/examples/instance-metadata - environment: - if-version: 0.4.0 - os: macOS - os-version: 14.3.1 - node-version: 18.19.0 - date-time: 2024-06-30T07:54:34.384Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child: - pipeline: - - cloud-instance-metadata - - extract-processor-name - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - cloud/provider: gcp - cloud/region: asia-east - cloud/instance-type: Standard_A1_v2 - outputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/energy: 0.001 - cloud/provider: gcp - cloud/region: asia-east - cloud/instance-type: Standard_A1_v2 - cpu-cores-available: 52 - cpu-cores-utilized: 1 - cpu-manufacturer: Intel - cpu-model-name: >- - 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 - cpu-tdp: 205 - gpu-count: nan - gpu-model-name: nan - gpu-tdp: nan - memory-available: 2 - cpu/name: Intel® Xeon® Platinum 8272CL From 072b53190a531539d2b19e4c37a8dd7b972d01bd Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 5 Jul 2024 14:32:12 +0400 Subject: [PATCH 337/863] fix(src): fix if-check file path to be relative --- src/check.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/check.ts b/src/check.ts index f1e8f0cdd..f69d8fa08 100644 --- a/src/check.ts +++ b/src/check.ts @@ -51,8 +51,11 @@ const IfCheck = async () => { } for await (const file of files) { - const fileName = path.basename(file); - console.log(IF_CHECK_EXECUTING(fileName)); + const fileRelativePath = path.relative( + process.env.CURRENT_DIR || process.cwd(), + file + ); + console.log(IF_CHECK_EXECUTING(fileRelativePath)); try { await executeCommands(file, true); From ab42df2e4d00ec38ed2d09608c796fcd010aa7fd Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 14:39:53 +0400 Subject: [PATCH 338/863] fix(manifests): add * as a value to mock obs group by --- .../outputs/pipelines/mock-obs-groupby.yaml | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml index 4783dffde..030d2dd05 100644 --- a/manifests/outputs/pipelines/mock-obs-groupby.yaml +++ b/manifests/outputs/pipelines/mock-obs-groupby.yaml @@ -94,42 +94,42 @@ tree: cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 12 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:10.000Z' duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 71 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:20.000Z' duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 75 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:30.000Z' duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 39 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:40.000Z' duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 42 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:50.000Z' duration: 10 name: server-1 cloud/instance-type: Standard_E64_v3 cloud/region: westus3 cloud/vendor: azure - cpu/utilization: 98 + cpu/utilization: '*' france: children: server-2: @@ -140,39 +140,39 @@ tree: cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 14 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:10.000Z' duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 80 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:20.000Z' duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 53 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:30.000Z' duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 10 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:40.000Z' duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 40 + cpu/utilization: '*' - timestamp: '2024-03-05T00:00:50.000Z' duration: 10 name: server-2 cloud/instance-type: Standard_E64_v3 cloud/region: france cloud/vendor: azure - cpu/utilization: 92 + cpu/utilization: '*' From 5b29cf0551ca00e3499ae5fca273f2c2b2261b2b Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 14:43:07 +0400 Subject: [PATCH 339/863] revert(manifests): drop groupby success case --- .../outputs/plugins/groupby/success.yaml | 101 ------------------ 1 file changed, 101 deletions(-) delete mode 100644 manifests/outputs/plugins/groupby/success.yaml diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml deleted file mode 100644 index 04d54837b..000000000 --- a/manifests/outputs/plugins/groupby/success.yaml +++ /dev/null @@ -1,101 +0,0 @@ -name: groupby -description: successful path -initialize: - plugins: - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/groupby/success.yml -o - manifests/outputs/plugins/groupby/success - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T19:08:31.858Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - cloud/instance-type - children: - uk-west: - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 From 055b14f617c40e8cc10c31c3023d204f65e868ec Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 14:47:55 +0400 Subject: [PATCH 340/863] fix(manifests): remove extraneous plugins --- .../cloud-metadata/failure-missing-cloud-vendor.yaml | 6 +----- .../outputs/plugins/csv-lookup/cloud-metadata/success.yaml | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index adc1705eb..074d1a4b0 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -35,11 +35,7 @@ execution: - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models + - '@grnsft/if-core@0.0.10' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml index 59a6d9739..73c459201 100644 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -34,10 +34,6 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.1 extraneous -> - file:../../../../if-unofficial-models - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' From ea9a86f65b867665efee68b7a8da2d616912fabf Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 14:52:52 +0400 Subject: [PATCH 341/863] fix(manifests): add * as a pu util value to mock obs group by cloud meta --- .../mock-obs-group-by-cloud-meta.yaml | 174 +++++++++--------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml index 5585d4c42..74389a65a 100644 --- a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml +++ b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml @@ -115,7 +115,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 93 + cpu/utilization: '*' - timestamp: '2024-03-05T00:05:00.000Z' duration: 300 name: server-1 @@ -123,7 +123,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 6 + cpu/utilization: '*' - timestamp: '2024-03-05T00:10:00.000Z' duration: 300 name: server-1 @@ -131,7 +131,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 6 + cpu/utilization: '*' - timestamp: '2024-03-05T00:15:00.000Z' duration: 300 name: server-1 @@ -139,7 +139,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 3 + cpu/utilization: '*' - timestamp: '2024-03-05T00:20:00.000Z' duration: 300 name: server-1 @@ -155,7 +155,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 85 + cpu/utilization: '*' - timestamp: '2024-03-05T00:30:00.000Z' duration: 300 name: server-1 @@ -163,7 +163,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 8 + cpu/utilization: '*' - timestamp: '2024-03-05T00:35:00.000Z' duration: 300 name: server-1 @@ -171,7 +171,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 59 + cpu/utilization: '*' - timestamp: '2024-03-05T00:40:00.000Z' duration: 300 name: server-1 @@ -179,7 +179,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 55 + cpu/utilization: '*' - timestamp: '2024-03-05T00:45:00.000Z' duration: 300 name: server-1 @@ -187,7 +187,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 85 + cpu/utilization: '*' - timestamp: '2024-03-05T00:50:00.000Z' duration: 300 name: server-1 @@ -195,7 +195,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 52 + cpu/utilization: '*' - timestamp: '2024-03-05T00:55:00.000Z' duration: 300 name: server-1 @@ -203,7 +203,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 54 + cpu/utilization: '*' outputs: - timestamp: '2024-03-05T00:00:00.000Z' duration: 300 @@ -212,7 +212,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 93 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:05:00.000Z' duration: 300 @@ -221,7 +221,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 6 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:10:00.000Z' duration: 300 @@ -230,7 +230,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 6 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:15:00.000Z' duration: 300 @@ -239,7 +239,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 3 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:20:00.000Z' duration: 300 @@ -248,7 +248,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 83 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:25:00.000Z' duration: 300 @@ -257,7 +257,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 85 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:30:00.000Z' duration: 300 @@ -266,7 +266,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 8 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:35:00.000Z' duration: 300 @@ -284,7 +284,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 55 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:45:00.000Z' duration: 300 @@ -293,7 +293,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 85 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:50:00.000Z' duration: 300 @@ -302,7 +302,7 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 52 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:55:00.000Z' duration: 300 @@ -311,49 +311,49 @@ tree: cloud/region: eastus geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 54 + cpu/utilization: '*' cpu-tdp: 270 aggregated: - cpu/utilization: 49.083333333333336 + cpu/utilization: '*' outputs: - - cpu/utilization: 93 + - cpu/utilization: '*' timestamp: '2024-03-05T00:00:00.000Z' duration: 300 - - cpu/utilization: 6 + - cpu/utilization: '*' timestamp: '2024-03-05T00:05:00.000Z' duration: 300 - - cpu/utilization: 6 + - cpu/utilization: '*' timestamp: '2024-03-05T00:10:00.000Z' duration: 300 - - cpu/utilization: 3 + - cpu/utilization: '*' timestamp: '2024-03-05T00:15:00.000Z' duration: 300 - - cpu/utilization: 83 + - cpu/utilization: '*' timestamp: '2024-03-05T00:20:00.000Z' duration: 300 - - cpu/utilization: 85 + - cpu/utilization: '*' timestamp: '2024-03-05T00:25:00.000Z' duration: 300 - - cpu/utilization: 8 + - cpu/utilization: '*' timestamp: '2024-03-05T00:30:00.000Z' duration: 300 - - cpu/utilization: 59 + - cpu/utilization: '*' timestamp: '2024-03-05T00:35:00.000Z' duration: 300 - - cpu/utilization: 55 + - cpu/utilization: '*' timestamp: '2024-03-05T00:40:00.000Z' duration: 300 - - cpu/utilization: 85 + - cpu/utilization: '*' timestamp: '2024-03-05T00:45:00.000Z' duration: 300 - - cpu/utilization: 52 + - cpu/utilization: '*' timestamp: '2024-03-05T00:50:00.000Z' duration: 300 - - cpu/utilization: 54 + - cpu/utilization: '*' timestamp: '2024-03-05T00:55:00.000Z' duration: 300 aggregated: - cpu/utilization: 49.083333333333336 + cpu/utilization: '*' server-2: children: Standard_E64_v3: @@ -365,7 +365,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 4 + cpu/utilization: '*' - timestamp: '2024-03-05T00:05:00.000Z' duration: 300 name: server-2 @@ -373,7 +373,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 63 + cpu/utilization: '*' - timestamp: '2024-03-05T00:10:00.000Z' duration: 300 name: server-2 @@ -381,7 +381,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 38 + cpu/utilization: '*' - timestamp: '2024-03-05T00:15:00.000Z' duration: 300 name: server-2 @@ -389,7 +389,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 10 + cpu/utilization: '*' - timestamp: '2024-03-05T00:20:00.000Z' duration: 300 name: server-2 @@ -397,7 +397,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 88 + cpu/utilization: '*' - timestamp: '2024-03-05T00:25:00.000Z' duration: 300 name: server-2 @@ -405,7 +405,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 81 + cpu/utilization: '*' - timestamp: '2024-03-05T00:30:00.000Z' duration: 300 name: server-2 @@ -413,7 +413,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 17 + cpu/utilization: '*' - timestamp: '2024-03-05T00:35:00.000Z' duration: 300 name: server-2 @@ -421,7 +421,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 11 + cpu/utilization: '*' - timestamp: '2024-03-05T00:40:00.000Z' duration: 300 name: server-2 @@ -429,7 +429,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 76 + cpu/utilization: '*' - timestamp: '2024-03-05T00:45:00.000Z' duration: 300 name: server-2 @@ -437,7 +437,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 63 + cpu/utilization: '*' - timestamp: '2024-03-05T00:50:00.000Z' duration: 300 name: server-2 @@ -445,7 +445,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 81 + cpu/utilization: '*' - timestamp: '2024-03-05T00:55:00.000Z' duration: 300 name: server-2 @@ -453,7 +453,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 74 + cpu/utilization: '*' outputs: - timestamp: '2024-03-05T00:00:00.000Z' duration: 300 @@ -462,7 +462,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 4 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:05:00.000Z' duration: 300 @@ -471,7 +471,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 63 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:10:00.000Z' duration: 300 @@ -480,7 +480,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 38 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:15:00.000Z' duration: 300 @@ -489,7 +489,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 10 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:20:00.000Z' duration: 300 @@ -498,7 +498,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 88 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:25:00.000Z' duration: 300 @@ -507,7 +507,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 81 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:30:00.000Z' duration: 300 @@ -516,7 +516,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 17 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:35:00.000Z' duration: 300 @@ -525,7 +525,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 11 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:40:00.000Z' duration: 300 @@ -534,7 +534,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 76 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:45:00.000Z' duration: 300 @@ -543,7 +543,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 63 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:50:00.000Z' duration: 300 @@ -552,7 +552,7 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 81 + cpu/utilization: '*' cpu-tdp: 270 - timestamp: '2024-03-05T00:55:00.000Z' duration: 300 @@ -561,85 +561,85 @@ tree: cloud/region: france geolocation: 37.7749,-122.4194 cloud/vendor: azure - cpu/utilization: 74 + cpu/utilization: '*' cpu-tdp: 270 aggregated: - cpu/utilization: 50.5 + cpu/utilization: '*' outputs: - - cpu/utilization: 4 + - cpu/utilization: '*' timestamp: '2024-03-05T00:00:00.000Z' duration: 300 - - cpu/utilization: 63 + - cpu/utilization: '*' timestamp: '2024-03-05T00:05:00.000Z' duration: 300 - - cpu/utilization: 38 + - cpu/utilization: '*' timestamp: '2024-03-05T00:10:00.000Z' duration: 300 - - cpu/utilization: 10 + - cpu/utilization: '*' timestamp: '2024-03-05T00:15:00.000Z' duration: 300 - - cpu/utilization: 88 + - cpu/utilization: '*' timestamp: '2024-03-05T00:20:00.000Z' duration: 300 - - cpu/utilization: 81 + - cpu/utilization: '*' timestamp: '2024-03-05T00:25:00.000Z' duration: 300 - - cpu/utilization: 17 + - cpu/utilization: '*' timestamp: '2024-03-05T00:30:00.000Z' duration: 300 - - cpu/utilization: 11 + - cpu/utilization: '*' timestamp: '2024-03-05T00:35:00.000Z' duration: 300 - - cpu/utilization: 76 + - cpu/utilization: '*' timestamp: '2024-03-05T00:40:00.000Z' duration: 300 - - cpu/utilization: 63 + - cpu/utilization: '*' timestamp: '2024-03-05T00:45:00.000Z' duration: 300 - - cpu/utilization: 81 + - cpu/utilization: '*' timestamp: '2024-03-05T00:50:00.000Z' duration: 300 - - cpu/utilization: 74 + - cpu/utilization: '*' timestamp: '2024-03-05T00:55:00.000Z' duration: 300 aggregated: - cpu/utilization: 50.5 + cpu/utilization: '*' outputs: - - cpu/utilization: 48.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:00:00.000Z' duration: 300 - - cpu/utilization: 34.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:05:00.000Z' duration: 300 - - cpu/utilization: 22 + - cpu/utilization: '*' timestamp: '2024-03-05T00:10:00.000Z' duration: 300 - - cpu/utilization: 6.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:15:00.000Z' duration: 300 - - cpu/utilization: 85.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:20:00.000Z' duration: 300 - - cpu/utilization: 83 + - cpu/utilization: '*' timestamp: '2024-03-05T00:25:00.000Z' duration: 300 - - cpu/utilization: 12.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:30:00.000Z' duration: 300 - - cpu/utilization: 35 + - cpu/utilization: '*' timestamp: '2024-03-05T00:35:00.000Z' duration: 300 - - cpu/utilization: 65.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:40:00.000Z' duration: 300 - - cpu/utilization: 74 + - cpu/utilization: '*' timestamp: '2024-03-05T00:45:00.000Z' duration: 300 - - cpu/utilization: 66.5 + - cpu/utilization: '*' timestamp: '2024-03-05T00:50:00.000Z' duration: 300 - - cpu/utilization: 64 + - cpu/utilization: '*' timestamp: '2024-03-05T00:55:00.000Z' duration: 300 aggregated: - cpu/utilization: 49.791666666666664 + cpu/utilization: '*' From 28388704d618743c47157d1f6d9a61f72f2a65be Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 5 Jul 2024 15:13:24 +0400 Subject: [PATCH 342/863] revert(manifests): drop groupby pipelines --- .../mock-obs-group-by-cloud-meta.yaml | 645 ------------------ .../outputs/pipelines/mock-obs-groupby.yaml | 178 ----- 2 files changed, 823 deletions(-) delete mode 100644 manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml delete mode 100644 manifests/outputs/pipelines/mock-obs-groupby.yaml diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml deleted file mode 100644 index 74389a65a..000000000 --- a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml +++ /dev/null @@ -1,645 +0,0 @@ -name: My Manifest File -description: integration of mock observations, group by and cloud metadata -aggregation: - metrics: - - cpu/utilization - type: both -initialize: - plugins: - group-by: - path: builtin - method: GroupBy - global-config: - input-parameters: - - cpu/energy - - grid/carbon-intensity - output-parameter: carbon - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: cloud/instance-type - output: - - cpu-tdp - mock-observations: - path: builtin - method: MockObservations - global-config: - timestamp-from: 2024-03-05T00:00 - timestamp-to: 2024-03-05T01:00 - duration: 300 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yml -o - manifests/outputs/pipelines/mock-obs-group-by-cloud-meta - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T05:21:45.561Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - pipeline: - - mock-observations - - group-by - - cloud-metadata - config: - group-by: - group: - - name - - cloud/instance-type - children: - server-1: - children: - Standard_E64_v3: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 83 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 59 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - aggregated: - cpu/utilization: '*' - outputs: - - cpu/utilization: '*' - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: '*' - server-2: - children: - Standard_E64_v3: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: '*' - cpu-tdp: 270 - aggregated: - cpu/utilization: '*' - outputs: - - cpu/utilization: '*' - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: '*' - outputs: - - cpu/utilization: '*' - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: '*' - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: '*' diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml deleted file mode 100644 index 030d2dd05..000000000 --- a/manifests/outputs/pipelines/mock-obs-groupby.yaml +++ /dev/null @@ -1,178 +0,0 @@ -name: Mock observations + Group by -description: Integration of `mock observations` + `groupby plugins` -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/pipelines/mock-obs-groupby.yml -o - manifests/outputs/pipelines/mock-obs-groupby - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T05:27:34.757Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - pipeline: - - mock-observations - - group-by - defaults: null - config: - group-by: - group: - - cloud/region - - name - children: - westus3: - children: - server-1: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:10.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:20.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:30.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:40.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:50.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: '*' - france: - children: - server-2: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:10.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:20.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:30.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:40.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' - - timestamp: '2024-03-05T00:00:50.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: '*' From 90d7998151e1ea409b098939687367631dfcb201 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 5 Jul 2024 16:19:33 +0400 Subject: [PATCH 343/863] fix(src): prevent show debug message during execution of if-check and if-env --- src/check.ts | 4 ++++ src/env.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/check.ts b/src/check.ts index f69d8fa08..32449ab23 100644 --- a/src/check.ts +++ b/src/check.ts @@ -2,6 +2,7 @@ /* eslint-disable no-process-exit */ import * as path from 'path'; +import {debugLogger} from './util/debug-logger'; import {logger} from './util/logger'; import {logStdoutFailMessage} from './util/helpers'; import {parseIfCheckArgs} from './util/args'; @@ -19,6 +20,9 @@ const { } = STRINGS; const IfCheck = async () => { + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + const commandArgs = await parseIfCheckArgs(); console.log(`${CHECKING}\n`); diff --git a/src/env.ts b/src/env.ts index 48b0b76b9..073dbd7ad 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node /* eslint-disable no-process-exit */ +import {debugLogger} from './util/debug-logger'; import {parseIfEnvArgs} from './util/args'; import {logger} from './util/logger'; @@ -16,6 +17,9 @@ const {IF_ENV} = CONFIG; const {SUCCESS_MESSAGE} = IF_ENV; const IfEnv = async () => { + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + const commandArgs = await parseIfEnvArgs(); const options: EnvironmentOptions = { folderPath: process.env.CURRENT_DIR || process.cwd(), From 23fa28af73ee43bb96b29c2af1f04b42437c3ebc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 18:51:05 +0400 Subject: [PATCH 344/863] feat(.github): optimize if check, move to release --- .github/workflows/nodejs-ci.yml | 3 --- .github/workflows/release-commit.yml | 4 ++-- .github/workflows/release-publish.yml | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index aade2b55f..fac415dc3 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -21,6 +21,3 @@ jobs: - name: Run unit tests run: npm run test --silent - - - name: Run integration tests - run: npm run if-check -- -d manifests/outputs diff --git a/.github/workflows/release-commit.yml b/.github/workflows/release-commit.yml index ddc87cd69..efcf8726e 100644 --- a/.github/workflows/release-commit.yml +++ b/.github/workflows/release-commit.yml @@ -28,8 +28,8 @@ jobs: - name: Run unit tests run: npm test - - name: Install dependencies - run: npm ci + - name: Run integration tests + run: npm run if-check -- -d manifests/outputs - name: Initialize git user email run: git config --global user.email "${{ vars.RELEASE_USER_EMAIL }}" diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 146c77c87..3261fa840 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -23,8 +23,8 @@ jobs: - name: Run unit tests run: npm test - - name: Install dependencies - run: npm ci + - name: Run integration tests + run: npm run if-check -- -d manifests/outputs - name: Initialize git user email run: git config --global user.email "${{ env.RELEASE_USER_EMAIL }}" From b8c1ad380c32414dbdf2b30e9b28e76e4509ea1f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 23:00:26 +0400 Subject: [PATCH 345/863] =?UTF-8?q?chore(release):=20v0.5.0=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 12 +- README.md | 53 +- Refactor-migration-guide.md | 11 +- github-processes.md | 39 ++ jest.config.js | 2 +- .../bugs/aggregation-error-wrong-metric.yml | 128 ---- .../bugs/azure-importer-ignoring-defaults.yml | 61 -- .../azure-importer-incorrect-calculation.yml | 56 -- manifests/bugs/initialize-error-no-config.yml | 27 - manifests/bugs/initialize-error-no-path.yml | 28 - .../bugs/initialize-error-no-plugins.yml | 23 - .../bugs/input-error-missing-duration.yml | 21 - ...-observations-failure-duration-is-zero.yml | 34 - .../bugs/pipeline-error-naming-mismatch.yml | 28 - .../pipeline-error-uninitialized-plugin.yml | 29 - manifests/bugs/pipeline-ordering-error.yml | 82 --- .../sci-embodied-missing-resources-total.yml | 23 - manifests/examples/basic.yml | 28 - .../failure-invalid-config-input-param.yml | 0 .../failure-output-param-is-null.yaml | 0 .../builtins}/coefficient/success.yml | 0 .../failure-invalid-instance-type.yaml | 12 +- .../failure-invalid-vendor.yaml | 27 + .../failure-missing-cloud-vendor.yml | 12 +- .../csv-lookup}/cloud-metadata/success.yml | 10 +- .../failure-missing-column.yml | 3 +- .../failure-missing-output.yml | 3 +- .../region-metadata}/success-renaming.yml | 3 +- .../csv-lookup/region-metadata}/success.yml | 5 +- .../failure-missing-input-param.yml | 23 + ...failure-unsupported-physical-processor.yml | 24 + .../csv-lookup/tdp-finder/success.yml | 24 + .../divide/failure-denominator-equal-zero.yml | 17 +- .../failure-invalid-config-denominator.yml | 17 +- .../divide/failure-missing-numerator.yml | 17 +- .../builtins}/divide/success.yml | 19 +- .../examples/builtins/exponent/success.yml | 25 + .../groupby/failure-invalid-config-group.yml | 0 .../failure-missing-cloud-instance-type.yml | 0 .../builtins}/groupby/success.yml | 2 +- .../builtins}/interpolation/interpolation.yml | 0 .../builtins/interpolation/success.yml | 23 + .../failure-invalid-config-cpu-range.yml | 0 ...ilure-invalid-memory-utilization-range.yml | 0 .../failure-missing-timestamp-from-param.yml | 0 .../builtins}/mock-observations/success.yml | 0 .../failure-input-parameter-is-missing.yml | 0 .../multiply/success-with-multiple-inputs.yml | 0 .../builtins}/multiply/success.yml | 0 .../regex/failure-missing-input-param.yml | 0 .../regex/failure-not-matching-with-regex.yml | 0 .../builtins}/regex/success.yml | 0 ...failure-invalid-default-emission-value.yml | 0 .../failure-missing-expected-lifespan.yml | 0 .../builtins}/sci-embodied/success.yml | 0 .../sci/failure-invalid-config-value.yml | 0 .../sci/failure-missing-input-param.yml | 8 +- .../builtins}/sci/success.yml | 3 - .../shell/failure-invalid-command.yml | 0 .../builtins}/shell/success.yml | 0 .../examples/builtins/subtract/success.yml | 24 + .../sum/failure-missing-input-param.yml | 0 .../sum/failure-missing-output-param.yml | 0 .../builtins}/sum/success.yml | 2 +- .../failure-config-start-later-end.yml | 0 .../failure-missing-global-config.yml | 0 .../builtins}/time-sync/success.yml | 0 .../examples/mock-cpu-util-to-carbon.yml | 70 -- .../examples/{ => pipelines}/generics.yml | 62 +- .../{ => pipelines}/instance-metadata.yml | 0 .../examples/{ => pipelines}/nesting.yml | 117 +++- .../{ => pipelines}/pipeline-teads-sci.yml | 72 +- .../pipeline-with-aggregate.yml | 92 ++- .../{ => pipelines}/pipeline-with-mocks.yml | 87 ++- manifests/examples/{ => pipelines}/sci.yml | 0 .../examples/{ => pipelines}/teads-curve.yml | 0 manifests/examples/pipelines/zeros.yml | 130 ++++ .../aggregate-failure-inalid-metrics.yml | 43 -- ...egate-failure-missing-metric-in-inputs.yml | 43 -- manifests/features/aggregate-horizontal.yml | 44 -- manifests/features/aggregate-vertical.yml | 44 -- manifests/features/aggregate.yml | 44 -- .../cloud-metadata-divide-boavizta.yml | 38 -- .../mock-obs-group-by-cloud-meta.yml | 51 -- manifests/integrations/mock-obs-groupby.yml | 39 -- manifests/integrations/mock-obs-time-sync.yml | 65 -- .../bugs/aggregation-error-wrong-metric.yaml | 243 +++++++ .../bugs/initialize-error-no-config.yaml | 78 +++ .../bugs/initialize-error-no-path.yaml | 91 +++ .../bugs/initialize-error-no-plugins.yaml | 74 ++ .../bugs/input-error-missing-duration.yaml | 84 +++ ...observations-failure-duration-is-zero.yaml | 81 +++ .../bugs/pipeline-error-naming-mismatch.yaml | 91 +++ .../pipeline-error-uninitialized-plugin.yaml | 92 +++ .../outputs/bugs/pipeline-ordering-error.yaml | 155 +++++ .../sci-embodied-missing-resources-total.yaml | 73 ++ manifests/outputs/divide.yaml | 93 +++ .../aggregate-failure-invalid-metrics.yaml | 101 +++ ...gate-failure-missing-metric-in-inputs.yaml | 100 +++ .../features/aggregate-horizontal.yaml | 128 ++++ .../outputs/features/aggregate-vertical.yaml | 151 ++++ manifests/outputs/features/aggregate.yaml | 155 +++++ .../pipelines/cloud-metadata-divide.yaml | 95 +++ .../mock-obs-group-by-cloud-meta.yaml | 645 ++++++++++++++++++ .../outputs/pipelines/mock-obs-groupby.yaml | 178 +++++ .../outputs/pipelines/mock-obs-time-sync.yaml | 350 ++++++++++ .../failure-invalid-config-input-param.yaml | 73 ++ .../failure-output-param-is-null.yaml | 73 ++ .../outputs/plugins/coefficient/success.yaml | 75 ++ .../failure-invalid-instance-type.yaml | 27 + .../failure-invalid-vendor.yaml | 10 +- .../failure-missing-cloud-vendor.yaml | 77 +++ .../csv-lookup/cloud-metadata/success.yaml | 82 +++ .../failure-missing-column.yaml | 76 +++ .../failure-missing-output.yaml | 75 ++ .../region-metadata/success-renaming.yaml | 80 +++ .../csv-lookup/region-metadata/success.yaml | 92 +++ .../failure-missing-input-param.yaml | 74 ++ ...ailure-unsupported-physical-processor.yaml | 75 ++ .../csv-lookup/tdp-finder/success.yaml | 76 +++ .../failure-invalid-config-denominator.yaml | 73 ++ .../divide/failure-missing-numerator.yaml | 77 +++ .../success-denominator-equal-zero.yaml | 95 +++ manifests/outputs/plugins/divide/success.yaml | 95 +++ .../outputs/plugins/exponent/success.yaml | 77 +++ .../groupby/failure-invalid-config-group.yaml | 96 +++ .../failure-missing-cloud-instance-type.yaml | 95 +++ .../outputs/plugins/groupby/success.yaml | 101 +++ .../plugins/interpolation/interpolation.yaml | 83 +++ .../plugins/interpolation/success.yaml | 83 +++ .../failure-invalid-config-cpu-range.yaml | 86 +++ ...lure-invalid-memory-utilization-range.yaml | 84 +++ .../failure-missing-timestamp-from-param.yaml | 83 +++ .../plugins/mock-observations/success.yaml | 220 ++++++ .../failure-input-parameter-is-missing.yaml | 75 ++ .../success-with-multiple-inputs.yaml | 96 +++ .../outputs/plugins/multiply/success.yaml | 78 +++ .../regex/failure-missing-input-param.yaml | 75 ++ .../failure-not-matching-with-regex.yaml | 76 +++ manifests/outputs/plugins/regex/success.yaml | 81 +++ ...ailure-invalid-default-emission-value.yaml | 75 ++ .../failure-missing-expected-lifespan.yaml | 71 ++ .../outputs/plugins/sci-embodied/success.yaml | 78 +++ .../sci/failure-invalid-config-value.yaml | 72 ++ .../sci/failure-missing-input-param.yaml | 72 ++ .../outputs/plugins/sci/success.yml.yaml | 80 +++ .../shell/failure-invalid-command.yaml | 70 ++ manifests/outputs/plugins/shell/success.yaml | 68 ++ .../outputs/plugins/subtract/success.yaml | 78 +++ .../sum/failure-missing-input-param.yaml | 75 ++ .../sum/failure-missing-output-param.yaml | 78 +++ manifests/outputs/plugins/sum/success.yaml | 78 +++ .../failure-config-start-later-end.yaml | 82 +++ .../failure-missing-global-config.yaml | 78 +++ .../outputs/plugins/time-sync/success.yaml | 119 ++++ .../failure-missing-input-param.yml | 18 - ...failure-unsupported-physical-processor.yml | 19 - manifests/plugins/tdp-finder/success.yml | 19 - package-lock.json | 60 +- package.json | 14 +- scripts/run-yamls.sh | 2 +- src/__mocks__/builtins/export-csv.ts | 5 - src/__mocks__/fs/index.ts | 117 +++- src/__mocks__/mock-manifest.yaml | 72 ++ src/__mocks__/plugin/lib/mockavizta/index.ts | 2 +- src/__tests__/integration/scenarios/sci-e.ts | 2 +- .../unit/builtins/CommonGenerator.test.ts | 21 +- .../unit/builtins/RandIntGenerator.test.ts | 31 +- .../unit/builtins/coefficient.test.ts | 12 +- .../unit/builtins/copy-param.test.ts | 124 ++++ .../unit/builtins/csv-lookup.test.ts | 63 +- src/__tests__/unit/builtins/divide.test.ts | 50 +- src/__tests__/unit/builtins/exponent.test.ts | 34 +- .../unit/builtins/export-csv-raw.test.ts | 23 +- .../unit/builtins/export-csv.test.ts | 26 +- .../unit/builtins/export-yaml.test.ts | 12 +- src/__tests__/unit/builtins/group-by.test.ts | 16 +- .../unit/builtins/interpolation.test.ts | 37 +- .../unit/builtins/mock-observations.test.ts | 17 +- src/__tests__/unit/builtins/multiply.test.ts | 15 +- src/__tests__/unit/builtins/regex.test.ts | 23 +- .../unit/builtins/sci-embodied.test.ts | 28 +- src/__tests__/unit/builtins/sci.test.ts | 33 +- src/__tests__/unit/builtins/shell.test.ts | 11 +- src/__tests__/unit/builtins/subtract.test.ts | 13 +- src/__tests__/unit/builtins/sum.test.ts | 20 +- src/__tests__/unit/builtins/time-sync.test.ts | 53 +- src/__tests__/unit/config/strings.test.ts | 171 ----- src/__tests__/unit/lib/exhaust.test.ts | 26 +- src/__tests__/unit/lib/initialize.test.ts | 36 +- src/__tests__/unit/lib/load.test.ts | 12 +- src/__tests__/unit/lib/manifest/basic.ts | 48 -- src/__tests__/unit/lib/manifest/nested.ts | 146 ---- .../unit/util/aggregation-helper.test.ts | 16 +- src/__tests__/unit/util/args.test.ts | 249 ++++++- src/__tests__/unit/util/errors.test.ts | 13 - src/__tests__/unit/util/fs.test.ts | 144 ++++ src/__tests__/unit/util/helpers.test.ts | 311 ++++++++- src/__tests__/unit/util/npm.test.ts | 265 +++++++ .../unit/util/plugin-storage.test.ts | 9 +- src/builtins/README.md | 2 +- src/builtins/coefficient/README.md | 20 +- src/builtins/coefficient/index.ts | 31 +- src/builtins/coefficient/types.ts | 5 - src/builtins/copy-param/README.md | 104 +++ src/builtins/copy-param/index.ts | 89 +++ src/builtins/csv-lookup/README.md | 40 +- src/builtins/csv-lookup/index.ts | 106 +-- src/builtins/divide/README.md | 32 +- src/builtins/divide/index.ts | 50 +- src/builtins/exponent/README.md | 22 +- src/builtins/exponent/index.ts | 46 +- src/builtins/exponent/types.ts | 5 - src/builtins/export-csv-raw.ts | 16 +- src/builtins/export-csv.ts | 24 +- src/builtins/export-log.ts | 1 + src/builtins/export-yaml.ts | 13 +- src/builtins/group-by.ts | 16 +- src/builtins/index.ts | 1 + src/builtins/interpolation/README.md | 30 +- src/builtins/interpolation/index.ts | 29 +- src/builtins/interpolation/types.ts | 5 - src/builtins/mock-observations/README.md | 2 +- .../helpers/common-generator.ts | 30 +- .../helpers/rand-int-generator.ts | 58 +- src/builtins/mock-observations/index.ts | 18 +- src/builtins/mock-observations/types.ts | 16 - src/builtins/multiply/README.md | 17 +- src/builtins/multiply/index.ts | 43 +- src/builtins/multiply/types.ts | 4 - src/builtins/regex/README.md | 34 +- src/builtins/regex/index.ts | 28 +- src/builtins/sci-embodied/README.md | 16 +- src/builtins/sci-embodied/index.ts | 27 +- src/builtins/sci/README.md | 25 +- src/builtins/sci/index.ts | 60 +- src/builtins/shell/README.md | 13 +- src/builtins/shell/index.ts | 11 +- src/builtins/subtract/README.md | 13 +- src/builtins/subtract/index.ts | 49 +- src/builtins/subtract/types.ts | 4 - src/builtins/sum/README.md | 29 +- src/builtins/sum/index.ts | 33 +- src/builtins/sum/types.ts | 4 - src/builtins/time-sync.ts | 74 +- src/check.ts | 89 +++ src/config/config.ts | 69 +- src/config/env-template.yml | 24 + src/config/params.ts | 6 - src/config/strings.ts | 91 ++- src/diff.ts | 11 +- src/env.ts | 50 ++ src/lib/aggregate.ts | 7 +- src/lib/compute.ts | 5 +- src/lib/exhaust.ts | 8 +- src/lib/initialize.ts | 46 +- src/lib/load.ts | 10 +- src/types/common.ts | 5 - src/types/compute.ts | 3 +- src/types/group-by.ts | 3 - src/types/helpers.ts | 4 - src/types/if-env.ts | 6 + src/types/interface.ts | 25 +- src/types/npm.ts | 3 + src/types/process-args.ts | 11 + src/types/util/args.ts | 1 + src/util/aggregation-helper.ts | 11 +- src/util/args.ts | 136 +++- src/util/debug-logger.ts | 18 +- src/util/errors.ts | 35 - src/util/fs.ts | 68 ++ src/util/helpers.ts | 133 +++- src/util/npm.ts | 193 ++++++ src/util/plugin-storage.ts | 7 +- src/util/validations.ts | 7 +- 275 files changed, 11221 insertions(+), 2652 deletions(-) delete mode 100644 manifests/bugs/aggregation-error-wrong-metric.yml delete mode 100644 manifests/bugs/azure-importer-ignoring-defaults.yml delete mode 100644 manifests/bugs/azure-importer-incorrect-calculation.yml delete mode 100644 manifests/bugs/initialize-error-no-config.yml delete mode 100644 manifests/bugs/initialize-error-no-path.yml delete mode 100644 manifests/bugs/initialize-error-no-plugins.yml delete mode 100644 manifests/bugs/input-error-missing-duration.yml delete mode 100644 manifests/bugs/mock-observations-failure-duration-is-zero.yml delete mode 100644 manifests/bugs/pipeline-error-naming-mismatch.yml delete mode 100644 manifests/bugs/pipeline-error-uninitialized-plugin.yml delete mode 100644 manifests/bugs/pipeline-ordering-error.yml delete mode 100644 manifests/bugs/sci-embodied-missing-resources-total.yml delete mode 100644 manifests/examples/basic.yml rename manifests/{plugins => examples/builtins}/coefficient/failure-invalid-config-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/coefficient/failure-output-param-is-null.yaml (100%) rename manifests/{plugins => examples/builtins}/coefficient/success.yml (100%) rename manifests/{plugins => examples/builtins/csv-lookup}/cloud-metadata/failure-invalid-instance-type.yaml (57%) create mode 100644 manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml rename manifests/{plugins => examples/builtins/csv-lookup}/cloud-metadata/failure-missing-cloud-vendor.yml (56%) rename manifests/{plugins => examples/builtins/csv-lookup}/cloud-metadata/success.yml (57%) rename manifests/{plugins/csv-lookup => examples/builtins/csv-lookup/region-metadata}/failure-missing-column.yml (95%) rename manifests/{plugins/csv-lookup => examples/builtins/csv-lookup/region-metadata}/failure-missing-output.yml (95%) rename manifests/{plugins/csv-lookup => examples/builtins/csv-lookup/region-metadata}/success-renaming.yml (96%) rename manifests/{plugins/csv-lookup => examples/builtins/csv-lookup/region-metadata}/success.yml (90%) create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml create mode 100644 manifests/examples/builtins/csv-lookup/tdp-finder/success.yml rename manifests/{plugins => examples/builtins}/divide/failure-denominator-equal-zero.yml (69%) rename manifests/{plugins => examples/builtins}/divide/failure-invalid-config-denominator.yml (69%) rename manifests/{plugins => examples/builtins}/divide/failure-missing-numerator.yml (68%) rename manifests/{plugins => examples/builtins}/divide/success.yml (66%) create mode 100644 manifests/examples/builtins/exponent/success.yml rename manifests/{plugins => examples/builtins}/groupby/failure-invalid-config-group.yml (100%) rename manifests/{plugins => examples/builtins}/groupby/failure-missing-cloud-instance-type.yml (100%) rename manifests/{plugins => examples/builtins}/groupby/success.yml (98%) rename manifests/{plugins => examples/builtins}/interpolation/interpolation.yml (100%) create mode 100644 manifests/examples/builtins/interpolation/success.yml rename manifests/{plugins => examples/builtins}/mock-observations/failure-invalid-config-cpu-range.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/failure-invalid-memory-utilization-range.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/failure-missing-timestamp-from-param.yml (100%) rename manifests/{plugins => examples/builtins}/mock-observations/success.yml (100%) rename manifests/{plugins => examples/builtins}/multiply/failure-input-parameter-is-missing.yml (100%) rename manifests/{plugins => examples/builtins}/multiply/success-with-multiple-inputs.yml (100%) rename manifests/{plugins => examples/builtins}/multiply/success.yml (100%) rename manifests/{plugins => examples/builtins}/regex/failure-missing-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/regex/failure-not-matching-with-regex.yml (100%) rename manifests/{plugins => examples/builtins}/regex/success.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/failure-invalid-default-emission-value.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/failure-missing-expected-lifespan.yml (100%) rename manifests/{plugins => examples/builtins}/sci-embodied/success.yml (100%) rename manifests/{plugins => examples/builtins}/sci/failure-invalid-config-value.yml (100%) rename manifests/{plugins => examples/builtins}/sci/failure-missing-input-param.yml (65%) rename manifests/{plugins => examples/builtins}/sci/success.yml (79%) rename manifests/{plugins => examples/builtins}/shell/failure-invalid-command.yml (100%) rename manifests/{plugins => examples/builtins}/shell/success.yml (100%) create mode 100644 manifests/examples/builtins/subtract/success.yml rename manifests/{plugins => examples/builtins}/sum/failure-missing-input-param.yml (100%) rename manifests/{plugins => examples/builtins}/sum/failure-missing-output-param.yml (100%) rename manifests/{plugins => examples/builtins}/sum/success.yml (95%) rename manifests/{plugins => examples/builtins}/time-sync/failure-config-start-later-end.yml (100%) rename manifests/{plugins => examples/builtins}/time-sync/failure-missing-global-config.yml (100%) rename manifests/{plugins => examples/builtins}/time-sync/success.yml (100%) delete mode 100644 manifests/examples/mock-cpu-util-to-carbon.yml rename manifests/examples/{ => pipelines}/generics.yml (51%) rename manifests/examples/{ => pipelines}/instance-metadata.yml (100%) rename manifests/examples/{ => pipelines}/nesting.yml (71%) rename manifests/examples/{ => pipelines}/pipeline-teads-sci.yml (54%) rename manifests/examples/{ => pipelines}/pipeline-with-aggregate.yml (61%) rename manifests/examples/{ => pipelines}/pipeline-with-mocks.yml (65%) rename manifests/examples/{ => pipelines}/sci.yml (100%) rename manifests/examples/{ => pipelines}/teads-curve.yml (100%) create mode 100644 manifests/examples/pipelines/zeros.yml delete mode 100644 manifests/features/aggregate-failure-inalid-metrics.yml delete mode 100644 manifests/features/aggregate-failure-missing-metric-in-inputs.yml delete mode 100644 manifests/features/aggregate-horizontal.yml delete mode 100644 manifests/features/aggregate-vertical.yml delete mode 100644 manifests/features/aggregate.yml delete mode 100644 manifests/integrations/cloud-metadata-divide-boavizta.yml delete mode 100644 manifests/integrations/mock-obs-group-by-cloud-meta.yml delete mode 100644 manifests/integrations/mock-obs-groupby.yml delete mode 100644 manifests/integrations/mock-obs-time-sync.yml create mode 100644 manifests/outputs/bugs/aggregation-error-wrong-metric.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-config.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-path.yaml create mode 100644 manifests/outputs/bugs/initialize-error-no-plugins.yaml create mode 100644 manifests/outputs/bugs/input-error-missing-duration.yaml create mode 100644 manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml create mode 100644 manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml create mode 100644 manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml create mode 100644 manifests/outputs/bugs/pipeline-ordering-error.yaml create mode 100644 manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml create mode 100644 manifests/outputs/divide.yaml create mode 100644 manifests/outputs/features/aggregate-failure-invalid-metrics.yaml create mode 100644 manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml create mode 100644 manifests/outputs/features/aggregate-horizontal.yaml create mode 100644 manifests/outputs/features/aggregate-vertical.yaml create mode 100644 manifests/outputs/features/aggregate.yaml create mode 100644 manifests/outputs/pipelines/cloud-metadata-divide.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-groupby.yaml create mode 100644 manifests/outputs/pipelines/mock-obs-time-sync.yaml create mode 100644 manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml create mode 100644 manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml create mode 100644 manifests/outputs/plugins/coefficient/success.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml rename manifests/{plugins => outputs/plugins/csv-lookup}/cloud-metadata/failure-invalid-vendor.yaml (59%) create mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml create mode 100644 manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml create mode 100644 manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml create mode 100644 manifests/outputs/plugins/divide/failure-missing-numerator.yaml create mode 100644 manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml create mode 100644 manifests/outputs/plugins/divide/success.yaml create mode 100644 manifests/outputs/plugins/exponent/success.yaml create mode 100644 manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml create mode 100644 manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml create mode 100644 manifests/outputs/plugins/groupby/success.yaml create mode 100644 manifests/outputs/plugins/interpolation/interpolation.yaml create mode 100644 manifests/outputs/plugins/interpolation/success.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml create mode 100644 manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml create mode 100644 manifests/outputs/plugins/mock-observations/success.yaml create mode 100644 manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml create mode 100644 manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml create mode 100644 manifests/outputs/plugins/multiply/success.yaml create mode 100644 manifests/outputs/plugins/regex/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml create mode 100644 manifests/outputs/plugins/regex/success.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml create mode 100644 manifests/outputs/plugins/sci-embodied/success.yaml create mode 100644 manifests/outputs/plugins/sci/failure-invalid-config-value.yaml create mode 100644 manifests/outputs/plugins/sci/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/sci/success.yml.yaml create mode 100644 manifests/outputs/plugins/shell/failure-invalid-command.yaml create mode 100644 manifests/outputs/plugins/shell/success.yaml create mode 100644 manifests/outputs/plugins/subtract/success.yaml create mode 100644 manifests/outputs/plugins/sum/failure-missing-input-param.yaml create mode 100644 manifests/outputs/plugins/sum/failure-missing-output-param.yaml create mode 100644 manifests/outputs/plugins/sum/success.yaml create mode 100644 manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml create mode 100644 manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml create mode 100644 manifests/outputs/plugins/time-sync/success.yaml delete mode 100644 manifests/plugins/tdp-finder/failure-missing-input-param.yml delete mode 100644 manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml delete mode 100644 manifests/plugins/tdp-finder/success.yml create mode 100644 src/__mocks__/mock-manifest.yaml create mode 100644 src/__tests__/unit/builtins/copy-param.test.ts delete mode 100644 src/__tests__/unit/config/strings.test.ts delete mode 100644 src/__tests__/unit/lib/manifest/basic.ts delete mode 100644 src/__tests__/unit/lib/manifest/nested.ts delete mode 100644 src/__tests__/unit/util/errors.test.ts create mode 100644 src/__tests__/unit/util/fs.test.ts create mode 100644 src/__tests__/unit/util/npm.test.ts delete mode 100644 src/builtins/coefficient/types.ts create mode 100644 src/builtins/copy-param/README.md create mode 100644 src/builtins/copy-param/index.ts delete mode 100644 src/builtins/exponent/types.ts delete mode 100644 src/builtins/interpolation/types.ts delete mode 100644 src/builtins/mock-observations/types.ts delete mode 100644 src/builtins/multiply/types.ts delete mode 100644 src/builtins/subtract/types.ts delete mode 100644 src/builtins/sum/types.ts create mode 100644 src/check.ts create mode 100644 src/config/env-template.yml create mode 100644 src/env.ts delete mode 100644 src/types/common.ts delete mode 100644 src/types/group-by.ts delete mode 100644 src/types/helpers.ts create mode 100644 src/types/if-env.ts create mode 100644 src/types/npm.ts delete mode 100644 src/util/errors.ts create mode 100644 src/util/fs.ts create mode 100644 src/util/npm.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ac010c51..d1ea0db53 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,16 +20,19 @@ The following document is a rule set of guidelines for contributing. - [Naming conventions](#naming-conventions) - [Documentation](#documentation) - [Writing tests](#writing-tests) + - [How to report issues (bugs)](#how-to-report-issues-bugs) ## What and when to contribute -You can contribute anything to the IF, but we are likely to close out unsolicited PRs without merging them. Our issue board is completely open and we have tags (`help-wanted`, `good-first-issue`) to help contributors to choose tasks to work on. We recommend speaking to the core team on Github before starting working on an issue. You can do this by raising an issue or commenting on an existing issue. This helps us to direct your energy in directions that are aligned with our roadmap, prevent multiple people working on the same task, and better manage our board. This all makes it much more likely that your work will get merged. +You can contribute anything to the IF, but we are likely to close out unsolicited PRs without merging them. Our issue board is completely open and we have tags (`core-only`, `good-first-issue`) to help contributors to choose tasks to work on. If an issue is unassigned and does not have the `core-only` label, it is available to work on. We recommend speaking to the core team on Github before starting working on an issue. You can do this by commenting on an existing issue or discussion thread or starting a new one if appropriate. This helps us to direct your energy in directions that are aligned with our roadmap, prevent multiple people working on the same task, and better manage our board. This all makes it much more likely that your work will get merged. + +You can also contribute by participating in discussions on our mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that includes what we've shipped, what we're working on and how you can get involved each week. ## Reporting bugs -We appreciate bug reports! If you experience an issue with IF or one of our plugins, you can report it using our bug reporting template. To do this: +We appreciate bug reports! If you experience an issue with IF, you can report it using our bug reporting template. To do this: -1. Go to the [IF repository](https://github.com/Green-Software-Foundation/if) (or [plugin repository](https://github.com/Green-Software-Foundation/if-plugins) if you bug relates to a specific plugin) +1. Go to the [IF repository](https://github.com/Green-Software-Foundation/if) 2. Click on the `Issues` tab 3. Click on `Create New Issue` and select the `Bug Report` template. 4. Fill out the requested information. @@ -43,8 +46,7 @@ The assessment rubric is as follows: | | Consequence | Severity | | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------- | | Bugs in IF core leading to incorrect calculations | unusable framework | 5 | -| Bugs in if-plugins leading to incorrect calculations | core pathways fail, IF very limited in functionality | 5 | -| Bugs in if-unofficial-pluginsd leading to incorrect calculations | Third party plugins harder to use, limits IF to standard lib | 3 | +| Bugs in builtins leading to incorrect calculations | core pathways fail, IF very limited in functionality | 5 | | Bugs in template | Harder to build plugins, ecosystem growth is impacted | 2 | | Bugs in docs | product does not match expectation, hard to debug, frustration, loss of adoption | 2 | | Security flaw: privacy related | leak user data, unlikely to achieve adoption in serious orgs | 5 | diff --git a/README.md b/README.md index d0db42493..6fe0f67a4 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,6 @@ > [!IMPORTANT] > Incubation Project: This project is an incubation project being run inside the Green Software Foundation; as such, we DON’T recommend using it in any critical use case. Incubation projects are experimental, offer no support guarantee, have minimal governance and process, and may be retired at any moment. This project may one day Graduate, in which case this disclaimer will be removed. -**Note** We have recently (March 2024) refactored the IF codebase and introduced some changes affecting both users and developers. You can read our migration guide [HERE](./Refactor-migration-guide.md) to help you update to the latest version! - -[Impact Framework](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/17072136/Opensource+Impact+Engine+Framework) (IF) is an [Incubation](https://oc.greensoftware.foundation/project-lifecycle.html#incubation) project from the [Open Source Working Group](https://greensoftwarefoundation.atlassian.net/wiki/spaces/~612dd45e45cd76006a84071a/pages/852049/Open+Source+Working+Group) in the [Green Software Foundation](https://greensoftware.foundation/). - **Our documentation is online at [if.greensoftware.foundation](https://if.greensoftware.foundation/)** **IF** is a framework to **M**odel, **M**easure, si**M**ulate and **M**onitor the environmental impacts of software @@ -23,39 +19,32 @@ Read the [specification and design docs](https://if.greensoftware.foundation) to ## Get started -The first thing to understand is that IF is a framework for running plugins. This means that in order to do some calculations, you need to load some plugins from some external resource. We provide a [standard library of plugins](https://github.com/Green-Software-Foundation/if-plugins) and a repository of [community plugins](https://github.com/Green-Software-Foundation/if-unofficial-plugins) to get you started. +IF is a framework for running pipelines of plugins that operate on a set of observations. This is all configured using a manifest file. We provide a standard library of plugins that come bundled with IF - we refer to these as `builtins`. We also have an [Explorer](https://explorer.if.greensoftware.foundation) where anyone can list third party plugins you can install. -Start by installing framework itself: +Start by installing the latest version of IF: ```sh npm install -g "@grnsft/if" ``` -Then installing some plugins: - -```sh -npm install -g "@grnsft/if-plugins" -``` - Then create a `manifest` file that describes your application (see our docs for a detailed explanation). Then, run `if` using the following command: ```sh -ie --manifest +if-run --manifest --stdout ## or you can use aliases -ie -m +if-run -m -s + ``` -Note that above command will not print the final output. In order to print the final output to the console, run `if` using the optional stdout argument: +Note that above command will print your outputs to the console. You can also provide the `--output` command to save your outputs to a yaml file: ```sh -ie --manifest --stdout -## or using aliases -ie -m -s +if-run -m -o ``` -You can also add a savepath for your output yaml in order to have the output stored in a file. Note that you also have to add configuration to your manifest to enable this, as follows: +Note that you also have to add configuration to your manifest to enable this, as follows: ```yaml initialize: @@ -63,49 +52,47 @@ initialize: - yaml ``` -On the command line: - -```sh -ie --manifest --output -## or using aliases -ie -m -o -``` - -The `ie` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). +The `if-run` CLI tool will configure and run the plugins defined in your input `yaml` (`manifest`) and return the results as an output `yaml` (`output`). Use the `debug` command if you want to diagnose and fix errors in your plugin: ```sh -ie --manifest --debug +if-run --manifest --debug ``` Use the `help` command if you need guidance about the available commands ```sh -ie --help +if-run --help ## or using alias -ie -h +if-run -h ``` ## Documentation Please read our documentation at [if.greensoftware.foundation](https://if.greensoftware.foundation/) + ## Video walk-through Watch this video to learn how to create and run a `manifest`. [![Watch the walk-through video](https://i3.ytimg.com/vi/R-6eDM8AsvY/maxresdefault.jpg)](https://youtu.be/GW37Qd4AQbU) + +## Join our mailing list + +We have a public mailing list at [if-community@greensoftware.foundation](https://groups.google.com/u/1/a/greensoftware.foundation/g/if-community). We send out weekly updates that explain what we've shipped, what we're working on and how you can get involved each week! + + ## Contributing To contribute to IF, please fork this repository and raise a pull request from your fork. -You can check our issue board for issues tagged `help-wanted`. These are issues that are not currently, actively being worked on by the core team but are well-scoped enough for someone to pick up. We recommend commenting on the issue to start a chat with the core team, then start working on the issue when you have been assigned to it. This process helps to ensure your work is aligned with our roadmap and makes it much more likely that your changes will get merged compared to unsolicited PRs. +You can check our issue board for issues. We mark some issues `core-only` if they are somehow sensitive and we want one of our core developers to handle it. Any other issues are open for the community to work on. We recommend commenting on the issue to start a chat with the core team, then start working on the issue when you have been assigned to it. This process helps to ensure your work is aligned with our roadmap and makes it much more likely that your changes will get merged compared to unsolicited PRs. Please read the full contribution guidelines at [if.greensoftware.foundation](https://if.greensoftware.foundation/Contributing) -The same guidelines also apply to `if-docs`, `if-plugins` and `if-unofficial-plugins`. ## Bug reports diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 80328fe9e..d315d5c41 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -12,13 +12,13 @@ There have been some name changes to the CLI, specifically: The command line tool has been renamed from `impact-engine` to simply `ie`. This means that to invoke the Impact Framework on the command line you simply use ``` - ie ... + if-run ... ``` - `impl` --> `manifest` We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to pass a manifest file to IF, you use the `--manifest` command, as follows: ```sh - ie --manifest + if-run --manifest ``` @@ -27,7 +27,7 @@ There have been some name changes to the CLI, specifically: We have deprecated the original `impl` and `ompl` terminology across all our repositories and on the command line. Now, to define a savepath for your output file, you use the `--output` command, as follows: ```sh - ie --manifest --output + if-run --manifest --output ``` ## Outputs @@ -55,13 +55,13 @@ npm i @grnsft/if Then run IF using the following command: ```sh -ie --manifest +if-run --manifest ``` This will dump the output to the console. If you want to save the output to a yaml file, provide a savepath to the `--output` command: ```sh -ie --manifest --output +if-run --manifest --output ``` @@ -186,7 +186,6 @@ There have also been some changes to the structure of manifest files. Some of th device/expected-lifespan: 94608000 # 3 years in seconds resources-reserved: 1 resources-total: 8 - functional-unit-time: "1 min" ``` diff --git a/github-processes.md b/github-processes.md index 06721b4c6..81f2301d5 100644 --- a/github-processes.md +++ b/github-processes.md @@ -107,6 +107,7 @@ After a PR has passed triage, it can be assigned to a core team member to review We intend to respond to new PRs and issues within 3 days of the ticket being opened, even if only with a brief message thanking the OP and explaining the triage process. +There may be exceptional instances where bug fixes are prioritized over other ongoing tasks and worked on immediately, before triage. ## Labels @@ -140,3 +141,41 @@ If more than two hotfixes are required on a particular release, the team will ca Hotfixes on release can be merged back into `main` when they have been fully QA tested. We intend for hotfixes to be as infrequent as possible. + + +## Software Development Life Cycle + +Our normal process is to have week-long sprints where we tackle issues that contribute to a larger epic which typically last for 4-6 weeks. + +Our Executive Director and Product owner take responsibility for defining epics. This means they make decisions about how IF should change and translate that into a series of documents that get worked up into tickets for specific tasks. After the initial design, individual tasks are refined by the product owner, which means defining a scope of work and acceptance criteria for each task. + +Refinement is the process of taking a loosely scoped or ambiguous ticket and making it so well-described that anyone could pick it up off the board and produce an equivalent outcome to one of the core team. It's important we do this diligently even if it feels unnecessary or frictionful, because: + +- it keeps us all aligned with the purpose and rationale of individual tasks +- it improves our transparency +- it lowers the barrier to entry for contributors +- it helps us to "measure twice, cut once" and avoid doing work more than once +- it helps us to think together about each issue +- it provides an archive of our thinking that we can go back to in future. + +We use checkboxes for the statement of work and acceptance criteria as this helps to track progress on the task while it is in flight. + +A ticket is considered READY when it has been refined by the product owner. In general, we try to pass the refined ticket to a core developer to review any implementation details. + +We have the `core-only` label that we apply to tasks that are reserved for the core team to work on. Community contributions that cover these tickets are unlikely to get merged unless organized in advance. This is typically for sensitive parts of the core of the IF. + +Epics are also opresented to the community on the IF discussion forum in advance of being worked on in a development sprint. This is to give community contributors a chance to give feedback, suggest course corrections and discuss the changes with the team. These discussions can also lead to community members taking on some of the epic tasks. + +Once the tickets are refined they get prioritized and assigned during our development sprints. There is a pre-sprint prioritization call between the project sponsor, owner and manager to determien the priorities for each sprint, then a sprint planning meeting where the tasks are assigned and sized. + +### Overview of development practises + +| Stage | Participants | Inputs | Outputs | Overview | +| ----------------------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1. Initiation | Sponsor and Product Owner | Problem Statement and Objectives | Action Plan | In this phase, the team identifies a specific job-to-be-done or problem, develops a high-level vision for a solution, and outlines a preliminary task breakdown. | +| 2. Backlog | Product Owner | Breakdown of Epic or Milestone Tasks | An issue for each high-level task detailing the What and Why, along with a link to its parent epic | In this phase, each task from the epic or milestone is incorporated into the backlog (labeled as 'draft'), setting the context effectively. | +| 3. Design | Sponsor and Product Owner | What and Why, link to parent Epic Priority, Preliminary Acceptance Criteria and outline of work scope | In this phase, preliminary acceptance criteria are documented as a foundation for further refinement. | +| 4. Refinement Product Owner, Dev and QA (where applicable) | Preliminary Acceptance Criteria and outline of work scope | Comprehensive scenarios for Acceptance Criteria, confirmed work scope, and size | In this phase, engineers review the desired outcomes to ensure technical feasibility, clarify doubts, and solidify their understanding. They also estimate the required effort. Following this review, the issue is deemed Ready for implementation. | +| 5. Implementation | Dev and QA (where applicable) | A comprehensive set of scenarios for Acceptance Criteria and a confirmed Scope of Work. | A Pull Request (PR) including Unit Tests that pass and manifest files for automated testing, Technical documentation | In this phase, engineers execute the solution and review PRs. They also record a demo to demonstrate that it meets the acceptance criteria. | +| 6. UAT | Product Owner and Sponsor (if applicable) | Working feature and Acceptance Criteria | TBC | In this phase, the Product Owner verifies that the implementation matches the design by reviewing a demonstration of the work completed. | +| 7. Rollout | Product Owner, Sponsor and Marketing (if applicable) | Demos, Technical Documentation | TBC | In this phase, the Product Owner ensures that the community is prepared for the upcoming change. This preparation includes updates to the change log, project announcements, revisions to documentation, marketing efforts, and more. | diff --git a/jest.config.js b/jest.config.js index ed24da708..016be5863 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,8 +12,8 @@ module.exports = { }, modulePathIgnorePatterns: [ './build', - './src/__tests__/unit/lib/manifest', './src/__tests__/integration/helpers', './src/__tests__/integration/test-data', ], + coveragePathIgnorePatterns: ['src/config', 'src/types'], }; diff --git a/manifests/bugs/aggregation-error-wrong-metric.yml b/manifests/bugs/aggregation-error-wrong-metric.yml deleted file mode 100644 index e9a9af6ea..000000000 --- a/manifests/bugs/aggregation-error-wrong-metric.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: aggregation-error-wrong-metric -description: a negative test case that fails due to the aggregation feature being passed an incorrect metric -tags: -aggregation: - metrics: - - "dummy-param" - type: "both" -initialize: - plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve - global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE - "sci-embodied": - path: "builtin" - method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO - "sci": - path: "builtin" - method: Sci - global-config: - functional-unit: "requests" - functional-unit-time: "1 minute" - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true - "group-by": - path: builtin - method: GroupBy -tree: - children: - child-1: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - child-2: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west diff --git a/manifests/bugs/azure-importer-ignoring-defaults.yml b/manifests/bugs/azure-importer-ignoring-defaults.yml deleted file mode 100644 index 424be5e84..000000000 --- a/manifests/bugs/azure-importer-ignoring-defaults.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: pipeline-demo -description: https://github.com/Green-Software-Foundation/if-unofficial-plugins/issues/81 -tags: -# aggregation: -# metrics: -# - "carbon" -# - "energy" -#type: "both" -initialize: - outputs: - - yaml - # - csv - plugins: - "azure-importer": - method: AzureImporter - path: "@grnsft/if-unofficial-plugins" - "try-defaults-1": - path: "builtin" - method: Coefficient - global-config: - input-parameter: grid/carbon-intensity - coefficient: 0.1 - output-parameter: grid/carbon-intensity - "try-defaults-2": - path: "builtin" - method: Coefficient - global-config: - input-parameter: network/energy - coefficient: 1000 - output-parameter: network/energy - "sci-o": - method: SciO - path: "@grnsft/if-plugins" - "group-by": - path: "builtin" - method: GroupBy -tree: - children: - web-front: # name this according to the sub-system, e.g. portal, APIs/backend, DB - pipeline: - - azure-importer - #- try-defaults-1 - #- try-defaults-2 - - sci-o - config: - group-by: - group: - - instance-type - azure-importer: - azure-observation-window: 60 min - azure-observation-aggregation: "average" - azure-subscription-id: 30b6e171-af2c-4fe6-b00d-d4c70f6291fe - azure-resource-group: gcf-app_group - azure-vm-name: gcf-app - defaults: - grid/carbon-intensity: 800 # adjust for SG grid - network/energy: 0.001 # review for naming accuracy - inputs: - - timestamp: "2024-04-04T08:00:00.001Z" - duration: 3600 - energy: 100 diff --git a/manifests/bugs/azure-importer-incorrect-calculation.yml b/manifests/bugs/azure-importer-incorrect-calculation.yml deleted file mode 100644 index fa4cc17d0..000000000 --- a/manifests/bugs/azure-importer-incorrect-calculation.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: pipeline-demo -description: https://github.com/Green-Software-Foundation/if-unofficial-plugins/issues/81 -tags: null -initialize: - plugins: - azure-importer: - path: '@grnsft/if-unofficial-plugins' - method: AzureImporter - try-defaults-1: - path: 'builtin' - method: Coefficient - global-config: - input-parameter: grid/carbon-intensity - coefficient: 0.1 - output-parameter: grid/carbon-intensity - try-defaults-2: - path: 'builtin' - method: Coefficient - global-config: - input-parameter: network/energy - coefficient: 1000 - output-parameter: network/energy - sci-o: - path: '@grnsft/if-plugins' - method: SciO - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -if-version: v0.3.2 -tree: - children: - web-front: - pipeline: - - azure-importer - - try-defaults-1 - - try-defaults-2 - config: - group-by: - group: - - instance-type - azure-importer: - azure-observation-window: 60 min - azure-observation-aggregation: average - azure-subscription-id: 30b6e171-af2c-4fe6-b00d-d4c70f6291fe - azure-resource-group: gcf-app_group - azure-vm-name: gcf-app - defaults: - grid/carbon-intensity: 800 - network/energy: 0.001 - inputs: - - timestamp: '2024-04-04T08:00:00.001Z' - duration: 3600 - energy: 100 - \ No newline at end of file diff --git a/manifests/bugs/initialize-error-no-config.yml b/manifests/bugs/initialize-error-no-config.yml deleted file mode 100644 index 67973b53f..000000000 --- a/manifests/bugs/initialize-error-no-config.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: initialize-error-no-config -description: a negative test case that fails due to plugin initialization missing some required config -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/initialize-error-no-path.yml b/manifests/bugs/initialize-error-no-path.yml deleted file mode 100644 index 21210c544..000000000 --- a/manifests/bugs/initialize-error-no-path.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: initialize-error-no-path -description: a negative test case that fails because the path is mising in a plugin initialization -tags: -initialize: - plugins: - teads-curve: - path: - method: TeadsCurve - global-config: - interpolation: spline - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/initialize-error-no-plugins.yml b/manifests/bugs/initialize-error-no-plugins.yml deleted file mode 100644 index 7c6bfad53..000000000 --- a/manifests/bugs/initialize-error-no-plugins.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: initialize-error-no-path -description: a negative test case that fails becuase no plugins are included in the initialize block -tags: -initialize: - plugins: - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/input-error-missing-duration.yml b/manifests/bugs/input-error-missing-duration.yml deleted file mode 100644 index 1a4a5d9ef..000000000 --- a/manifests/bugs/input-error-missing-duration.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: input-error-missing-duration -description: a negative test case that fails due to the required `duration` field being omitted from input data -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - cpu/utilization: 20 diff --git a/manifests/bugs/mock-observations-failure-duration-is-zero.yml b/manifests/bugs/mock-observations-failure-duration-is-zero.yml deleted file mode 100644 index e3d0d4cb8..000000000 --- a/manifests/bugs/mock-observations-failure-duration-is-zero.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: mock-observation-demo -description: a manifest demonstrating how to use the mock observations feature -tags: -initialize: - outputs: ['yaml'] - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: "builtin" - global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 0 - components: - - cloud/instance-type: A1 - - cloud/instance-type: B1 - generators: - common: - region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - memory/utilization: - min: 1 - max: 99 -tree: - children: - child: - pipeline: - - mock-observations - inputs: diff --git a/manifests/bugs/pipeline-error-naming-mismatch.yml b/manifests/bugs/pipeline-error-naming-mismatch.yml deleted file mode 100644 index 22bb804a4..000000000 --- a/manifests/bugs/pipeline-error-naming-mismatch.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: pipeline-error-naming-mismatch -description: a negative test case that fails due to the plugin name in the pipeline not matching the name given in initialize -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - wrong-name - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/pipeline-error-uninitialized-plugin.yml b/manifests/bugs/pipeline-error-uninitialized-plugin.yml deleted file mode 100644 index 95afc196b..000000000 --- a/manifests/bugs/pipeline-error-uninitialized-plugin.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: pipeline-uninitialized-plugin-error -description: a negative test case that fails due to an uninitialized plugin being invoked in a pipeline -tags: -initialize: - # outputs: ['yaml'] - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - - multiply - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/bugs/pipeline-ordering-error.yml b/manifests/bugs/pipeline-ordering-error.yml deleted file mode 100644 index 3538465ea..000000000 --- a/manifests/bugs/pipeline-ordering-error.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: pipeline-ordering-error -description: a negative test case that fails because sci-o is invoked too early in the pipeline (before its inputs are generated) -tags: -initialize: - plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve - global-config: - interpolation: spline - "sum": - path: "builtin" - method: Sum - global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy - "sci-embodied": - path: "builtin" - method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO - "sci": - path: "builtin" - method: Sci - global-config: - functional-unit: "" - functional-unit-time: "1-day" - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true -tree: - children: - child-1: - pipeline: - - teads-curve - - sci-o - - sum - - sci-embodied - - time-sync - - sci - config: - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 50 - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - network/energy: 0.000001 diff --git a/manifests/bugs/sci-embodied-missing-resources-total.yml b/manifests/bugs/sci-embodied-missing-resources-total.yml deleted file mode 100644 index 952859c56..000000000 --- a/manifests/bugs/sci-embodied-missing-resources-total.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: sci-embodied -description: receiving incorrect error message when running sci-embodied without `resources-total` issue #716 -tags: -initialize: - #outputs: ['yaml'] - plugins: - "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor - method: SciEmbodied - path: "builtin" -tree: - children: - child: - pipeline: - - sci-embodied # duration & config -> embodied - defaults: - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - # resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/examples/basic.yml b/manifests/examples/basic.yml deleted file mode 100644 index e737f5d5b..000000000 --- a/manifests/examples/basic.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: basic -description: a minimal manifest executing a single plugin on a single component for a single timestep -tags: -initialize: - plugins: - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - outputs: ['yaml'] -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/plugins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml similarity index 100% rename from manifests/plugins/coefficient/failure-invalid-config-input-param.yml rename to manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml diff --git a/manifests/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml similarity index 100% rename from manifests/plugins/coefficient/failure-output-param-is-null.yaml rename to manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml diff --git a/manifests/plugins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml similarity index 100% rename from manifests/plugins/coefficient/success.yml rename to manifests/examples/builtins/coefficient/success.yml diff --git a/manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml similarity index 57% rename from manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml rename to manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index 9bb4581ef..fa55623c2 100644 --- a/manifests/plugins/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -2,11 +2,17 @@ name: cloud-metadata description: cloud/instance-type instance type is not supported in the cloud vendor tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml new file mode 100644 index 000000000..6f247f6c4 --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: failure with invalid `inputs.cloud/vendor` +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + cloud/vendor: gcp + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 diff --git a/manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml similarity index 56% rename from manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml rename to manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index 9b80c4301..33c5cc4b1 100644 --- a/manifests/plugins/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -2,11 +2,17 @@ name: cloud-metadata description: failing because cloud/vendor is not provided tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml similarity index 57% rename from manifests/plugins/cloud-metadata/success.yml rename to manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml index dec29460d..bd3cfdbb7 100644 --- a/manifests/plugins/cloud-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/plugins/csv-lookup/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml similarity index 95% rename from manifests/plugins/csv-lookup/failure-missing-column.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml index a0d54d0b5..85360f717 100644 --- a/manifests/plugins/csv-lookup/failure-missing-column.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/plugins/csv-lookup/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml similarity index 95% rename from manifests/plugins/csv-lookup/failure-missing-output.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index c6fc07d7b..005961ee0 100644 --- a/manifests/plugins/csv-lookup/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/plugins/csv-lookup/success-renaming.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml similarity index 96% rename from manifests/plugins/csv-lookup/success-renaming.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml index 7934e6234..66df39736 100644 --- a/manifests/plugins/csv-lookup/success-renaming.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup diff --git a/manifests/plugins/csv-lookup/success.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml similarity index 90% rename from manifests/plugins/csv-lookup/success.yml rename to manifests/examples/builtins/csv-lookup/region-metadata/success.yml index f57b4718a..005961ee0 100644 --- a/manifests/plugins/csv-lookup/success.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml @@ -2,8 +2,7 @@ name: csv-lookup-demo description: tags: initialize: - # outputs: - # - yaml + # outputs: [yaml] plugins: cloud-metadata: method: CSVLookup @@ -23,4 +22,4 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 cloud/provider: Google Cloud - cloud/region: asia-east-1 + cloud/region: asia-east1 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml new file mode 100644 index 000000000..b14e57d1d --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -0,0 +1,23 @@ +name: tdp-finder +description: failure with `inputs` missing `physical-processor` param +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml new file mode 100644 index 000000000..47f392fcc --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 302 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml new file mode 100644 index 000000000..42545b0df --- /dev/null +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -0,0 +1,24 @@ +name: tdp-finder +description: successful path +tags: +initialize: + # outputs: ['yaml'] + plugins: + tdp-finder: + method: CSVLookup + path: "builtin" + global-config: + filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: "tdp" +tree: + children: + child: + pipeline: + - tdp-finder + config: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e diff --git a/manifests/plugins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml similarity index 69% rename from manifests/plugins/divide/failure-denominator-equal-zero.yml rename to manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index af5ed2ae0..4022d4797 100644 --- a/manifests/plugins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml similarity index 69% rename from manifests/plugins/divide/failure-invalid-config-denominator.yml rename to manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 063274bc0..91129714a 100644 --- a/manifests/plugins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -5,8 +5,14 @@ initialize: outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 'vcpus' output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml similarity index 68% rename from manifests/plugins/divide/failure-missing-numerator.yml rename to manifests/examples/builtins/divide/failure-missing-numerator.yml index 7f03d5eba..7cf123976 100644 --- a/manifests/plugins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -5,8 +5,14 @@ initialize: # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: #numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/plugins/divide/success.yml b/manifests/examples/builtins/divide/success.yml similarity index 66% rename from manifests/plugins/divide/success.yml rename to manifests/examples/builtins/divide/success.yml index ed75a7c5c..6a32d7e2c 100644 --- a/manifests/plugins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -2,11 +2,17 @@ name: divide description: success path tags: initialize: -# outputs: ['yaml'] + # outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] divide: method: Divide path: "builtin" @@ -14,19 +20,12 @@ initialize: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true tree: children: child: pipeline: - cloud-metadata - divide - - boavizta-cpu config: divide: defaults: diff --git a/manifests/examples/builtins/exponent/success.yml b/manifests/examples/builtins/exponent/success.yml new file mode 100644 index 000000000..c8b59b78c --- /dev/null +++ b/manifests/examples/builtins/exponent/success.yml @@ -0,0 +1,25 @@ +name: exponent demo +description: +tags: +initialize: + # outputs: [yaml] + plugins: + exponent: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'cpu/energy' + exponent: 2 + output-parameter: 'energy' +tree: + children: + child: + pipeline: + - exponent + config: + exponent: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 diff --git a/manifests/plugins/groupby/failure-invalid-config-group.yml b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml similarity index 100% rename from manifests/plugins/groupby/failure-invalid-config-group.yml rename to manifests/examples/builtins/groupby/failure-invalid-config-group.yml diff --git a/manifests/plugins/groupby/failure-missing-cloud-instance-type.yml b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml similarity index 100% rename from manifests/plugins/groupby/failure-missing-cloud-instance-type.yml rename to manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml diff --git a/manifests/plugins/groupby/success.yml b/manifests/examples/builtins/groupby/success.yml similarity index 98% rename from manifests/plugins/groupby/success.yml rename to manifests/examples/builtins/groupby/success.yml index 0105799b1..e8e164e91 100644 --- a/manifests/plugins/groupby/success.yml +++ b/manifests/examples/builtins/groupby/success.yml @@ -1,7 +1,7 @@ name: groupby description: successful path initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: group-by: path: "builtin" diff --git a/manifests/plugins/interpolation/interpolation.yml b/manifests/examples/builtins/interpolation/interpolation.yml similarity index 100% rename from manifests/plugins/interpolation/interpolation.yml rename to manifests/examples/builtins/interpolation/interpolation.yml diff --git a/manifests/examples/builtins/interpolation/success.yml b/manifests/examples/builtins/interpolation/success.yml new file mode 100644 index 000000000..cce024727 --- /dev/null +++ b/manifests/examples/builtins/interpolation/success.yml @@ -0,0 +1,23 @@ +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: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 diff --git a/manifests/plugins/mock-observations/failure-invalid-config-cpu-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-invalid-config-cpu-range.yml rename to manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml diff --git a/manifests/plugins/mock-observations/failure-invalid-memory-utilization-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-invalid-memory-utilization-range.yml rename to manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml diff --git a/manifests/plugins/mock-observations/failure-missing-timestamp-from-param.yml b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml similarity index 100% rename from manifests/plugins/mock-observations/failure-missing-timestamp-from-param.yml rename to manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml diff --git a/manifests/plugins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml similarity index 100% rename from manifests/plugins/mock-observations/success.yml rename to manifests/examples/builtins/mock-observations/success.yml diff --git a/manifests/plugins/multiply/failure-input-parameter-is-missing.yml b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml similarity index 100% rename from manifests/plugins/multiply/failure-input-parameter-is-missing.yml rename to manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml diff --git a/manifests/plugins/multiply/success-with-multiple-inputs.yml b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml similarity index 100% rename from manifests/plugins/multiply/success-with-multiple-inputs.yml rename to manifests/examples/builtins/multiply/success-with-multiple-inputs.yml diff --git a/manifests/plugins/multiply/success.yml b/manifests/examples/builtins/multiply/success.yml similarity index 100% rename from manifests/plugins/multiply/success.yml rename to manifests/examples/builtins/multiply/success.yml diff --git a/manifests/plugins/regex/failure-missing-input-param.yml b/manifests/examples/builtins/regex/failure-missing-input-param.yml similarity index 100% rename from manifests/plugins/regex/failure-missing-input-param.yml rename to manifests/examples/builtins/regex/failure-missing-input-param.yml diff --git a/manifests/plugins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml similarity index 100% rename from manifests/plugins/regex/failure-not-matching-with-regex.yml rename to manifests/examples/builtins/regex/failure-not-matching-with-regex.yml diff --git a/manifests/plugins/regex/success.yml b/manifests/examples/builtins/regex/success.yml similarity index 100% rename from manifests/plugins/regex/success.yml rename to manifests/examples/builtins/regex/success.yml diff --git a/manifests/plugins/sci-embodied/failure-invalid-default-emission-value.yml b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml similarity index 100% rename from manifests/plugins/sci-embodied/failure-invalid-default-emission-value.yml rename to manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml diff --git a/manifests/plugins/sci-embodied/failure-missing-expected-lifespan.yml b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml similarity index 100% rename from manifests/plugins/sci-embodied/failure-missing-expected-lifespan.yml rename to manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml diff --git a/manifests/plugins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml similarity index 100% rename from manifests/plugins/sci-embodied/success.yml rename to manifests/examples/builtins/sci-embodied/success.yml diff --git a/manifests/plugins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml similarity index 100% rename from manifests/plugins/sci/failure-invalid-config-value.yml rename to manifests/examples/builtins/sci/failure-invalid-config-value.yml diff --git a/manifests/plugins/sci/failure-missing-input-param.yml b/manifests/examples/builtins/sci/failure-missing-input-param.yml similarity index 65% rename from manifests/plugins/sci/failure-missing-input-param.yml rename to manifests/examples/builtins/sci/failure-missing-input-param.yml index 44ced7374..54514a8e5 100644 --- a/manifests/plugins/sci/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sci/failure-missing-input-param.yml @@ -8,17 +8,13 @@ initialize: kind: plugin method: Sci path: "builtin" - # global-config: - # functional-unit: requests + global-config: + functional-unit: requests tree: children: child: pipeline: - sci - config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/plugins/sci/success.yml b/manifests/examples/builtins/sci/success.yml similarity index 79% rename from manifests/plugins/sci/success.yml rename to manifests/examples/builtins/sci/success.yml index c7e6dbde6..cddfe5755 100644 --- a/manifests/plugins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -16,9 +16,6 @@ tree: pipeline: - sci config: - sci: - functional-unit-time: 1 sec - functional-unit: requests # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/plugins/shell/failure-invalid-command.yml b/manifests/examples/builtins/shell/failure-invalid-command.yml similarity index 100% rename from manifests/plugins/shell/failure-invalid-command.yml rename to manifests/examples/builtins/shell/failure-invalid-command.yml diff --git a/manifests/plugins/shell/success.yml b/manifests/examples/builtins/shell/success.yml similarity index 100% rename from manifests/plugins/shell/success.yml rename to manifests/examples/builtins/shell/success.yml diff --git a/manifests/examples/builtins/subtract/success.yml b/manifests/examples/builtins/subtract/success.yml new file mode 100644 index 000000000..bcc27294c --- /dev/null +++ b/manifests/examples/builtins/subtract/success.yml @@ -0,0 +1,24 @@ +name: subtract demo +description: +tags: +initialize: + # outputs: ['yaml'] + plugins: + subtract: + method: Subtract + path: 'builtin' + global-config: + input-parameters: ['cpu/energy', 'network/energy'] + output-parameter: 'energy/diff' +tree: + children: + child: + pipeline: + - subtract + config: + subtract: + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 \ No newline at end of file diff --git a/manifests/plugins/sum/failure-missing-input-param.yml b/manifests/examples/builtins/sum/failure-missing-input-param.yml similarity index 100% rename from manifests/plugins/sum/failure-missing-input-param.yml rename to manifests/examples/builtins/sum/failure-missing-input-param.yml diff --git a/manifests/plugins/sum/failure-missing-output-param.yml b/manifests/examples/builtins/sum/failure-missing-output-param.yml similarity index 100% rename from manifests/plugins/sum/failure-missing-output-param.yml rename to manifests/examples/builtins/sum/failure-missing-output-param.yml diff --git a/manifests/plugins/sum/success.yml b/manifests/examples/builtins/sum/success.yml similarity index 95% rename from manifests/plugins/sum/success.yml rename to manifests/examples/builtins/sum/success.yml index fc0661bf5..454efc9e0 100644 --- a/manifests/plugins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -2,7 +2,7 @@ name: sum description: successful path tags: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: sum: method: Sum diff --git a/manifests/plugins/time-sync/failure-config-start-later-end.yml b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml similarity index 100% rename from manifests/plugins/time-sync/failure-config-start-later-end.yml rename to manifests/examples/builtins/time-sync/failure-config-start-later-end.yml diff --git a/manifests/plugins/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml similarity index 100% rename from manifests/plugins/time-sync/failure-missing-global-config.yml rename to manifests/examples/builtins/time-sync/failure-missing-global-config.yml diff --git a/manifests/plugins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml similarity index 100% rename from manifests/plugins/time-sync/success.yml rename to manifests/examples/builtins/time-sync/success.yml diff --git a/manifests/examples/mock-cpu-util-to-carbon.yml b/manifests/examples/mock-cpu-util-to-carbon.yml deleted file mode 100644 index 35f7cea26..000000000 --- a/manifests/examples/mock-cpu-util-to-carbon.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: mock-cpu-util-to-carbon -description: a complete pipeline that starts with mocked CPU utilization data and outputs operational carbon in gCO2eq -initialize: - #outputs: ['yaml'] - plugins: - group-by: - path: 'builtin' - method: GroupBy - operational-carbon: - path: 'builtin' - method: Multiply - global-config: - input-parameters: ['cpu/energy', 'grid/carbon-intensity'] - output-parameter: 'carbon' - watttime: - path: '@grnsft/if-unofficial-plugins' - method: WattTimeGridEmissions - teads-curve: - path: '@grnsft/if-unofficial-plugins' - method: TeadsCurve - global-config: - interpolation: spline - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - start-time: '2024-03-05T00:00:00.000Z' - end-time: '2024-03-05T00:01:00.000Z' - interval: 5 - allow-padding: true -tree: - pipeline: - - mock-observations - - group-by - - time-sync - - cloud-metadata - - watttime - - teads-curve - - operational-carbon - defaults: - config: - group-by: - group: - - cloud/region - - name - inputs: null diff --git a/manifests/examples/generics.yml b/manifests/examples/pipelines/generics.yml similarity index 51% rename from manifests/examples/generics.yml rename to manifests/examples/pipelines/generics.yml index c3ffa52e2..641bedcb1 100644 --- a/manifests/examples/generics.yml +++ b/manifests/examples/pipelines/generics.yml @@ -2,25 +2,55 @@ name: generics description: a pipeline that does arbitrary calculations using our generic arithmetic builtins tags: initialize: + # outputs: [yaml] plugins: - teads-curve: - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy-sum + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "coefficient": path: "builtin" method: Coefficient global-config: - input-parameter: energy + input-parameter: cpu-energy-kwh coefficient: 2 output-parameter: energy-doubled "multiply": @@ -33,13 +63,19 @@ tree: children: child-1: pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - coefficient - multiply config: defaults: cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 diff --git a/manifests/examples/instance-metadata.yml b/manifests/examples/pipelines/instance-metadata.yml similarity index 100% rename from manifests/examples/instance-metadata.yml rename to manifests/examples/pipelines/instance-metadata.yml diff --git a/manifests/examples/nesting.yml b/manifests/examples/pipelines/nesting.yml similarity index 71% rename from manifests/examples/nesting.yml rename to manifests/examples/pipelines/nesting.yml index e56e8bb18..978510f48 100644 --- a/manifests/examples/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -7,31 +7,62 @@ tags: aggregation: metrics: - "carbon" - - "energy" type: "both" params: initialize: - outputs: ['yaml'] + # outputs: ['yaml'] plugins: - teads-curve: - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - sum: + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh sci-embodied: path: "builtin" method: SciEmbodied - sci-o: - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" sci: path: "builtin" method: Sci @@ -62,13 +93,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -108,13 +143,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -156,13 +195,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -202,13 +245,17 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-allocated: 1 + vcpus-total: 8 pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci diff --git a/manifests/examples/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml similarity index 54% rename from manifests/examples/pipeline-teads-sci.yml rename to manifests/examples/pipelines/pipeline-teads-sci.yml index 01c491cdc..c07b093bd 100644 --- a/manifests/examples/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -3,25 +3,57 @@ description: a full pipeline seeded with some hardcoded input data and yielding tags: initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sum": + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide path: "builtin" - method: Sum global-config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci @@ -47,10 +79,14 @@ tree: children: child-1: pipeline: - - teads-curve - - sum + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - sci config: @@ -60,8 +96,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 component: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" diff --git a/manifests/examples/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml similarity index 61% rename from manifests/examples/pipeline-with-aggregate.yml rename to manifests/examples/pipelines/pipeline-with-aggregate.yml index bd3e637ac..7b689f1d8 100644 --- a/manifests/examples/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -7,25 +7,62 @@ aggregation: type: "both" initialize: plugins: - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci global-config: - functional-unit: "requests" + functional-unit: requests # factor to convert per time to per f.unit "sum-carbon": path: "builtin" method: Sum @@ -42,17 +79,18 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - "group-by": - path: builtin - method: GroupBy tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -67,8 +105,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -96,10 +134,14 @@ tree: requests: 30 child-2: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -114,8 +156,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 @@ -140,4 +182,4 @@ tree: cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west - requests: 180 + requests: 180 \ No newline at end of file diff --git a/manifests/examples/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml similarity index 65% rename from manifests/examples/pipeline-with-mocks.yml rename to manifests/examples/pipelines/pipeline-with-mocks.yml index 008e319b1..168ebd7fe 100644 --- a/manifests/examples/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -25,20 +25,57 @@ initialize: cpu/utilization: min: 1 max: 99 - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve + "interpolate": + method: Interpolation + path: 'builtin' global-config: - interpolation: spline - "sci-e": - path: "@grnsft/if-plugins" - method: SciE + method: linear + x: [0, 10, 50, 100] + y: [0.12, 0.32, 0.75, 1.02] + input-parameter: 'cpu/utilization' + output-parameter: 'cpu-factor' + "cpu-factor-to-wattage": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-factor", "cpu/thermal-design-power"] + output-parameter: "cpu-wattage" + "wattage-times-duration": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-wattage", "duration"] + output-parameter: "cpu-wattage-times-duration" + "wattage-to-energy-kwh": + method: Divide + path: "builtin" + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + "calculate-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + "correct-cpu-energy-for-vcpu-ratio": + method: Divide + path: "builtin" + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh "sci-embodied": path: "builtin" method: SciEmbodied - "sci-o": - path: "@grnsft/if-plugins" - method: SciO + "operational-carbon": + method: Multiply + path: builtin + global-config: + input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] + output-parameter: "carbon-operational" "sum-carbon": path: "builtin" method: Sum @@ -68,10 +105,14 @@ tree: children: child-1: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -86,9 +127,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -116,10 +156,14 @@ tree: requests: 50 child-2: pipeline: - - teads-curve - - sci-e + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio - sci-embodied - - sci-o + - operational-carbon - sum-carbon - time-sync - sci @@ -134,9 +178,8 @@ tree: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - functional-unit-time: "1 min" + vcpus-total: 8 + vcpus-allocated: 1 inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/examples/sci.yml b/manifests/examples/pipelines/sci.yml similarity index 100% rename from manifests/examples/sci.yml rename to manifests/examples/pipelines/sci.yml diff --git a/manifests/examples/teads-curve.yml b/manifests/examples/pipelines/teads-curve.yml similarity index 100% rename from manifests/examples/teads-curve.yml rename to manifests/examples/pipelines/teads-curve.yml diff --git a/manifests/examples/pipelines/zeros.yml b/manifests/examples/pipelines/zeros.yml new file mode 100644 index 000000000..da5541789 --- /dev/null +++ b/manifests/examples/pipelines/zeros.yml @@ -0,0 +1,130 @@ +name: generics +description: a pipeline that does arbitrary calculations using our generic arithmetic builtins +tags: +initialize: + plugins: + "sum-zero-and-one": + path: "builtin" + method: Sum + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-plus-zero + "sum-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-plus-zero + "subtract-one-and-zero": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-minus-zero + "subtract-zero-and-zero": + path: "builtin" + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-minus-zero + "subtract-zero-and-one": + path: "builtin" + method: Subtract + global-config: + input-parameters: + - zero-value + - some-value + output-parameter: zero-minus-one + "coefficient-one-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 1 + output-parameter: zero-times-one-coefficient + "coefficient-zero-times-one": + path: "builtin" + method: Coefficient + global-config: + input-parameter: some-value + coefficient: 0 + output-parameter: one-times-zero-coefficient + "coefficient-zero-times-zero": + path: "builtin" + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 0 + output-parameter: zero-times-zero-coefficient + "multiply-one-times-zero": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["some-value", "zero-value"] + output-parameter: "one-times-zero" + "multiply-zero-times-one": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["zero-value", "zero-value"] + output-parameter: "zero-times-one" + exponent-one-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'some-value' + exponent: 0 + output-parameter: 'one-raised-to-zero-power' + exponent-zero-to-zero: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 0 + output-parameter: 'zero-raised-to-zero-power' + exponent-zero-to-one: + method: Exponent + path: 'builtin' + global-config: + input-parameter: 'zero-value' + exponent: 1 + output-parameter: 'zero-raised-to-first-power' + "sci": + path: "builtin" + method: Sci + global-config: + functional-unit: "zero-value" +tree: + children: + child-1: + pipeline: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci + config: + defaults: + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + duration: 1 + some-value: 1 + zero-value: 0 + carbon: 10 diff --git a/manifests/features/aggregate-failure-inalid-metrics.yml b/manifests/features/aggregate-failure-inalid-metrics.yml deleted file mode 100644 index cf2e31bce..000000000 --- a/manifests/features/aggregate-failure-inalid-metrics.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations -aggregation: - metrics: - - 'test' - type: 'both' -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 diff --git a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml b/manifests/features/aggregate-failure-missing-metric-in-inputs.yml deleted file mode 100644 index 3857d0f76..000000000 --- a/manifests/features/aggregate-failure-missing-metric-in-inputs.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-01-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - # cpu/utilization: 110 - - timestamp: '2024-02-26 00:15:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 diff --git a/manifests/features/aggregate-horizontal.yml b/manifests/features/aggregate-horizontal.yml deleted file mode 100644 index 114074795..000000000 --- a/manifests/features/aggregate-horizontal.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Aggregation -description: Apply `horizontal` aggregation -aggregation: - metrics: - - 'cpu/utilization' - type: 'horizontal' -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/features/aggregate-vertical.yml b/manifests/features/aggregate-vertical.yml deleted file mode 100644 index b37f8e22a..000000000 --- a/manifests/features/aggregate-vertical.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Aggregation -description: Apply `vertical` aggregation -aggregation: - metrics: - - 'cpu/utilization' - type: 'vertical' -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/features/aggregate.yml b/manifests/features/aggregate.yml deleted file mode 100644 index f320a13ea..000000000 --- a/manifests/features/aggregate.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Aggregation -description: Apply both `horizontal` and `vertical` aggregations -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" -tree: - children: - application: - pipeline: - - cloud-metadata - children: - uk-west: - children: - server-1: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 89 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 59 - server-2: - inputs: - - timestamp: '2024-02-26 00:00:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 24 - - timestamp: '2024-02-26 00:05:00' - duration: 300 - cloud/instance-type: m5n.large - cloud/vendor: aws - cpu/utilization: 27 - \ No newline at end of file diff --git a/manifests/integrations/cloud-metadata-divide-boavizta.yml b/manifests/integrations/cloud-metadata-divide-boavizta.yml deleted file mode 100644 index cafd1467b..000000000 --- a/manifests/integrations/cloud-metadata-divide-boavizta.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: divide-demo -description: -tags: -initialize: - plugins: - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" - divide: - method: Divide - path: "builtin" - global-config: - numerator: vcpus-allocated - denominator: 2 - output: cpu/number-cores - boavizta-cpu: - method: BoaviztaCpuOutput - path: "@grnsft/if-unofficial-plugins" - global-config: - allocation: LINEAR - verbose: true -tree: - children: - child: - pipeline: - - cloud-metadata - - divide - - boavizta-cpu - config: - divide: - defaults: - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 diff --git a/manifests/integrations/mock-obs-group-by-cloud-meta.yml b/manifests/integrations/mock-obs-group-by-cloud-meta.yml deleted file mode 100644 index b0d43f2a5..000000000 --- a/manifests/integrations/mock-obs-group-by-cloud-meta.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: My Manifest File -description: integration of mock observations, group by and cloud metadata -aggregation: - metrics: - - 'cpu/utilization' - type: 'both' -initialize: - # outputs: ['yaml'] - plugins: - group-by: - path: 'builtin' - method: GroupBy - global-config: - input-parameters: ['cpu/energy', 'grid/carbon-intensity'] - output-parameter: 'carbon' - cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: 2024-03-05T00:00 - timestamp-to: 2024-03-05T01:00 - duration: 300 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 -tree: - pipeline: - - mock-observations - - group-by - - cloud-metadata - config: - group-by: - group: - - name - - cloud/instance-type - inputs: null diff --git a/manifests/integrations/mock-obs-groupby.yml b/manifests/integrations/mock-obs-groupby.yml deleted file mode 100644 index 39c37e2c8..000000000 --- a/manifests/integrations/mock-obs-groupby.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Mock observations + Group by -description: Integration of `mock observations` + `groupby plugins` -initialize: - plugins: - mock-observations: - path: 'builtin' - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - group-by: - path: 'builtin' - method: GroupBy -tree: - pipeline: - - mock-observations - - group-by - defaults: - config: - group-by: - group: - - cloud/region - - name - inputs: null diff --git a/manifests/integrations/mock-obs-time-sync.yml b/manifests/integrations/mock-obs-time-sync.yml deleted file mode 100644 index 727caf363..000000000 --- a/manifests/integrations/mock-obs-time-sync.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Mock observation and time sync integration -description: Integration of `mock observation` + `time sync` -tags: -initialize: - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: "builtin" - global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 60 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - "teads-curve": - path: "@grnsft/if-unofficial-plugins" - method: TeadsCurve - global-config: - interpolation: spline - "time-sync": - method: TimeSync - path: "builtin" - global-config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true -tree: - children: - child-1: - pipeline: - - teads-curve - - time-sync - defaults: - cpu/thermal-design-power: 100 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml new file mode 100644 index 000000000..fc0ac48b0 --- /dev/null +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -0,0 +1,243 @@ +name: aggregation-error-wrong-metric +description: >- + a negative test case that fails due to the aggregation feature being passed an + incorrect metric +tags: null +aggregation: + metrics: + - dummy-param + type: both +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor + cpu-factor-to-wattage: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + method: Divide + path: builtin + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + time-sync: + method: TimeSync + path: builtin + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/aggregation-error-wrong-metric.yml -o + manifests/outputs/bugs/aggregation-error-wrong-metric + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:25:34.759Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric dummy-param is not found in + inputs[0]. +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 100 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml new file mode 100644 index 000000000..56be9add7 --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-config.yaml @@ -0,0 +1,78 @@ +name: initialize-error-no-config +description: >- + a negative test case that fails due to plugin initialization missing some + required config +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + method: Interpolation + path: builtin + global-config: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-config.yml -o + manifests/outputs/bugs/initialize-error-no-config + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:45:41.936Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.interpolate.global-config" + parameter is expected object, received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml new file mode 100644 index 000000000..e2ee4d616 --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-path.yaml @@ -0,0 +1,91 @@ +name: initialize-error-no-path +description: >- + a negative test case that fails because the path is mising in a plugin + initialization +tags: null +initialize: + plugins: + interpolate: + method: Interpolation + path: null + 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-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-path.yml -o + manifests/outputs/bugs/initialize-error-no-path + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:57:11.499Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.interpolate.path" parameter is + expected string, received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml new file mode 100644 index 000000000..208010e00 --- /dev/null +++ b/manifests/outputs/bugs/initialize-error-no-plugins.yaml @@ -0,0 +1,74 @@ +name: initialize-error-no-path +description: >- + a negative test case that fails becuase no plugins are included in the + initialize block +tags: null +initialize: + plugins: null + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/initialize-error-no-plugins.yml -o + manifests/outputs/bugs/initialize-error-no-plugins + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:52:35.214Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins" parameter is expected object, + received null. Error code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - teads-curve + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml new file mode 100644 index 000000000..dd339eb4f --- /dev/null +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -0,0 +1,84 @@ +name: input-error-missing-duration +description: >- + a negative test case that fails due to the required `duration` field being + omitted from input data +tags: null +initialize: + plugins: + interpolate: + 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: cpu-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/input-error-missing-duration.yml -o + manifests/outputs/bugs/input-error-missing-duration + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T19:59:58.987Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "duration" parameter is required at index 0. Error + code: invalid_type. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + inputs: + - timestamp: 2023-07-06T00:00 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml new file mode 100644 index 000000000..fedf856fb --- /dev/null +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -0,0 +1,81 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 0 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yml -o + manifests/outputs/bugs/mock-observations-failure-duration-is-zero + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:02:22.596Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'RangeError: Maximum call stack size exceeded' +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml new file mode 100644 index 000000000..21fc5e668 --- /dev/null +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -0,0 +1,91 @@ +name: pipeline-error-naming-mismatch +description: >- + a negative test case that fails due to the plugin name in the pipeline not + matching the name given in initialize +tags: null +initialize: + plugins: + interpolate: + 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: cpu-factor + outputs: + - yaml +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-error-naming-mismatch.yml -o + manifests/outputs/bugs/pipeline-error-naming-mismatch + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:06:51.254Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + PluginInitializationError: Not initalized plugin: wrong-name. Check if + wrong-name is in 'manifest.initalize.plugins'. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - wrong-name + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml new file mode 100644 index 000000000..a37517432 --- /dev/null +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -0,0 +1,92 @@ +name: pipeline-uninitialized-plugin-error +description: >- + a negative test case that fails due to an uninitialized plugin being invoked + in a pipeline +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yml -o + manifests/outputs/bugs/pipeline-error-uninitialized-plugin + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:08:51.260Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + PluginInitializationError: Not initalized plugin: multiply. Check if + multiply is in 'manifest.initalize.plugins'. +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + pipeline: + - interpolate + - multiply + inputs: + - timestamp: 2023-07-06T00:00 + duration: 1 + cpu/utilization: 20 + - timestamp: 2023-07-06T00:01 + duration: 1 + cpu/utilization: 80 + - timestamp: 2023-07-06T00:02 + duration: 1 + cpu/utilization: 20 diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml new file mode 100644 index 000000000..fe59b03d8 --- /dev/null +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -0,0 +1,155 @@ +name: pipeline-ordering-error +description: >- + a negative test case that fails because sci-o is invoked too early in the + pipeline (before its inputs are generated) +tags: null +initialize: + outputs: + - yaml + plugins: + interpolate: + 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: cpu-factor + cpu-factor-to-wattage: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + method: Divide + path: builtin + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + method: Divide + path: builtin + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/pipeline-ordering-error.yml -o + manifests/outputs/bugs/pipeline-ordering-error + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:14:29.109Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu-energy-raw" parameter is required. Error code: + invalid_type. +tree: + children: + child-1: + pipeline: + - interpolate + - correct-cpu-energy-for-vcpu-ratio + - calculate-vcpu-ratio + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + config: null + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml new file mode 100644 index 000000000..e0a50cd90 --- /dev/null +++ b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml @@ -0,0 +1,73 @@ +name: sci-embodied +description: >- + receiving incorrect error message when running sci-embodied without + `resources-total` issue +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/bugs/sci-embodied-missing-resources-total.yml -o + manifests/outputs/bugs/sci-embodied-missing-resources-total + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:17:30.390Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "vcpus-allocated" parameter is required. Error code: + invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/divide.yaml b/manifests/outputs/divide.yaml new file mode 100644 index 000000000..e0875c420 --- /dev/null +++ b/manifests/outputs/divide.yaml @@ -0,0 +1,93 @@ +name: divide +description: success path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /home/joe/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /home/joe/Code/if/src/index.ts -m ./manifests/plugins/divide/success.yml -o + ./manifests/outputs/divide + environment: + if-version: 0.4.0 + os: linux + os-version: 5.15.0-113-generic + node-version: 21.4.0 + date-time: 2024-07-03T14:02:26.789Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml new file mode 100644 index 000000000..1a737e742 --- /dev/null +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -0,0 +1,101 @@ +name: Aggregation +description: Fails with invalid metric. +aggregation: + metrics: + - test + type: both +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-failure-invalid-metrics.yml -o + manifests/outputs/features/aggregate-failure-invalid-metrics + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:25:17.348Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric test is not found in + inputs[0]. +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml new file mode 100644 index 000000000..82d6759bc --- /dev/null +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -0,0 +1,100 @@ +name: Aggregation +description: Fails with missing metric in inputs. +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yml -o + manifests/outputs/features/aggregate-failure-missing-metric-in-inputs + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:26:58.250Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingAggregationParamError: Aggregation metric cpu/utilization is not + found in inputs[0]. +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-01-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + - timestamp: '2024-02-26 00:15:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml new file mode 100644 index 000000000..3110af664 --- /dev/null +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -0,0 +1,128 @@ +name: Aggregation +description: Apply `horizontal` aggregation +aggregation: + metrics: + - cpu/utilization + type: horizontal +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-horizontal.yml -o + manifests/outputs/features/aggregate-horizontal + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:28:27.168Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 74 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 25.5 diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml new file mode 100644 index 000000000..1527a9280 --- /dev/null +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -0,0 +1,151 @@ +name: Aggregation +description: Apply `vertical` aggregation +aggregation: + metrics: + - cpu/utilization + type: vertical +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate-vertical.yml -o + manifests/outputs/features/aggregate-vertical + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:32:47.459Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml new file mode 100644 index 000000000..062cd9932 --- /dev/null +++ b/manifests/outputs/features/aggregate.yaml @@ -0,0 +1,155 @@ +name: Aggregation +description: Apply both `horizontal` and `vertical` aggregations +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/features/aggregate.yml -o + manifests/outputs/features/aggregate + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-01T20:34:35.981Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + application: + pipeline: + - cloud-metadata + children: + uk-west: + children: + server-1: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 89 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 59 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 74 + server-2: + inputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + outputs: + - timestamp: '2024-02-26 00:00:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 24 + vcpus-allocated: 2 + - timestamp: '2024-02-26 00:05:00' + duration: 300 + cloud/instance-type: m5n.large + cloud/vendor: aws + cpu/utilization: 27 + vcpus-allocated: 2 + aggregated: + cpu/utilization: 25.5 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 + outputs: + - cpu/utilization: 56.5 + timestamp: '2024-02-26 00:00:00' + duration: 300 + - cpu/utilization: 43 + timestamp: '2024-02-26 00:05:00' + duration: 300 + aggregated: + cpu/utilization: 49.75 diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml new file mode 100644 index 000000000..130c4361e --- /dev/null +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -0,0 +1,95 @@ +name: divide-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/cloud-metadata-divide.yml -o + manifests/outputs/pipelines/cloud-metadata-divide + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:13:05.868Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml new file mode 100644 index 000000000..5585d4c42 --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml @@ -0,0 +1,645 @@ +name: My Manifest File +description: integration of mock observations, group by and cloud metadata +aggregation: + metrics: + - cpu/utilization + type: both +initialize: + plugins: + group-by: + path: builtin + method: GroupBy + global-config: + input-parameters: + - cpu/energy + - grid/carbon-intensity + output-parameter: carbon + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-tdp + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2024-03-05T00:00 + timestamp-to: 2024-03-05T01:00 + duration: 300 + components: + - name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + - name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + generators: + common: + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + randint: + cpu/utilization: + min: 1 + max: 99 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yml -o + manifests/outputs/pipelines/mock-obs-group-by-cloud-meta + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:21:45.561Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + pipeline: + - mock-observations + - group-by + - cloud-metadata + config: + group-by: + group: + - name + - cloud/instance-type + children: + server-1: + children: + Standard_E64_v3: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 93 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 3 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 83 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 8 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 59 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 55 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 52 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 54 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 93 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 6 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 3 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 83 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 8 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 59 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 55 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 85 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 52 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: eastus + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 54 + cpu-tdp: 270 + aggregated: + cpu/utilization: 49.083333333333336 + outputs: + - cpu/utilization: 93 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 6 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 6 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 3 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 83 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 85 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 8 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 59 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 55 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 85 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 52 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 54 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 49.083333333333336 + server-2: + children: + Standard_E64_v3: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 4 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 38 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 10 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 88 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 17 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 11 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 76 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 74 + outputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 4 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 38 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 10 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 88 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 17 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 11 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 76 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 63 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 81 + cpu-tdp: 270 + - timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + geolocation: 37.7749,-122.4194 + cloud/vendor: azure + cpu/utilization: 74 + cpu-tdp: 270 + aggregated: + cpu/utilization: 50.5 + outputs: + - cpu/utilization: 4 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 63 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 38 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 10 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 88 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 81 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 17 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 11 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 76 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 63 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 81 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 74 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 50.5 + outputs: + - cpu/utilization: 48.5 + timestamp: '2024-03-05T00:00:00.000Z' + duration: 300 + - cpu/utilization: 34.5 + timestamp: '2024-03-05T00:05:00.000Z' + duration: 300 + - cpu/utilization: 22 + timestamp: '2024-03-05T00:10:00.000Z' + duration: 300 + - cpu/utilization: 6.5 + timestamp: '2024-03-05T00:15:00.000Z' + duration: 300 + - cpu/utilization: 85.5 + timestamp: '2024-03-05T00:20:00.000Z' + duration: 300 + - cpu/utilization: 83 + timestamp: '2024-03-05T00:25:00.000Z' + duration: 300 + - cpu/utilization: 12.5 + timestamp: '2024-03-05T00:30:00.000Z' + duration: 300 + - cpu/utilization: 35 + timestamp: '2024-03-05T00:35:00.000Z' + duration: 300 + - cpu/utilization: 65.5 + timestamp: '2024-03-05T00:40:00.000Z' + duration: 300 + - cpu/utilization: 74 + timestamp: '2024-03-05T00:45:00.000Z' + duration: 300 + - cpu/utilization: 66.5 + timestamp: '2024-03-05T00:50:00.000Z' + duration: 300 + - cpu/utilization: 64 + timestamp: '2024-03-05T00:55:00.000Z' + duration: 300 + aggregated: + cpu/utilization: 49.791666666666664 diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml new file mode 100644 index 000000000..4783dffde --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-groupby.yaml @@ -0,0 +1,178 @@ +name: Mock observations + Group by +description: Integration of `mock observations` + `groupby plugins` +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: '2024-03-05T00:00:00.000Z' + timestamp-to: '2024-03-05T00:01:00.000Z' + duration: 10 + components: + - name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + - name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + generators: + common: + cloud/vendor: azure + randint: + cpu/utilization: + min: 1 + max: 99 + group-by: + path: builtin + method: GroupBy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-groupby.yml -o + manifests/outputs/pipelines/mock-obs-groupby + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:27:34.757Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + pipeline: + - mock-observations + - group-by + defaults: null + config: + group-by: + group: + - cloud/region + - name + children: + westus3: + children: + server-1: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 12 + - timestamp: '2024-03-05T00:00:10.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 71 + - timestamp: '2024-03-05T00:00:20.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 75 + - timestamp: '2024-03-05T00:00:30.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 39 + - timestamp: '2024-03-05T00:00:40.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 42 + - timestamp: '2024-03-05T00:00:50.000Z' + duration: 10 + name: server-1 + cloud/instance-type: Standard_E64_v3 + cloud/region: westus3 + cloud/vendor: azure + cpu/utilization: 98 + france: + children: + server-2: + inputs: + - timestamp: '2024-03-05T00:00:00.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 14 + - timestamp: '2024-03-05T00:00:10.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 80 + - timestamp: '2024-03-05T00:00:20.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 53 + - timestamp: '2024-03-05T00:00:30.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 10 + - timestamp: '2024-03-05T00:00:40.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 40 + - timestamp: '2024-03-05T00:00:50.000Z' + duration: 10 + name: server-2 + cloud/instance-type: Standard_E64_v3 + cloud/region: france + cloud/vendor: azure + cpu/utilization: 92 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml new file mode 100644 index 000000000..271340c2b --- /dev/null +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -0,0 +1,350 @@ +name: Mock observation and time sync integration +description: Integration of `mock observation` + `time sync` +tags: null +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/pipelines/mock-obs-time-sync.yml -o + manifests/outputs/pipelines/mock-obs-time-sync + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:29:47.787Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - time-sync + defaults: + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: 14 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.662 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000007048611111111113 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + cpu/thermal-design-power: 80 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 + cpu/thermal-design-power: 60 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + cpu/thermal-design-power: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 diff --git a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml new file mode 100644 index 000000000..ba10eaee3 --- /dev/null +++ b/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml @@ -0,0 +1,73 @@ +name: coefficient-demo +description: failure with ivalid `global-config.input-parameter` +tags: null +initialize: + outputs: + - yaml + plugins: + coefficient: + method: Coefficient + path: builtin + global-config: + input-parameter: 4 + coefficient: 3 + output-parameter: carbon-product +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yml + -o manifests/outputs/plugins/coefficient/failure-invalid-config-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:41:49.144Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "input-parameter" parameter is expected string, + received number. Error code: invalid_type. +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 diff --git a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml new file mode 100644 index 000000000..dd2f6c952 --- /dev/null +++ b/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml @@ -0,0 +1,73 @@ +name: coefficient-demo +description: value of output-param is missing +tags: null +initialize: + outputs: + - yaml + plugins: + coefficient: + method: Coefficient + path: builtin + global-config: + input-parameter: carbon + coefficient: 3 + output-parameter: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/failure-output-param-is-null.yml -o + manifests/outputs/plugins/coefficient/failure-output-param-is-null + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:38:48.831Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output-parameter" parameter is expected string, + received null. Error code: invalid_type. +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 diff --git a/manifests/outputs/plugins/coefficient/success.yaml b/manifests/outputs/plugins/coefficient/success.yaml new file mode 100644 index 000000000..86300012c --- /dev/null +++ b/manifests/outputs/plugins/coefficient/success.yaml @@ -0,0 +1,75 @@ +name: coefficient-demo +description: successful path +tags: null +initialize: + plugins: + coefficient: + path: builtin + method: Coefficient + global-config: + input-parameter: carbon + coefficient: 3 + output-parameter: carbon-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/coefficient/success.yml -o + manifests/outputs/plugins/coefficient/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:37:08.297Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - coefficient + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + carbon: 30 + carbon-product: 90 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml new file mode 100644 index 000000000..fa55623c2 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -0,0 +1,27 @@ +name: cloud-metadata +description: cloud/instance-type instance type is not supported in the cloud vendor +tags: +initialize: + # outputs: ['yaml'] + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] +tree: + children: + child: + pipeline: + - cloud-metadata + config: + inputs: + - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred + cloud/vendor: aws + cloud/instance-type: m6 + duration: 100 + cpu/utilization: 10 diff --git a/manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml similarity index 59% rename from manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml rename to manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 9e2ebe4f2..c474c91fe 100644 --- a/manifests/plugins/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -5,8 +5,14 @@ initialize: #outputs: ['yaml'] plugins: cloud-metadata: - method: CloudMetadata - path: "@grnsft/if-plugins" + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: ['cpu-cores-utilized', 'vcpus-allocated'] tree: children: child: diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml new file mode 100644 index 000000000..943416663 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -0,0 +1,77 @@ +name: cloud-metadata +description: failing because cloud/vendor is not provided +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml + -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:20:08.333Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - cloud-metadata + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 100 + cpu/utilization: 10 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml new file mode 100644 index 000000000..25c8db6e3 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml @@ -0,0 +1,82 @@ +name: cloud-metadata +description: successful path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yml -o + manifests/outputs/plugins/csv-lookup/cloud-metadata/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:21:45.504Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + config: null + inputs: + - timestamp: 2023-07-06T00:00 + cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 + outputs: + - timestamp: 2023-07-06T00:00 + cloud/vendor: aws + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 + vcpus-allocated: 2 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml new file mode 100644 index 000000000..cad931fd1 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -0,0 +1,76 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: nonexistant + cloud-region: cloud/region + output: '*' +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yml + -o + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:26:59.352Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml new file mode 100644 index 000000000..ad5ab9ec8 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -0,0 +1,75 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + outputs: + - yaml + plugins: + cloud-metadata: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yml + -o + manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:26:09.874Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output" parameter is invalid input. Error code: + invalid_union. +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml new file mode 100644 index 000000000..77aeecd66 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml @@ -0,0 +1,80 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: + - em-zone-id + - renamed-em-zone-data + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yml -o + manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:24:10.894Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + renamed-em-zone-data: TW diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml new file mode 100644 index 000000000..10bb9a637 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml @@ -0,0 +1,92 @@ +name: csv-lookup-demo +description: null +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv + query: + cloud-provider: cloud/provider + cloud-region: cloud/region + output: '*' + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/region-metadata/success.yml -o + manifests/outputs/plugins/csv-lookup/region-metadata/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:23:15.965Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cloud/provider: Google Cloud + cloud/region: asia-east1 + year: 2022 + cfe-region: Taiwan + em-zone-id: TW + wt-region-id: TW + location: Taiwan + geolocation: 25.0375,121.5625 + cfe-hourly: 0.18 + cfe-annual: nan + power-usage-efficiency: nan + net-carbon: 0 + grid-carbon-intensity-24x7: 453 + grid-carbon-intensity-consumption: nan + grid-carbon-intensity-marginal: nan + grid-carbon-intensity-production: nan + grid-carbon-intensity: 453 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml new file mode 100644 index 000000000..56b6c2630 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -0,0 +1,74 @@ +name: tdp-finder +description: failure with `inputs` missing `physical-processor` param +tags: null +initialize: + outputs: + - yaml + plugins: + tdp-finder: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yml + -o + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:30:11.973Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml new file mode 100644 index 000000000..888df1ce7 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -0,0 +1,75 @@ +name: tdp-finder +description: successful path +tags: null +initialize: + outputs: + - yaml + plugins: + tdp-finder: + method: CSVLookup + path: builtin + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml + -o + manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:29:16.211Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 302 diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml new file mode 100644 index 000000000..bf12d4892 --- /dev/null +++ b/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml @@ -0,0 +1,76 @@ +name: tdp-finder +description: successful path +tags: null +initialize: + plugins: + tdp-finder: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv + query: + name: physical-processor + output: tdp + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/csv-lookup/tdp-finder/success.yml -o + manifests/outputs/plugins/csv-lookup/tdp-finder/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:28:19.790Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - tdp-finder + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e + outputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + physical-processor: AMD 3020e + tdp: 6 diff --git a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml new file mode 100644 index 000000000..299cc1ade --- /dev/null +++ b/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml @@ -0,0 +1,73 @@ +name: divide +description: failure when `global-config.denominator` is string +tags: null +initialize: + outputs: + - yaml + plugins: + divide: + method: Divide + path: builtin + global-config: + numerator: cpu/utilization + denominator: test + output: cpu/divided-two +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml -o + manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T06:02:25.409Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingInputDataError: test is missing from the input array, or has nullish + value. +tree: + children: + child: + pipeline: + - divide + config: + divide: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 diff --git a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml new file mode 100644 index 000000000..6aa908327 --- /dev/null +++ b/manifests/outputs/plugins/divide/failure-missing-numerator.yaml @@ -0,0 +1,77 @@ +name: divide +description: success path +tags: null +initialize: + outputs: + - yaml + plugins: + divide: + method: Divide + path: builtin + global-config: + denominator: 2 + output: cpu/number-cores +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-missing-numerator.yml -o + manifests/outputs/plugins/divide/failure-missing-numerator + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:49:51.802Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "numerator" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + vcpus-allocated: 8 diff --git a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml new file mode 100644 index 000000000..5617fdbf9 --- /dev/null +++ b/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml @@ -0,0 +1,95 @@ +name: divide +description: denominator is invalid, denominator is +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 0 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/failure-denominator-equal-zero.yml -o + manifests/outputs/plugins/divide/failure-denominator-equal-zero + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T06:05:58.040Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 2 diff --git a/manifests/outputs/plugins/divide/success.yaml b/manifests/outputs/plugins/divide/success.yaml new file mode 100644 index 000000000..3c741121f --- /dev/null +++ b/manifests/outputs/plugins/divide/success.yaml @@ -0,0 +1,95 @@ +name: divide +description: success path +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated + divide: + path: builtin + method: Divide + global-config: + numerator: vcpus-allocated + denominator: 2 + output: cpu/number-cores + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/divide/success.yml -o + manifests/outputs/plugins/divide/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T05:43:34.055Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-metadata + - divide + config: + divide: null + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/utilization: 80 + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 + vcpus-allocated: 2 + cpu/number-cores: 1 diff --git a/manifests/outputs/plugins/exponent/success.yaml b/manifests/outputs/plugins/exponent/success.yaml new file mode 100644 index 000000000..1a8588693 --- /dev/null +++ b/manifests/outputs/plugins/exponent/success.yaml @@ -0,0 +1,77 @@ +name: exponent demo +description: null +tags: null +initialize: + plugins: + exponent: + path: builtin + method: Exponent + global-config: + input-parameter: cpu/energy + exponent: 2 + output-parameter: energy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/exponent/success.yml -o + manifests/outputs/plugins/exponent/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:07:19.737Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - exponent + config: + exponent: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + energy: 0.000001 diff --git a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml new file mode 100644 index 000000000..3b188a07d --- /dev/null +++ b/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml @@ -0,0 +1,96 @@ +name: groupby +description: failure when `config->group-by->group` is not an array +initialize: + outputs: + - yaml + plugins: + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-invalid-config-group.yml -o + manifests/outputs/plugins/groupby/failure-invalid-config-group + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:11:23.166Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "group" parameter is expected array, received string. + Error code: invalid_type. +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: cloud/region + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml new file mode 100644 index 000000000..ae91af1e1 --- /dev/null +++ b/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml @@ -0,0 +1,95 @@ +name: groupby +description: null +initialize: + outputs: + - yaml + plugins: + group-by: + path: builtin + method: GroupBy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yml -o + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:10:00.820Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InvalidGroupingError: Invalid group cloud/instance-type.' +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: + - cloud/region + - cloud/instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml new file mode 100644 index 000000000..04d54837b --- /dev/null +++ b/manifests/outputs/plugins/groupby/success.yaml @@ -0,0 +1,101 @@ +name: groupby +description: successful path +initialize: + plugins: + group-by: + path: builtin + method: GroupBy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/success.yml -o + manifests/outputs/plugins/groupby/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:08:31.858Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + my-app: + pipeline: + - group-by + config: + group-by: + group: + - cloud/region + - cloud/instance-type + children: + uk-west: + children: + A1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + B1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/plugins/interpolation/interpolation.yaml b/manifests/outputs/plugins/interpolation/interpolation.yaml new file mode 100644 index 000000000..9e3c45e4d --- /dev/null +++ b/manifests/outputs/plugins/interpolation/interpolation.yaml @@ -0,0 +1,83 @@ +name: interpolation-demo +description: simple demo of interpolation plugin +tags: null +initialize: + plugins: + interpolation: + path: builtin + method: Interpolation + 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 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/interpolation/interpolation.yml -o + manifests/outputs/plugins/interpolation/interpolation + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:14:18.033Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + result: 0.69625 diff --git a/manifests/outputs/plugins/interpolation/success.yaml b/manifests/outputs/plugins/interpolation/success.yaml new file mode 100644 index 000000000..bad3425f9 --- /dev/null +++ b/manifests/outputs/plugins/interpolation/success.yaml @@ -0,0 +1,83 @@ +name: interpolation-demo +description: simple demo of interpolation plugin +tags: null +initialize: + plugins: + interpolation: + path: builtin + method: Interpolation + 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 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/interpolation/success.yml -o + manifests/outputs/plugins/interpolation/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:13:22.946Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - interpolation + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + cpu/utilization: 45 + result: 0.69625 diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml new file mode 100644 index 000000000..d79f394f5 --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -0,0 +1,86 @@ +name: mock-observation-demo +description: >- + failure with `global-config->generators->randint->cpu/utilization->min` is + greater than `max` +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 99 + max: 10 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yml + -o + manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:19:22.233Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + GlobalConfigError: Min value should not be greater than or equal to max + value of cpu/utilization +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml new file mode 100644 index 000000000..3667dff6c --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -0,0 +1,84 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 99 + max: 10 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yml + -o + manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:18:11.486Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + GlobalConfigError: Min value should not be greater than or equal to max + value of memory/utilization +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml new file mode 100644 index 000000000..b8599cb08 --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -0,0 +1,83 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + outputs: + - yaml + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: builtin + global-config: + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yml + -o + manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:17:01.277Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "timestamp-from" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - mock-observations + inputs: null diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/plugins/mock-observations/success.yaml new file mode 100644 index 000000000..cacd16cad --- /dev/null +++ b/manifests/outputs/plugins/mock-observations/success.yaml @@ -0,0 +1,220 @@ +name: mock-observation-demo +description: a manifest demonstrating how to use the mock observations feature +tags: null +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/mock-observations/success.yml -o + manifests/outputs/plugins/mock-observations/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:15:43.108Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - mock-observations + inputs: null + outputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 81 + memory/utilization: 63 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 92 + memory/utilization: 63 + - timestamp: '2023-07-06T00:02:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 63 + memory/utilization: 95 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 37 + memory/utilization: 13 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 28 + memory/utilization: 50 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 98 + memory/utilization: 29 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 10 + memory/utilization: 93 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 84 + memory/utilization: 37 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 10 + memory/utilization: 30 + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 50 + memory/utilization: 10 + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 97 + memory/utilization: 89 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 61 + memory/utilization: 83 + - timestamp: '2023-07-06T00:02:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 86 + memory/utilization: 52 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 17 + memory/utilization: 60 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 53 + memory/utilization: 84 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 38 + memory/utilization: 58 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 4 + memory/utilization: 39 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 89 + memory/utilization: 52 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 38 + memory/utilization: 16 + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 25 + memory/utilization: 78 diff --git a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml new file mode 100644 index 000000000..1ef59959d --- /dev/null +++ b/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml @@ -0,0 +1,75 @@ +name: multiply +description: failure `inputs` is missing `cpu/energy` parameter +tags: null +initialize: + outputs: + - yaml + plugins: + multiply: + method: Multiply + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yml -o + manifests/outputs/plugins/multiply/failure-input-parameter-is-missing + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:23:15.185Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu/energy" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu: 0.001 + network/energy: 0.002 diff --git a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml new file mode 100644 index 000000000..76c3d93d3 --- /dev/null +++ b/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml @@ -0,0 +1,96 @@ +name: multiply +description: a manifest demonstrating how to use the multiply feature +tags: null +initialize: + plugins: + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/success-with-multiple-inputs.yml -o + manifests/outputs/plugins/multiply/success-with-multiple-inputs + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:22:04.324Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: -0.002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: 0 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + energy-product: 0.000002 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: -0.002 + energy-product: -0.00001 + - timestamp: 2023-08-06T10:00 + duration: 3600 + cpu/energy: 0.005 + network/energy: 0 + energy-product: 0 diff --git a/manifests/outputs/plugins/multiply/success.yaml b/manifests/outputs/plugins/multiply/success.yaml new file mode 100644 index 000000000..60546f50e --- /dev/null +++ b/manifests/outputs/plugins/multiply/success.yaml @@ -0,0 +1,78 @@ +name: multiply +description: a manifest demonstrating how to use the multiply feature +tags: null +initialize: + plugins: + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-product + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/multiply/success.yml -o + manifests/outputs/plugins/multiply/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T19:20:34.016Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - multiply + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.002 + energy-product: 0.000002 diff --git a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml new file mode 100644 index 000000000..8399ac20e --- /dev/null +++ b/manifests/outputs/plugins/regex/failure-missing-input-param.yaml @@ -0,0 +1,75 @@ +name: regex +description: failure with missing `physical-processor` field from `inputs` +tags: null +initialize: + outputs: + - yaml + plugins: + regex: + method: Regex + path: builtin + global-config: + parameter: physical-processor + match: ^(.*), + output: cpu/name +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/failure-missing-input-param.yml -o + manifests/outputs/plugins/regex/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:26:07.477Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + MissingInputDataError: physical-processor is missing from the input array, + or has nullish value. +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical: >- + 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 diff --git a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml new file mode 100644 index 000000000..4b1ae47d6 --- /dev/null +++ b/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml @@ -0,0 +1,76 @@ +name: regex +description: physical processor doesn't match the regex expression +tags: null +initialize: + outputs: + - yaml + plugins: + regex: + method: Regex + path: builtin + global-config: + parameter: physical-processor + match: ^ + output: cpu/name +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/failure-not-matching-with-regex.yml -o + manifests/outputs/plugins/regex/failure-not-matching-with-regex + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:24:39.241Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + RegexMismatchError: `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` does + not match the /^/ regex expression +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 diff --git a/manifests/outputs/plugins/regex/success.yaml b/manifests/outputs/plugins/regex/success.yaml new file mode 100644 index 000000000..763cd4093 --- /dev/null +++ b/manifests/outputs/plugins/regex/success.yaml @@ -0,0 +1,81 @@ +name: regex +description: successful path +tags: null +initialize: + plugins: + regex: + path: builtin + method: Regex + global-config: + parameter: physical-processor + match: ^(.*), + output: cpu/name + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/regex/success.yml -o + manifests/outputs/plugins/regex/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:23:25.744Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - regex + config: + regex: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 + cpu/name: >- + Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® + E5-2673 v4 2.3 GHz, diff --git a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml new file mode 100644 index 000000000..a3df4f806 --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -0,0 +1,75 @@ +name: sci-embodied +description: >- + failure with `defaults.device/emissions-embodied` being string instead of + number +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yml + -o + manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:49:08.280Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "device/emissions-embodied" parameter is invalid + number. please provide it as `gco2e` to input. Error code: invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: fail + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml new file mode 100644 index 000000000..073b2cb45 --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml @@ -0,0 +1,71 @@ +name: sci-embodied +description: missing device/expected-lifespan +tags: null +initialize: + outputs: + - yaml + plugins: + sci-embodied: + method: SciEmbodied + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yml + -o manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:42:51.951Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "device/expected-lifespan" parameter is required. + Error code: invalid_union. +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 diff --git a/manifests/outputs/plugins/sci-embodied/success.yaml b/manifests/outputs/plugins/sci-embodied/success.yaml new file mode 100644 index 000000000..5f74a121e --- /dev/null +++ b/manifests/outputs/plugins/sci-embodied/success.yaml @@ -0,0 +1,78 @@ +name: sci-embodied +description: successful path +tags: null +initialize: + plugins: + sci-embodied: + path: builtin + method: SciEmbodied + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci-embodied/success.yml -o + manifests/outputs/plugins/sci-embodied/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:42:03.186Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sci-embodied + defaults: + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: 1 + resources-total: 8 + carbon-embodied: 0.007292237442922374 diff --git a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml new file mode 100644 index 000000000..61c424e91 --- /dev/null +++ b/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml @@ -0,0 +1,72 @@ +name: sci +description: failure with `config.sci.functional-unit` value being number +tags: null +initialize: + outputs: + - yaml + plugins: + sci: + kind: plugin + method: Sci + path: builtin +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/failure-invalid-config-value.yml -o + manifests/outputs/plugins/sci/failure-invalid-config-value + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:38:15.858Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InputValidationError: Required' +tree: + children: + child: + pipeline: + - sci + config: + sci: + functional-unit: 999 + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + requests: 100 diff --git a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml new file mode 100644 index 000000000..656f21c1d --- /dev/null +++ b/manifests/outputs/plugins/sci/failure-missing-input-param.yaml @@ -0,0 +1,72 @@ +name: sci +description: missing input value (carbon-embodied) +tags: null +initialize: + outputs: + - yaml + plugins: + sci: + kind: plugin + method: Sci + path: builtin + global-config: + functional-unit: requests +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/failure-missing-input-param.yml -o + manifests/outputs/plugins/sci/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:36:10.588Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "carbon" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sci + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + requests: 100 diff --git a/manifests/outputs/plugins/sci/success.yml.yaml b/manifests/outputs/plugins/sci/success.yml.yaml new file mode 100644 index 000000000..bd7b81f0c --- /dev/null +++ b/manifests/outputs/plugins/sci/success.yml.yaml @@ -0,0 +1,80 @@ +name: sci +description: successful path +tags: null +initialize: + plugins: + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sci/success.yml -o + manifests/outputs/plugins/sci/success.yml + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:35:12.024Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sci + config: null + inputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + carbon: 5.02 + requests: 100 + outputs: + - timestamp: 2023-07-06T00:00 + duration: 3600 + energy: 5 + carbon-operational: 5 + carbon-embodied: 0.02 + carbon: 5.02 + requests: 100 + sci: 0.050199999999999995 diff --git a/manifests/outputs/plugins/shell/failure-invalid-command.yaml b/manifests/outputs/plugins/shell/failure-invalid-command.yaml new file mode 100644 index 000000000..f9ec8894b --- /dev/null +++ b/manifests/outputs/plugins/shell/failure-invalid-command.yaml @@ -0,0 +1,70 @@ +name: shell +description: falure with `global-config.command` being number instead od string +tags: null +initialize: + outputs: + - yaml + plugins: + shell: + method: Shell + path: builtin + global-config: + command: 1000 +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/shell/failure-invalid-command.yml -o + manifests/outputs/plugins/shell/failure-invalid-command + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:51:36.186Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "command" parameter is expected string, received + number. Error code: invalid_type. +tree: + children: + child: + pipeline: + - shell + inputs: + - timestamp: '2023-11-02T10:35:31.820Z' + duration: 3600 + cpu/energy: 0.002 + memory/energy: 0.000005 diff --git a/manifests/outputs/plugins/shell/success.yaml b/manifests/outputs/plugins/shell/success.yaml new file mode 100644 index 000000000..3a8825817 --- /dev/null +++ b/manifests/outputs/plugins/shell/success.yaml @@ -0,0 +1,68 @@ +name: shell +description: successful path +tags: null +initialize: + plugins: + shell: + path: builtin + method: Shell + global-config: + command: python3 /usr/local/bin/sampler + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/shell/success.yml -o + manifests/outputs/plugins/shell/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:50:37.625Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - shell + inputs: + - timestamp: '2023-11-02T10:35:31.820Z' + duration: 3600 + cpu/energy: 0.002 + memory/energy: 0.000005 + outputs: [] diff --git a/manifests/outputs/plugins/subtract/success.yaml b/manifests/outputs/plugins/subtract/success.yaml new file mode 100644 index 000000000..5d028f63f --- /dev/null +++ b/manifests/outputs/plugins/subtract/success.yaml @@ -0,0 +1,78 @@ +name: subtract demo +description: null +tags: null +initialize: + plugins: + subtract: + path: builtin + method: Subtract + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy/diff + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/subtract/success.yml -o + manifests/outputs/plugins/subtract/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:52:42.932Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - subtract + config: + subtract: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.003 + network/energy: 0.001 + energy/diff: 0.002 diff --git a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml new file mode 100644 index 000000000..ce59a1f4e --- /dev/null +++ b/manifests/outputs/plugins/sum/failure-missing-input-param.yaml @@ -0,0 +1,75 @@ +name: sum +description: failure with `inputs[0]` misses one of `global-config.input-parameters` +tags: null +initialize: + outputs: + - yaml + plugins: + sum: + method: Sum + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/failure-missing-input-param.yml -o + manifests/outputs/plugins/sum/failure-missing-input-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:55:20.733Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "cpu/energy" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu: 0.001 + network/energy: 0.001 diff --git a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml new file mode 100644 index 000000000..548a8b14e --- /dev/null +++ b/manifests/outputs/plugins/sum/failure-missing-output-param.yaml @@ -0,0 +1,78 @@ +name: sum +description: missing `output-parameter` in global-config +tags: null +initialize: + outputs: + - yaml + plugins: + sum: + method: Sum + path: builtin + global-config: + input-parameters: + - cpu/energy + - network/energy +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/failure-missing-output-param.yml -o + manifests/outputs/plugins/sum/failure-missing-output-param + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:54:23.422Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "output-parameter" parameter is required. Error code: + invalid_type. +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: e diff --git a/manifests/outputs/plugins/sum/success.yaml b/manifests/outputs/plugins/sum/success.yaml new file mode 100644 index 000000000..1d9b47a3f --- /dev/null +++ b/manifests/outputs/plugins/sum/success.yaml @@ -0,0 +1,78 @@ +name: sum +description: successful path +tags: null +initialize: + plugins: + sum: + path: builtin + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/sum/success.yml -o + manifests/outputs/plugins/sum/success + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T20:53:35.496Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - sum + config: + sum: null + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + network/energy: 0.001 + energy: 0.002 diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml new file mode 100644 index 000000000..e0957366a --- /dev/null +++ b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml @@ -0,0 +1,82 @@ +name: time-sync +description: >- + failure with `global-config.start-time` being later than + `global-config.end-time` +tags: null +initialize: + outputs: + - yaml + plugins: + time-sync: + method: TimeSync + path: builtin + global-config: + start-time: '2023-12-12T00:01:00.000Z' + end-time: '2023-12-12T00:00:00.000Z' + interval: 5 + allow-padding: true +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/failure-config-start-later-end.yml -o + manifests/outputs/plugins/time-sync/failure-config-start-later-end + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:13:59.114Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: 'InputValidationError: `start-time` should be lower than `end-time`' +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml new file mode 100644 index 000000000..79f3bb69e --- /dev/null +++ b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml @@ -0,0 +1,78 @@ +name: time-sync +description: missing global config +tags: null +initialize: + outputs: + - yaml + plugins: + time-sync: + method: TimeSync + path: builtin + global-config: null +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/failure-missing-global-config.yml -o + manifests/outputs/plugins/time-sync/failure-missing-global-config + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:13:12.360Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + ManifestValidationError: "initialize.plugins.time-sync.global-config" + parameter is expected object, received null. Error code: invalid_type. +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 3 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 diff --git a/manifests/outputs/plugins/time-sync/success.yaml b/manifests/outputs/plugins/time-sync/success.yaml new file mode 100644 index 000000000..1f0a7f07e --- /dev/null +++ b/manifests/outputs/plugins/time-sync/success.yaml @@ -0,0 +1,119 @@ +name: time-sync +description: successful path +tags: null +initialize: + plugins: + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + outputs: + - yaml +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/time-sync/success.yml -o + manifests/outputs/plugins/time-sync/success -s + environment: + if-version: 0.4.0 + os: macOS + os-version: '13.2' + node-version: 18.14.2 + date-time: 2024-07-02T21:12:32.629Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - time-sync + config: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + energy-cpu: 0.0018000000000000004 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + energy-cpu: 0.0007714285714285716 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + energy-cpu: 0.0004952380952380952 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + energy-cpu: 0.0001666666666666667 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + energy-cpu: 0.0001 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + energy-cpu: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + energy-cpu: 0 diff --git a/manifests/plugins/tdp-finder/failure-missing-input-param.yml b/manifests/plugins/tdp-finder/failure-missing-input-param.yml deleted file mode 100644 index 7877b56ce..000000000 --- a/manifests/plugins/tdp-finder/failure-missing-input-param.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: tdp-finder -description: failure with `inputs` missing `physical-processor` param -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 diff --git a/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml deleted file mode 100644 index 56c5c93a5..000000000 --- a/manifests/plugins/tdp-finder/failure-unsupported-physical-processor.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 302 diff --git a/manifests/plugins/tdp-finder/success.yml b/manifests/plugins/tdp-finder/success.yml deleted file mode 100644 index 26f905ecd..000000000 --- a/manifests/plugins/tdp-finder/success.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: tdp-finder -description: successful path -tags: -initialize: - outputs: ['yaml'] - plugins: - tdp-finder: # a model that returns an embodied value given the sci embodied attribution equation. - method: TdpFinder - path: "@grnsft/if-plugins" -tree: - children: - child: - pipeline: - - tdp-finder - config: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - physical-processor: AMD 3020e diff --git a/package-lock.json b/package-lock.json index 736858023..324104a9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "@grnsft/if", - "version": "0.4.0-beta.1", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@grnsft/if", - "version": "0.4.0-beta.1", + "version": "0.5.0", "license": "MIT", "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", + "@grnsft/if-core": "^0.0.10", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -23,8 +24,10 @@ "zod": "^3.22.4" }, "bin": { - "ie": "build/index.js", - "if-diff": "build/diff.js" + "if-check": "build/check.js", + "if-diff": "build/diff.js", + "if-env": "build/env.js", + "if-run": "build/index.js" }, "devDependencies": { "@babel/core": "^7.22.10", @@ -35,6 +38,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -1179,6 +1183,18 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@grnsft/if-core": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.10.tgz", + "integrity": "sha512-WHCdr7H/dFO9gT5fbjrthjOU+4RoLZ5P1F84pbGwJiKLmcU7dvYRuNQKDVIQQ7YJfZl76KSaS7sYgqA+QG8Wpw==", + "dependencies": { + "typescript": "^5.1.6" + }, + "engines": { + "node": ">=18", + "npm": ">=8" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "dev": true, @@ -3004,11 +3020,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3757,6 +3774,24 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "license": "MIT", @@ -5003,9 +5038,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6321,8 +6357,9 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -11087,8 +11124,9 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, diff --git a/package.json b/package.json index 718c4b4e4..768ab1bd0 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "@grnsft/if", "description": "Impact Framework", - "version": "0.4.0-beta.1", + "version": "0.5.0", "author": { "name": "Green Software Foundation", "email": "info@gsf.com" }, "bin": { - "ie": "./build/index.js", - "if-diff": "./build/diff.js" + "if-diff": "./build/diff.js", + "if-run": "./build/index.js", + "if-env": "./build/env.js", + "if-check": "./build/check.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -16,6 +18,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", + "@grnsft/if-core": "^0.0.10", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -36,6 +39,7 @@ "@types/luxon": "^3.4.2", "@types/node": "^20.8.9", "axios-mock-adapter": "^1.22.0", + "cross-env": "7.0.3", "fixpack": "^4.0.0", "gts": "^5.0.0", "husky": "^8.0.0", @@ -72,8 +76,10 @@ "coverage": "jest --verbose --coverage --testPathPattern=src/__tests__/unit", "fix": "gts fix", "fix:package": "fixpack", - "ie": "npx ts-node src/index.ts", + "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/check.ts", "if-diff": "npx ts-node src/diff.ts", + "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/env.ts", + "if-run": "npx ts-node src/index.ts", "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", diff --git a/scripts/run-yamls.sh b/scripts/run-yamls.sh index 11371af66..fbe394c6b 100644 --- a/scripts/run-yamls.sh +++ b/scripts/run-yamls.sh @@ -4,5 +4,5 @@ echo 'Running all manifests' for f in ./examples/manifests/*.yml; do echo "Processing $f file..."; - npm run ie -- --manifest $f + npm run if-run -- --manifest $f done diff --git a/src/__mocks__/builtins/export-csv.ts b/src/__mocks__/builtins/export-csv.ts index e8fc2a26f..1f0e00e73 100644 --- a/src/__mocks__/builtins/export-csv.ts +++ b/src/__mocks__/builtins/export-csv.ts @@ -14,7 +14,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', }, inputs: [ { @@ -43,7 +42,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', 'cpu/energy': 0.000008888888888888888, "carbon-plus-energy'": 10.000008888888889, 'carbon-embodied': 0.0000020256215119228817, @@ -65,7 +63,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', }, inputs: [ { @@ -94,7 +91,6 @@ export const tree = { 'device/expected-lifespan': 94608000, 'resources-reserved': 1, 'resources-total': 8, - 'functional-unit-time': '1 min', 'cpu/energy': 0.00001650338753387534, "carbon-plus-energy'": 10.000016503387533, 'carbon-embodied': 0.0000020256215119228817, @@ -154,7 +150,6 @@ export const context: Context = { method: 'Sci', 'global-config': { 'functional-unit': 'requests', - 'functional-unit-time': '1 minute', }, }, }, diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index da8438c8b..6d4f61b8b 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -1,10 +1,20 @@ import * as YAML from 'js-yaml'; +import * as fs from 'fs'; +import * as fsAsync from 'fs/promises'; +import * as path from 'path'; export const readFile = async (filePath: string) => { + /** mock for util/npm */ + if (filePath.includes('package.json-npm')) { + const updatedPath = filePath.replace('-npm', ''); + return fs.readFileSync(updatedPath, 'utf8'); + } + /** mock for util/json */ if (filePath.includes('json-reject')) { return Promise.reject(new Error('rejected')); } + if (filePath.includes('json')) { if (filePath.includes('param')) { return JSON.stringify({ @@ -28,6 +38,13 @@ export const readFile = async (filePath: string) => { throw new Error('file not found'); } + if (filePath.includes('fail-csv-reader.csv')) { + return ` +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 +16,16,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.4xlarge,EBS-Only,32,32,November 2018,`; + } + /** * Used for csv lookup plugin. */ @@ -73,16 +90,98 @@ cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,g export const mkdir = (dirPath: string) => dirPath; export const writeFile = async (pathToFile: string, content: string) => { - if (pathToFile === 'reject') { - throw new Error('Wrong file path'); + if (pathToFile.includes('package.json-npm1')) { + const updatedPath = pathToFile.replace('-npm1', ''); + const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); + const fileContentObject = JSON.parse(fileContent); + const parsedContent = JSON.parse(content); + + for (const property in fileContentObject) { + expect(parsedContent).toHaveProperty(property); + } + } else if (pathToFile.includes('package.json-npm')) { + const updatedPath = pathToFile.replace('-npm', ''); + const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); + + expect(content).toBe(fileContent); + } else if (pathToFile.includes('/manifest.yml')) { + const templateManifest = path.resolve( + __dirname, + '../../config/env-template.yml' + ); + const fileContent = await fsAsync.readFile(templateManifest, 'utf8'); + + expect(content).toBe(fileContent); + } else { + if (pathToFile === 'reject') { + throw new Error('Wrong file path'); + } + + const mockPathToFile = 'mock-pathToFile'; + const mockContent = { + name: 'mock-name', + }; + const mockObject = YAML.dump(mockContent, {noRefs: true}); + + expect(pathToFile).toBe(mockPathToFile); + expect(content).toBe(mockObject); + } +}; + +export const stat = async (filePath: string) => { + if (filePath === 'true') { + return true; + } else { + throw new Error('File not found.'); } +}; - const mockPathToFile = 'mock-pathToFile'; - const mockContent = { - name: 'mock-name', - }; - const mockObject = YAML.dump(mockContent, {noRefs: true}); +export const access = async (directoryPath: string) => { + if (directoryPath === 'true') { + return true; + } else { + throw new Error('Directory not found.'); + } +}; - expect(pathToFile).toBe(mockPathToFile); - expect(content).toBe(mockObject); +export const unlink = async (filePath: string) => { + if (filePath === 'true') { + return; + } else { + throw new Error('File not found.'); + } +}; + +export const readdir = (directoryPath: string) => { + if (directoryPath.includes('mock-empty-directory')) { + return []; + } + + if (directoryPath.includes('mock-directory')) { + return ['file1.yaml', 'file2.yml', 'file3.txt']; + } + + if (directoryPath.includes('mock-sub-directory')) { + return ['subdir/file2.yml', 'file1.yaml']; + } + + return []; +}; + +export const lstat = (filePath: string) => { + if ( + filePath.includes('mock-directory') || + filePath.includes('mock-sub-directory/subdir') + ) { + return { + isDirectory: () => true, + }; + } + + if (filePath.includes('mock-file')) { + return { + isDirectory: () => false, + }; + } + return; }; diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml new file mode 100644 index 000000000..1e38c1b13 --- /dev/null +++ b/src/__mocks__/mock-manifest.yaml @@ -0,0 +1,72 @@ +name: template manifest +description: auto-generated template +tags: null +initialize: + plugins: + memory-energy-from-memory-util: + path: builtin + method: Coefficient + global-config: + input-parameter: memory/utilization + coefficient: 0.0001 + output-parameter: memory/energy + outputs: + - yaml +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/index.ts -m + ./src/env-template.yml -o ./manifests/outputs/template + environment: + if-version: 0.4.0 + os: macOS + os-version: 13.6.6 + node-version: 20.12.2 + date-time: 2024-06-18T08:39:55.771Z (UTC) + dependencies: + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.3" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - memory-energy-from-memory-util + config: null + inputs: + - timestamp: 2023-12-12T00:00:00.000Z + duration: 3600 + memory/utilization: 10 + outputs: + - timestamp: 2023-12-12T00:00:00.000Z + duration: 3600 + memory/utilization: 10 + memory/energy: 0.001 diff --git a/src/__mocks__/plugin/lib/mockavizta/index.ts b/src/__mocks__/plugin/lib/mockavizta/index.ts index 163a0cd24..54feae6a2 100644 --- a/src/__mocks__/plugin/lib/mockavizta/index.ts +++ b/src/__mocks__/plugin/lib/mockavizta/index.ts @@ -1,4 +1,4 @@ -import {PluginParams} from '../../../../types/interface'; +import {PluginParams} from '@grnsft/if-core/types'; /** * Mock model for testing. diff --git a/src/__tests__/integration/scenarios/sci-e.ts b/src/__tests__/integration/scenarios/sci-e.ts index 9fb808341..0342240c2 100644 --- a/src/__tests__/integration/scenarios/sci-e.ts +++ b/src/__tests__/integration/scenarios/sci-e.ts @@ -36,7 +36,7 @@ describe('integration/sci-e', () => { await saveYamlFileAs(file, absoluteManifestPath); // save yaml uses absolute path const response = ( await execPromise( - `npm run ie -- --manifest ${relativeManifestPath} --stdout` + `npm run if-run -- --manifest ${relativeManifestPath} --stdout` ) ).stdout; // exec promise uses relative path diff --git a/src/__tests__/unit/builtins/CommonGenerator.test.ts b/src/__tests__/unit/builtins/CommonGenerator.test.ts index 881aa810e..b0c165d1a 100644 --- a/src/__tests__/unit/builtins/CommonGenerator.test.ts +++ b/src/__tests__/unit/builtins/CommonGenerator.test.ts @@ -1,12 +1,13 @@ -import {KeyValuePair} from '../../../types/common'; - -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core/utils'; import {CommonGenerator} from '../../../builtins/mock-observations/helpers/common-generator'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; -describe('lib/mock-observations/CommonGenerator: ', () => { +describe('builtins/mock-observations/CommonGenerator: ', () => { describe('initialize: ', () => { it('throws an error when config is not empty object.', async () => { const commonGenerator = CommonGenerator({}); @@ -16,18 +17,14 @@ describe('lib/mock-observations/CommonGenerator: ', () => { try { commonGenerator.next([]); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'CommonGenerator: Config must not be null or empty.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); }); describe('next(): ', () => { it('returns a result with valid data.', async () => { - const config: KeyValuePair = { + const config: Record = { key1: 'value1', key2: 'value2', }; @@ -35,7 +32,7 @@ describe('lib/mock-observations/CommonGenerator: ', () => { expect.assertions(1); - expect(commonGenerator.next([])).toStrictEqual({ + expect(commonGenerator.next([])).toEqual({ key1: 'value1', key2: 'value2', }); diff --git a/src/__tests__/unit/builtins/RandIntGenerator.test.ts b/src/__tests__/unit/builtins/RandIntGenerator.test.ts index c904f7350..328f7d6f4 100644 --- a/src/__tests__/unit/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/unit/builtins/RandIntGenerator.test.ts @@ -1,23 +1,20 @@ -import {KeyValuePair} from '../../../types/common'; - -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core/utils'; import {RandIntGenerator} from '../../../builtins/mock-observations/helpers/rand-int-generator'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {GlobalConfigError} = ERRORS; +const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; -describe('lib/mock-observations/RandIntGenerator: ', () => { +describe('builtins/mock-observations/RandIntGenerator: ', () => { describe('initialize', () => { it('throws an error when the generator name is empty string.', async () => { expect.assertions(1); try { RandIntGenerator('', {}); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: `name` is empty or all spaces.' - ) - ); + expect(error).toEqual(new GlobalConfigError(INVALID_NAME)); } }); @@ -26,11 +23,7 @@ describe('lib/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('generator-name', {}); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: Config must not be null or empty.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -42,18 +35,14 @@ describe('lib/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('random', config); } catch (error) { - expect(error).toEqual( - new InputValidationError( - 'RandIntGenerator: Config is missing min or max.' - ) - ); + expect(error).toEqual(new GlobalConfigError(MISSING_MIN_MAX)); } }); }); describe('next(): ', () => { it('returns a result with valid data.', async () => { - const config: KeyValuePair = { + const config: Record = { min: 10, max: 90, }; diff --git a/src/__tests__/unit/builtins/coefficient.test.ts b/src/__tests__/unit/builtins/coefficient.test.ts index bf7455679..034d20f95 100644 --- a/src/__tests__/unit/builtins/coefficient.test.ts +++ b/src/__tests__/unit/builtins/coefficient.test.ts @@ -1,8 +1,11 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {Coefficient} from '../../../builtins/coefficient'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { describe('Coefficient: ', () => { @@ -49,7 +52,6 @@ describe('builtins/coefficient: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; const coefficient = Coefficient(config!); - const expectedMessage = 'Global config is not provided.'; expect.assertions(1); @@ -62,7 +64,9 @@ describe('builtins/coefficient: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); diff --git a/src/__tests__/unit/builtins/copy-param.test.ts b/src/__tests__/unit/builtins/copy-param.test.ts new file mode 100644 index 000000000..64809e44a --- /dev/null +++ b/src/__tests__/unit/builtins/copy-param.test.ts @@ -0,0 +1,124 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {Copy} from '../../../builtins/copy-param'; + +import {STRINGS} from '../../../config'; + +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/copy: ', () => { + describe('Copy: ', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(copy).toHaveProperty('metadata'); + expect(copy).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies Copy strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + original: '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 copy = Copy(config!); + + expect.assertions(1); + + try { + copy.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + original: 1, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', () => { + const globalConfig = { + 'keep-existing': true, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + expect.assertions(1); + + try { + copy.execute([ + { + duration: 3600, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"original" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + it('does not persist the original value when keep-existing==false.', () => { + expect.assertions(1); + const globalConfig = { + 'keep-existing': false, + from: 'original', + to: 'copy', + }; + const copy = Copy(globalConfig); + + const expectedResult = [ + { + duration: 3600, + 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); + }); + }); + }); +}); diff --git a/src/__tests__/unit/builtins/csv-lookup.test.ts b/src/__tests__/unit/builtins/csv-lookup.test.ts index 4e16fd9b6..81e0498b4 100644 --- a/src/__tests__/unit/builtins/csv-lookup.test.ts +++ b/src/__tests__/unit/builtins/csv-lookup.test.ts @@ -2,12 +2,21 @@ jest.mock('fs/promises', () => require('../../../__mocks__/fs')); import axios from 'axios'; import AxiosMockAdapter from 'axios-mock-adapter'; +import {ERRORS} from '@grnsft/if-core/utils'; import {CSVLookup} from '../../../builtins'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {FileNotFoundError, InputValidationError, ConfigNotFoundError} = ERRORS; +const { + GlobalConfigError, + ReadFileError, + FetchingFileError, + QueryDataNotFoundError, + MissingCSVColumnError, + CSVParseError, +} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { const mock = new AxiosMockAdapter(axios); @@ -131,7 +140,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(ReadFileError); } } }); @@ -160,7 +169,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(ReadFileError); } } }); @@ -192,7 +201,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(FileNotFoundError); + expect(error).toBeInstanceOf(FetchingFileError); } } }); @@ -340,11 +349,8 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error.message).toEqual( - `Error happened while parsing given CSV file: ./file.csv -InputValidationError: One or more of the given query parameters are not found in the target CSV file column headers.` - ); + expect(error).toBeInstanceOf(QueryDataNotFoundError); + expect(error.message).toEqual(NO_QUERY_DATA); } } }); @@ -368,8 +374,8 @@ InputValidationError: One or more of the given query parameters are not found in await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(ConfigNotFoundError); - expect(error.message).toEqual('Global config is not provided.'); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error.message).toEqual(MISSING_GLOBAL_CONFIG); } } }); @@ -400,10 +406,9 @@ InputValidationError: One or more of the given query parameters are not found in await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingCSVColumnError); expect(error.message).toEqual( - `Error happened while parsing given CSV file: ./file.csv -InputValidationError: There is no column with name: mock.` + MISSING_CSV_COLUMN(globalConfig.output) ); } } @@ -477,5 +482,33 @@ InputValidationError: There is no column with name: mock.` expect(result).toStrictEqual(expectedResult); }); }); + + it('rejects with CSV parse error', async () => { + process.env.csv = 'fail'; + expect.assertions(1); + const globalConfig = { + filepath: './fail-csv-reader.csv', + query: { + 'cpu-cores-available': 'cpu/available', + 'cpu-cores-utilized': 'cpu/utilized', + 'cpu-manufacturer': 'cpu/manufacturer', + }, + output: [['gpu-count']], + }; + const csvLookup = CSVLookup(globalConfig); + + try { + await csvLookup.execute([ + { + timestamp: '2024-03-01', + 'cpu/available': 16, + 'cpu/utilized': 16, + 'cpu/manufacturer': 'AWS', + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(CSVParseError); + } + }); }); }); diff --git a/src/__tests__/unit/builtins/divide.test.ts b/src/__tests__/unit/builtins/divide.test.ts index 8f56bb19d..ba75e3879 100644 --- a/src/__tests__/unit/builtins/divide.test.ts +++ b/src/__tests__/unit/builtins/divide.test.ts @@ -1,8 +1,11 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {Divide} from '../../../builtins'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { describe('Divide: ', () => { @@ -103,7 +106,6 @@ describe('builtins/divide: ', () => { }); it('throws an error on missing global config.', async () => { - const expectedMessage = 'Global config is not provided.'; const config = undefined; const divide = Divide(config!); @@ -117,14 +119,13 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); it('throws an error when `denominator` is 0.', async () => { - const expectedMessage = - '"denominator" parameter is number must be greater than 0. Error code: too_small.'; - const globalConfig = { numerator: 'vcpus-allocated', denominator: 0, @@ -134,22 +135,25 @@ describe('builtins/divide: ', () => { expect.assertions(1); - try { - await divide.execute([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 3600, - 'vcpus-allocated': 24, - }, - ]); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(expectedMessage)); - } + const response = await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]); + + expect(response).toEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + 'vcpus-allocated-per-second': 24, + }, + ]); }); it('throws an error when `denominator` is string.', async () => { - const expectedMessage = '`10` is missing from the input.'; - const globalConfig = { numerator: 'vcpus-allocated', denominator: '10', @@ -168,7 +172,11 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(expectedMessage)); + expect(error).toStrictEqual( + new MissingInputDataError( + MISSING_INPUT_DATA(globalConfig.denominator) + ) + ); } }); }); diff --git a/src/__tests__/unit/builtins/exponent.test.ts b/src/__tests__/unit/builtins/exponent.test.ts index 54c69ffcb..ad438179d 100644 --- a/src/__tests__/unit/builtins/exponent.test.ts +++ b/src/__tests__/unit/builtins/exponent.test.ts @@ -1,10 +1,10 @@ -import {Exponent} from '../../../builtins/exponent'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {Exponent} from '../../../builtins/exponent'; const {InputValidationError} = ERRORS; -describe('lib/exponent: ', () => { +describe('builtins/exponent: ', () => { describe('Exponent: ', () => { const globalConfig = { 'input-parameter': 'energy/base', @@ -45,9 +45,6 @@ describe('lib/exponent: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Exponent: energy/base is missing from the input array.'; - expect.assertions(1); try { @@ -59,27 +56,30 @@ describe('lib/exponent: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError( + '"input-parameter" parameter is required. Error code: invalid_type.' + ) ); } }); it('throws an error on input param value not numeric.', async () => { - const expectedMessage = 'Exponent: i-am-not-a-number is not numeric.'; - expect.assertions(1); + const input = [ + { + duration: 3600, + 'energy/base': 'i-am-not-a-number', + timestamp: '2021-01-01T00:00:00Z', + }, + ]; try { - await exponent.execute([ - { - duration: 3600, - 'energy/base': 'i-am-not-a-number', - timestamp: '2021-01-01T00:00:00Z', - }, - ]); + await exponent.execute(input); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError( + '"input-parameter" parameter is expected number, received string. Error code: invalid_type.' + ) ); } }); diff --git a/src/__tests__/unit/builtins/export-csv-raw.test.ts b/src/__tests__/unit/builtins/export-csv-raw.test.ts index 1ebf9e45e..e97242a4d 100644 --- a/src/__tests__/unit/builtins/export-csv-raw.test.ts +++ b/src/__tests__/unit/builtins/export-csv-raw.test.ts @@ -1,12 +1,16 @@ import * as fs from 'fs/promises'; + import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core/utils'; import {ExportCSVRaw} from '../../../builtins/export-csv-raw'; -import {ERRORS} from '../../../util/errors'; + +import {STRINGS} from '../../../config'; import {tree, context, outputs} from '../../../__mocks__/builtins/export-csv'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {WRITE_CSV_ERROR, OUTPUT_REQUIRED} = STRINGS; jest.mock('fs/promises', () => ({ __esModule: true, @@ -31,7 +35,7 @@ describe('builtins/export-csv-raw: ', () => { it('generates CSV file with correct data.', async () => { const outputPath = 'output#carbon'; const content = - "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,functional-unit-time,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,1 min,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,1 min,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,,8000.000004051243,"; + "id,timestamp,cloud/instance-type,region,duration,cpu/utilization,network/energy,energy,cpu/thermal-design-power,grid/carbon-intensity,device/emissions-embodied,time-reserved,device/expected-lifespan,resources-reserved,resources-total,cpu/energy,carbon-plus-energy',carbon-embodied,carbon-operational,carbon,sci\nchildren.child-1.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,10,10,5,100,800,1533.12,3600,94608000,1,8,0.000008888888888888888,10.000008888888889,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\nchildren.child-2.outputs.0,2023-12-12T00:00:00.000Z,A1,uk-west,1,30,10,5,100,800,1533.12,3600,94608000,1,8,0.00001650338753387534,10.000016503387533,0.0000020256215119228817,4000,4000.0000020256216,240000.0001215373\noutputs.0,2023-12-12T00:00:00.000Z,,,1,,,,,,,,,,,,,,,8000.000004051243,"; await exportCSVRaw.execute(tree, context, outputPath); @@ -40,18 +44,17 @@ describe('builtins/export-csv-raw: ', () => { it('throws an error when the CSV file could not be created.', async () => { const outputPath = 'output#carbon'; + const expectedMessage = 'Could not write CSV file.'; expect.assertions(1); - jest - .spyOn(fs, 'writeFile') - .mockRejectedValue('Could not write CSV file.'); + jest.spyOn(fs, 'writeFile').mockRejectedValue(expectedMessage); await expect( exportCSVRaw.execute(tree, context, outputPath) ).rejects.toThrow( - new ExhaustError( - 'Failed to write CSV to output#carbon: Could not write CSV file.' + new ExhaustOutputArgError( + WRITE_CSV_ERROR(outputPath, expectedMessage) ) ); }); @@ -65,8 +68,8 @@ describe('builtins/export-csv-raw: ', () => { try { await exportCSVRaw.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); }); diff --git a/src/__tests__/unit/builtins/export-csv.test.ts b/src/__tests__/unit/builtins/export-csv.test.ts index 94414a970..78feaf534 100644 --- a/src/__tests__/unit/builtins/export-csv.test.ts +++ b/src/__tests__/unit/builtins/export-csv.test.ts @@ -1,9 +1,12 @@ import * as fs from 'fs/promises'; + import {stringify} from 'csv-stringify/sync'; import {jest} from '@jest/globals'; +import {ERRORS} from '@grnsft/if-core/utils'; import {ExportCSV} from '../../../builtins/export-csv'; -import {ERRORS} from '../../../util/errors'; + +import {STRINGS} from '../../../config'; import { tree, @@ -13,7 +16,8 @@ import { aggregation, } from '../../../__mocks__/builtins/export-csv'; -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED, CSV_EXPORT} = STRINGS; jest.mock('fs/promises', () => ({ writeFile: jest.fn<() => Promise>().mockResolvedValue(), @@ -197,8 +201,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); @@ -210,10 +214,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual( - new ExhaustError('Output path should contain `#`.') - ); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); } }); @@ -225,12 +227,8 @@ describe('builtins/export-csv: ', () => { try { await exportCSV.execute(tree, context, outputPath); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual( - new ExhaustError( - 'CSV export criteria is not found in output path. Please append it after --output #.' - ) - ); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(CSV_EXPORT)); } }); }); diff --git a/src/__tests__/unit/builtins/export-yaml.test.ts b/src/__tests__/unit/builtins/export-yaml.test.ts index a2157e4ef..fb7954c1e 100644 --- a/src/__tests__/unit/builtins/export-yaml.test.ts +++ b/src/__tests__/unit/builtins/export-yaml.test.ts @@ -1,14 +1,18 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {ExportYaml} from '../../../builtins/export-yaml'; -import {ERRORS} from '../../../util/errors'; import {saveYamlFileAs} from '../../../util/yaml'; +import {STRINGS} from '../../../config'; + import {tree, context} from '../../../__mocks__/builtins/export-csv'; jest.mock('../../../util/yaml', () => ({ saveYamlFileAs: jest.fn(), })); -const {ExhaustError} = ERRORS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED} = STRINGS; describe('builtins/export-yaml: ', () => { describe('ExportYaml: ', () => { @@ -38,8 +42,8 @@ describe('builtins/export-yaml: ', () => { try { await exportYaml.execute({}, context, ''); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); - expect(error).toEqual(new ExhaustError('Output path is required.')); + expect(error).toBeInstanceOf(ExhaustOutputArgError); + expect(error).toEqual(new ExhaustOutputArgError(OUTPUT_REQUIRED)); } }); }); diff --git a/src/__tests__/unit/builtins/group-by.test.ts b/src/__tests__/unit/builtins/group-by.test.ts index 9c99ee700..3d676148b 100644 --- a/src/__tests__/unit/builtins/group-by.test.ts +++ b/src/__tests__/unit/builtins/group-by.test.ts @@ -1,7 +1,11 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {GroupBy} from '../../../builtins/group-by'; -import {ERRORS} from '../../../util/errors'; -const {InvalidGroupingError, InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {InvalidGroupingError, InputValidationError, GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, INVALID_GROUP_BY} = STRINGS; describe('builtins/group-by: ', () => { describe('GroupBy: ', () => { @@ -92,10 +96,8 @@ describe('builtins/group-by: ', () => { try { plugin.execute(inputs, config!); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError('Config is not provided.') - ); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -166,7 +168,7 @@ describe('builtins/group-by: ', () => { } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( - new InvalidGroupingError('Invalid group unknown.') + new InvalidGroupingError(INVALID_GROUP_BY(config.group[2])) ); } }); diff --git a/src/__tests__/unit/builtins/interpolation.test.ts b/src/__tests__/unit/builtins/interpolation.test.ts index c4bba939f..6219e01ec 100644 --- a/src/__tests__/unit/builtins/interpolation.test.ts +++ b/src/__tests__/unit/builtins/interpolation.test.ts @@ -1,8 +1,17 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {Method} from '@grnsft/if-core/types'; + import {Interpolation} from '../../../builtins'; -import {Method} from '../../../builtins/interpolation/types'; -import {ERRORS} from '../../../util/errors'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +import {STRINGS} from '../../../config'; + +const {InputValidationError, GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + WITHIN_THE_RANGE, + ARRAY_LENGTH_NON_EMPTY, + X_Y_EQUAL, +} = STRINGS; describe('builtins/interpolation: ', () => { describe('Interpolation: ', () => { @@ -144,10 +153,8 @@ describe('builtins/interpolation: ', () => { try { plugin.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(ConfigNotFoundError); - expect(error).toEqual( - new ConfigNotFoundError('Global config is not provided.') - ); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); } }); @@ -163,11 +170,7 @@ describe('builtins/interpolation: ', () => { plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - 'The length of `x` and `y` should be equal' - ) - ); + expect(error).toEqual(new InputValidationError(X_Y_EQUAL)); } }); @@ -184,11 +187,7 @@ describe('builtins/interpolation: ', () => { plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - 'The target x value must be within the range of the given x values' - ) - ); + expect(error).toEqual(new InputValidationError(WITHIN_THE_RANGE)); } }); it('throws an error when the the length of the input arrays is <2', () => { @@ -213,9 +212,7 @@ describe('builtins/interpolation: ', () => { } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( - new InputValidationError( - 'the length of the input arrays must be greater than 1' - ) + new InputValidationError(ARRAY_LENGTH_NON_EMPTY) ); } }); diff --git a/src/__tests__/unit/builtins/mock-observations.test.ts b/src/__tests__/unit/builtins/mock-observations.test.ts index 37d3a04b4..fd28d5595 100644 --- a/src/__tests__/unit/builtins/mock-observations.test.ts +++ b/src/__tests__/unit/builtins/mock-observations.test.ts @@ -1,10 +1,13 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {MockObservations} from '../../../builtins/mock-observations'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError} = ERRORS; +const {InputValidationError, GlobalConfigError} = ERRORS; +const {INVALID_MIN_MAX} = STRINGS; -describe('lib/mock-observations: ', () => { +describe('builtins/mock-observations: ', () => { describe('init: ', () => { it('successfully initalized.', () => { const mockObservations = MockObservations({ @@ -88,8 +91,6 @@ describe('lib/mock-observations: ', () => { }); it('throws an error when the `min` is greater then `max` of `randint` config.', async () => { - const errorMessage = - 'RandIntGenerator: Min value should not be greater than or equal to max value of cpu/utilization.'; const config = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', @@ -112,8 +113,10 @@ describe('lib/mock-observations: ', () => { try { await mockObservations.execute([]); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual(new InputValidationError(errorMessage)); + expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toEqual( + new GlobalConfigError(INVALID_MIN_MAX('cpu/utilization')) + ); } }); diff --git a/src/__tests__/unit/builtins/multiply.test.ts b/src/__tests__/unit/builtins/multiply.test.ts index a4451179d..d15a7e8f9 100644 --- a/src/__tests__/unit/builtins/multiply.test.ts +++ b/src/__tests__/unit/builtins/multiply.test.ts @@ -1,10 +1,10 @@ -import {Multiply} from '../../../builtins/multiply'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {Multiply} from '../../../builtins/multiply'; const {InputValidationError} = ERRORS; -describe('lib/multiply: ', () => { +describe('builtins/multiply: ', () => { describe('Multiply: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,9 +48,6 @@ describe('lib/multiply: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Multiply: cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -62,7 +59,9 @@ describe('lib/multiply: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); @@ -88,10 +87,10 @@ describe('lib/multiply: ', () => { const expectedResult = [ { duration: 3600, + timestamp: '2021-01-01T00:00:00Z', carbon: 3, 'other-carbon': 2, 'carbon-product': 6, - timestamp: '2021-01-01T00:00:00Z', }, ]; diff --git a/src/__tests__/unit/builtins/regex.test.ts b/src/__tests__/unit/builtins/regex.test.ts index 19ccdf89d..54a70ed9e 100644 --- a/src/__tests__/unit/builtins/regex.test.ts +++ b/src/__tests__/unit/builtins/regex.test.ts @@ -1,10 +1,13 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {Regex} from '../../../builtins/regex'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigValidationError} = ERRORS; +const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -describe('lib/regex: ', () => { +describe('builtins/regex: ', () => { describe('Regex: ', () => { const globalConfig = { parameter: 'physical-processor', @@ -81,7 +84,6 @@ describe('lib/regex: ', () => { it('throws an error when `parameter` does not match to `match`.', 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'; - const expectedMessage = `Regex: \`${physicalProcessor}\` does not match the /^(^:)+/ regex expression.`; const globalConfig = { parameter: 'physical-processor', @@ -102,14 +104,14 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new RegexMismatchError( + REGEX_MISMATCH(physicalProcessor, '/^(^:)+/') + ) ); } }); it('throws an error on missing global config.', async () => { - const expectedMessage = 'Regex: Configuration data is missing.'; - const config = undefined; const regex = Regex(config!); @@ -124,15 +126,12 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigValidationError(expectedMessage) + new GlobalConfigError(MISSING_GLOBAL_CONFIG) ); } }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Regex: `physical-processor` is missing from the input.'; - expect.assertions(1); try { @@ -144,7 +143,7 @@ describe('lib/regex: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new MissingInputDataError(MISSING_INPUT_DATA('physical-processor')) ); } }); diff --git a/src/__tests__/unit/builtins/sci-embodied.test.ts b/src/__tests__/unit/builtins/sci-embodied.test.ts index 75f9f12fd..a3f5bcbff 100644 --- a/src/__tests__/unit/builtins/sci-embodied.test.ts +++ b/src/__tests__/unit/builtins/sci-embodied.test.ts @@ -1,9 +1,13 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {SciEmbodied} from '../../../builtins/sci-embodied'; -import {ERRORS} from '../../../util/errors'; + +import {STRINGS} from '../../../config'; const {InputValidationError} = ERRORS; +const {SCI_EMBODIED_ERROR} = STRINGS; -describe('lib/sci-embodied:', () => { +describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { const sciEmbodied = SciEmbodied(); @@ -191,8 +195,6 @@ describe('lib/sci-embodied:', () => { }); it('throws an error when `device/emissions-embodied` is string.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is not a valid number in input. please provide it as `gco2e`. Error code: invalid_union.'; const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -216,7 +218,13 @@ describe('lib/sci-embodied:', () => { try { await sciEmbodied.execute(inputs); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); expect(error).toBeInstanceOf(InputValidationError); } }); @@ -268,8 +276,6 @@ describe('lib/sci-embodied:', () => { }); it('throws an exception on invalid values.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is not a valid number in input. please provide it as `gco2e`. Error code: invalid_union.'; const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -285,8 +291,14 @@ describe('lib/sci-embodied:', () => { try { await sciEmbodied.execute(inputs); } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); expect(error).toBeInstanceOf(InputValidationError); + expect(error).toStrictEqual( + new InputValidationError( + `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( + 'gco2e' + )}. Error code: invalid_union.` + ) + ); } }); }); diff --git a/src/__tests__/unit/builtins/sci.test.ts b/src/__tests__/unit/builtins/sci.test.ts index 2b6261cda..6a8ddc8db 100644 --- a/src/__tests__/unit/builtins/sci.test.ts +++ b/src/__tests__/unit/builtins/sci.test.ts @@ -1,10 +1,10 @@ -import {Sci} from '../../../builtins/sci'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {Sci} from '../../../builtins/sci'; -const {InputValidationError} = ERRORS; +const {MissingInputDataError} = ERRORS; -describe('lib/sci:', () => { +describe('builtins/sci:', () => { describe('Sci: ', () => { const sci = Sci({'functional-unit': 'users'}); @@ -113,7 +113,7 @@ describe('lib/sci:', () => { try { await sci.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingInputDataError); } }); @@ -136,9 +136,30 @@ describe('lib/sci:', () => { try { await sci.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(MissingInputDataError); } }); }); + + it('fallbacks to carbon value, if functional unit is 0.', async () => { + const sci = Sci({ + 'functional-unit': 'requests', + }); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.2, + 'carbon-embodied': 0.05, + carbon: 0.205, + duration: 1, + requests: 0, + }, + ]; + const result = await sci.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); + }); }); }); diff --git a/src/__tests__/unit/builtins/shell.test.ts b/src/__tests__/unit/builtins/shell.test.ts index 7f1ffd58c..96de944f1 100644 --- a/src/__tests__/unit/builtins/shell.test.ts +++ b/src/__tests__/unit/builtins/shell.test.ts @@ -1,16 +1,15 @@ import {spawnSync} from 'child_process'; import {loadAll} from 'js-yaml'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Shell} from '../../../builtins/shell'; -import {ERRORS} from '../../../util/errors'; - -const {InputValidationError} = ERRORS; +const {InputValidationError, ProcessExecutionError} = ERRORS; jest.mock('child_process'); jest.mock('js-yaml'); -describe('lib/shell', () => { +describe('builtins/shell', () => { describe('Shell', () => { const shell = Shell({}); @@ -87,9 +86,9 @@ describe('lib/shell', () => { try { await shell.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(ProcessExecutionError); expect(error).toStrictEqual( - new InputValidationError('Could not run the command') + new ProcessExecutionError('Could not run the command') ); } }); diff --git a/src/__tests__/unit/builtins/subtract.test.ts b/src/__tests__/unit/builtins/subtract.test.ts index 7ac717142..fd4cf7c96 100644 --- a/src/__tests__/unit/builtins/subtract.test.ts +++ b/src/__tests__/unit/builtins/subtract.test.ts @@ -1,10 +1,10 @@ -import {Subtract} from '../../../builtins/subtract'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {Subtract} from '../../../builtins/subtract'; const {InputValidationError} = ERRORS; -describe('lib/subtract: ', () => { +describe('builtins/subtract: ', () => { describe('Subtract: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,9 +48,6 @@ describe('lib/subtract: ', () => { }); it('throws an error on missing params in input.', async () => { - const expectedMessage = - 'Subtract: cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -62,7 +59,9 @@ describe('lib/subtract: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); diff --git a/src/__tests__/unit/builtins/sum.test.ts b/src/__tests__/unit/builtins/sum.test.ts index 734ea8db2..1810fc13a 100644 --- a/src/__tests__/unit/builtins/sum.test.ts +++ b/src/__tests__/unit/builtins/sum.test.ts @@ -1,10 +1,13 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {Sum} from '../../../builtins/sum'; -import {ERRORS} from '../../../util/errors'; +import {STRINGS} from '../../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; -describe('lib/sum: ', () => { +describe('builtins/sum: ', () => { describe('Sum: ', () => { const globalConfig = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -48,7 +51,6 @@ describe('lib/sum: ', () => { }); it('throws an error when global config is not provided.', () => { - const expectedMessage = 'Global config is not provided.'; const config = undefined; const sum = Sum(config!); @@ -65,13 +67,13 @@ describe('lib/sum: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigNotFoundError(expectedMessage)); + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); } }); it('throws an error on missing params in input.', () => { - const expectedMessage = 'cpu/energy is missing from the input array.'; - expect.assertions(1); try { @@ -83,7 +85,9 @@ describe('lib/sum: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(expectedMessage) + new InputValidationError( + '"cpu/energy" parameter is required. Error code: invalid_type.,"network/energy" parameter is required. Error code: invalid_type.,"memory/energy" parameter is required. Error code: invalid_type.' + ) ); } }); diff --git a/src/__tests__/unit/builtins/time-sync.test.ts b/src/__tests__/unit/builtins/time-sync.test.ts index 4839ad6ca..6dd984659 100644 --- a/src/__tests__/unit/builtins/time-sync.test.ts +++ b/src/__tests__/unit/builtins/time-sync.test.ts @@ -1,11 +1,25 @@ -import {TimeSync} from '../../../builtins/time-sync'; -import {ERRORS} from '../../../util/errors'; +import {ERRORS} from '@grnsft/if-core/utils'; import {Settings, DateTime} from 'luxon'; + +import {TimeSync} from '../../../builtins/time-sync'; + import {STRINGS} from '../../../config'; -Settings.defaultZone = 'utc'; -const {InputValidationError} = ERRORS; -const {INVALID_OBSERVATION_OVERLAP, INVALID_TIME_NORMALIZATION} = STRINGS; +Settings.defaultZone = 'utc'; +const { + InputValidationError, + InvalidPaddingError, + InvalidDateInInputError, + InvalidInputError, + GlobalConfigError, +} = ERRORS; + +const { + INVALID_OBSERVATION_OVERLAP, + INVALID_TIME_NORMALIZATION, + AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, +} = STRINGS; jest.mock('luxon', () => { const originalModule = jest.requireActual('luxon'); @@ -196,7 +210,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_TIME_NORMALIZATION) + new GlobalConfigError(INVALID_TIME_NORMALIZATION) ); } }); @@ -228,7 +242,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_OBSERVATION_OVERLAP) + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) ); } }); @@ -258,7 +272,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError(INVALID_OBSERVATION_OVERLAP) + new InvalidInputError(INVALID_OBSERVATION_OVERLAP) ); } }); @@ -335,22 +349,23 @@ describe('execute(): ', () => { 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([ - { - timestamp: 45, - duration: 10, - 'cpu/utilization': 10, - }, - ]); + await timeModel.execute(data); } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); + expect(error).toBeInstanceOf(InvalidDateInInputError); expect(error).toStrictEqual( - new InputValidationError('Unexpected date datatype: number: 45') + new InvalidDateInInputError(INVALID_DATE_TYPE(data[0].timestamp)) ); } }); @@ -675,7 +690,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError('Avoiding padding at start') + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, false)) ); } }); @@ -735,7 +750,7 @@ describe('execute(): ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError('Avoiding padding at start and end') + new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(true, true)) ); } }); diff --git a/src/__tests__/unit/config/strings.test.ts b/src/__tests__/unit/config/strings.test.ts deleted file mode 100644 index bdc1f871f..000000000 --- a/src/__tests__/unit/config/strings.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import {STRINGS} from '../../../config/strings'; - -const { - NOT_NATIVE_PLUGIN, - INVALID_MODULE_PATH, - INVALID_AGGREGATION_METHOD, - METRIC_MISSING, - AVOIDING_PADDING, - AVOIDING_PADDING_BY_EDGES, - INVALID_GROUP_BY, - REJECTING_OVERRIDE, - INVALID_EXHAUST_PLUGIN, - UNKNOWN_PARAM, - NOT_INITALIZED_PLUGIN, -} = STRINGS; - -describe('config/strings: ', () => { - describe('NOT_NATIVE_PLUGIN(): ', () => { - it('successfully injects path into message.', () => { - const path = 'mock/path'; - const expectedMessage = ` -You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`; - - expect(NOT_NATIVE_PLUGIN(path)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_MODULE_PATH(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Provided module: '${param}' is invalid or not found.`; - - expect(INVALID_MODULE_PATH(param)).toEqual(expectedMessage); - }); - }); - - describe('AVOIDING_PADDING(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Avoiding padding at ${param}`; - - expect(AVOIDING_PADDING(param)).toEqual(expectedMessage); - }); - }); - - describe('AVOIDING_PADDING_BY_EDGES(): ', () => { - it('successfully appends given start and end params.', () => { - const start = true; - const end = true; - - const expectedMessage = 'Avoiding padding at start and end'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - - it('successfully appends given start param.', () => { - const start = true; - const end = false; - - const expectedMessage = 'Avoiding padding at start'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - - it('successfully appends given end param.', () => { - const start = false; - const end = true; - - const expectedMessage = 'Avoiding padding at end'; - - expect(AVOIDING_PADDING_BY_EDGES(start, end)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_AGGREGATION_METHOD(): ', () => { - it('successfully appends given param to message.', () => { - const param = 'mock-param'; - - const expectedMessage = `Aggregation is not possible for given ${param} since method is 'none'.`; - - expect(INVALID_AGGREGATION_METHOD(param)).toEqual(expectedMessage); - }); - }); - - describe('METRIC_MISSING(): ', () => { - it('successfully appends given param to message.', () => { - const metric = 'mock-metric'; - const index = 0; - - const expectedMessage = `Aggregation metric ${metric} is not found in inputs[${index}].`; - - expect(METRIC_MISSING(metric, index)).toEqual(expectedMessage); - }); - }); - - describe('INVALID_GROUP_BY(): ', () => { - it('injects type in given message.', () => { - const type = 'mock-type'; - const message = `Invalid group ${type}.`; - - expect(INVALID_GROUP_BY(type)).toEqual(message); - }); - }); - - describe('REJECTING_OVERRIDE(): ', () => { - it('inejcts param name into message.', () => { - const param: any = { - name: 'mock-name', - description: 'mock-description', - aggregation: 'sum', - unit: 'mock-unit', - }; - - expect(REJECTING_OVERRIDE(param)); - }); - }); - - describe('INVALID_EXHAUST_PLUGIN(): ', () => { - it('injects plugin name into message.', () => { - const pluginName = 'mock-plugin'; - const message = `Invalid exhaust plugin: ${pluginName}.`; - - expect(INVALID_EXHAUST_PLUGIN(pluginName)).toEqual(message); - }); - }); - - describe('AVOIDING_PADDING(): ', () => { - it('successfully appends given param to message.', () => { - const description_suffix = 'pad description'; - - const expectedMessage = `Avoiding padding at ${description_suffix}`; - - expect(AVOIDING_PADDING(description_suffix)).toEqual(expectedMessage); - }); - }); - - describe('UNKNOWN_PARAM(): ', () => { - it('injects name into message.', () => { - const name = 'mock-name'; - const message = `Unknown parameter: ${name}. Using 'sum' aggregation method.`; - - expect(UNKNOWN_PARAM(name)).toEqual(message); - }); - }); - - describe('NOT_INITALIZED_PLUGIN(): ', () => { - it('injects name into message.', () => { - const name = 'mock-name'; - const message = `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`; - - expect(NOT_INITALIZED_PLUGIN(name)).toEqual(message); - }); - }); - - describe('AVOIDING_PADDING_BY_EDGES(): ', () => { - it('successfully combines boolean params into a description.', () => { - let description_suffix = 'start and end'; - let expectedMessage = `Avoiding padding at ${description_suffix}`; - - expect(AVOIDING_PADDING_BY_EDGES(true, true)).toEqual(expectedMessage); - description_suffix = 'start'; - expectedMessage = `Avoiding padding at ${description_suffix}`; - expect(AVOIDING_PADDING_BY_EDGES(true, false)).toEqual(expectedMessage); - description_suffix = 'end'; - expectedMessage = `Avoiding padding at ${description_suffix}`; - expect(AVOIDING_PADDING_BY_EDGES(false, true)).toEqual(expectedMessage); - }); - }); -}); diff --git a/src/__tests__/unit/lib/exhaust.test.ts b/src/__tests__/unit/lib/exhaust.test.ts index 97db0b9dc..49db14370 100644 --- a/src/__tests__/unit/lib/exhaust.test.ts +++ b/src/__tests__/unit/lib/exhaust.test.ts @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ jest.mock('fs', () => require('../../../__mocks__/fs')); -import {exhaust} from '../../../lib/exhaust'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {exhaust} from '../../../lib/exhaust'; import {STRINGS} from '../../../config'; -const {ExhaustError} = ERRORS; -const {INVALID_EXHAUST_PLUGIN} = STRINGS; +const {ExhaustOutputArgError, InvalidExhaustPluginError} = ERRORS; +const {INVALID_EXHAUST_PLUGIN, OUTPUT_REQUIRED} = STRINGS; describe('lib/exhaust: ', () => { describe('exhaust(): ', () => { @@ -50,7 +50,6 @@ describe('lib/exhaust: ', () => { outputs: ['yaml'], }, }; - const expectedMessage = 'Output path is required.'; expect.assertions(2); @@ -58,10 +57,10 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {}); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); + expect(error).toBeInstanceOf(ExhaustOutputArgError); - if (error instanceof ExhaustError) { - expect(error.message).toEqual(expectedMessage); + if (error instanceof ExhaustOutputArgError) { + expect(error.message).toEqual(OUTPUT_REQUIRED); } } }); @@ -73,9 +72,6 @@ describe('lib/exhaust: ', () => { outputs: ['mock'], }, }; - const expectedMessage = INVALID_EXHAUST_PLUGIN( - context.initialize.outputs[0] - ); expect.assertions(2); @@ -83,10 +79,12 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {}); } catch (error) { - expect(error).toBeInstanceOf(ExhaustError); + expect(error).toBeInstanceOf(InvalidExhaustPluginError); - if (error instanceof ExhaustError) { - expect(error.message).toEqual(expectedMessage); + if (error instanceof InvalidExhaustPluginError) { + expect(error.message).toEqual( + INVALID_EXHAUST_PLUGIN(context.initialize.outputs[0]) + ); } } }); diff --git a/src/__tests__/unit/lib/initialize.test.ts b/src/__tests__/unit/lib/initialize.test.ts index ad5541684..ff3c10c45 100644 --- a/src/__tests__/unit/lib/initialize.test.ts +++ b/src/__tests__/unit/lib/initialize.test.ts @@ -10,15 +10,19 @@ jest.mock('../../../util/log-memoize', () => ({ memoizedLog: mockLog, })); -import {initialize} from '../../../lib/initialize'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../../../util/errors'; +import {initialize} from '../../../lib/initialize'; import {STRINGS} from '../../../config'; import {GlobalPlugins} from '../../../types/manifest'; -const {PluginCredentialError, ModuleInitializationError} = ERRORS; +const { + MissingPluginPathError, + MissingPluginMethodError, + PluginInitializationError, +} = ERRORS; const {MISSING_METHOD, MISSING_PATH, INVALID_MODULE_PATH} = STRINGS; describe('lib/initalize: ', () => { @@ -81,9 +85,9 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); } catch (error) { - expect(error).toBeInstanceOf(PluginCredentialError); + expect(error).toBeInstanceOf(MissingPluginPathError); - if (error instanceof PluginCredentialError) { + if (error instanceof MissingPluginPathError) { expect(error.message).toEqual(MISSING_PATH); } } @@ -103,9 +107,9 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); } catch (error) { - expect(error).toBeInstanceOf(PluginCredentialError); + expect(error).toBeInstanceOf(MissingPluginMethodError); - if (error instanceof PluginCredentialError) { + if (error instanceof MissingPluginMethodError) { expect(error.message).toEqual(MISSING_METHOD); } } @@ -160,14 +164,16 @@ describe('lib/initalize: ', () => { try { await initialize(plugins); - } catch (error) { - expect(error).toBeInstanceOf(ModuleInitializationError); - - if (error instanceof ModuleInitializationError) { - expect(error.message).toEqual( - INVALID_MODULE_PATH(plugins.mockavizta.path) - ); - } + } catch (error: any) { + expect(error).toBeInstanceOf(PluginInitializationError); + expect(error.message).toEqual( + INVALID_MODULE_PATH( + plugins.mockavizta.path, + new Error( + "Cannot find module 'failing-mock' from 'src/lib/initialize.ts'" + ) + ) + ); } }); }); diff --git a/src/__tests__/unit/lib/load.test.ts b/src/__tests__/unit/lib/load.test.ts index f9ad3e73b..ba3bca902 100644 --- a/src/__tests__/unit/lib/load.test.ts +++ b/src/__tests__/unit/lib/load.test.ts @@ -38,13 +38,15 @@ jest.mock('../../../util/yaml', () => ({ }, })); +import {PluginParams} from '@grnsft/if-core/types'; + import {load, loadIfDiffFiles} from '../../../lib/load'; -import {PARAMETERS} from '../../../config'; +import {PARAMETERS, STRINGS} from '../../../config'; -import {PluginParams} from '../../../types/interface'; +import {parseManifestFromStdin} from '../../../util/helpers'; -import {STRINGS} from '../../../config'; +import {LoadDiffParams} from '../../../types/util/args'; const {INVALID_SOURCE} = STRINGS; @@ -109,8 +111,10 @@ describe('lib/load: ', () => { it('successfully loads target, and source from stdin.', async () => { process.env.readline = 'valid-source'; - const params = { + const piped = await parseManifestFromStdin(); + const params: LoadDiffParams = { targetPath: 'target-path.yml', + pipedSourceManifest: piped, }; const response = await loadIfDiffFiles(params); diff --git a/src/__tests__/unit/lib/manifest/basic.ts b/src/__tests__/unit/lib/manifest/basic.ts deleted file mode 100644 index e5da7c642..000000000 --- a/src/__tests__/unit/lib/manifest/basic.ts +++ /dev/null @@ -1,48 +0,0 @@ -import {Manifest} from '../../../../types/manifest'; - -export const manifest: Manifest = { - name: 'gsf-demo', - description: 'Hello', - tags: { - kind: 'web', - complexity: 'moderate', - category: 'cloud', - }, - initialize: { - plugins: { - 'mock-name': { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'front-end': { - pipeline: ['mock-name'], - config: { - 'mock-name': { - 'core-units': 24, - processor: 'Intel® Core™ i7-1185G7', - }, - }, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 3600, - 'cpu/utilization': 18.392, - }, - { - timestamp: '2023-08-06T00:00', - duration: 3600, - 'cpu/utilization': 16, - }, - ], - }, - }, - }, -}; diff --git a/src/__tests__/unit/lib/manifest/nested.ts b/src/__tests__/unit/lib/manifest/nested.ts deleted file mode 100644 index 0c27fad12..000000000 --- a/src/__tests__/unit/lib/manifest/nested.ts +++ /dev/null @@ -1,146 +0,0 @@ -import {Manifest} from '../../../../types/manifest'; - -export const manifestNested: Manifest = { - name: 'nesting-demo', - description: null, - tags: { - kind: 'web', - complexity: 'moderate', - category: 'on-premise', - }, - initialize: { - plugins: { - mockavizta: { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'child-0': { - config: { - mockavizta: { - allocation: 'LINEAR', - verbose: true, - }, - }, - pipeline: ['mockavizta'], - children: { - 'child-0-1': { - children: { - 'child-0-1-1': { - pipeline: ['mockavizta'], - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - 'child-0-1-2': { - children: { - 'child-1-2-1': { - pipeline: ['mockavizta'], - config: { - mockavizta: { - allocation: 'mock-allocation', - verbose: false, - }, - }, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - }, - }, - }, - }, - }, - }, - }, - }, -}; - -export const manifestNestedNoConfig: Manifest = { - name: 'nesting-demo', - description: null, - tags: { - kind: 'web', - complexity: 'moderate', - category: 'on-premise', - }, - initialize: { - plugins: { - mockavizta: { - model: 'MockaviztaModel', - path: 'mock-path', - 'global-config': { - allocation: 'LINEAR', - verbose: true, - }, - }, - }, - }, - tree: { - children: { - 'child-0': { - config: { - mockavizta: { - allocation: 'LINEAR', - verbose: true, - }, - }, - pipeline: ['mockavizta'], - children: { - 'child-0-1': { - children: { - 'child-0-1-1': { - pipeline: ['mockavizta'], - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - 'child-0-1-2': { - children: { - 'child-1-2-1': { - pipeline: ['mockavizta'], - config: {}, - inputs: [ - { - timestamp: '2023-07-06T00:00', - duration: 10, - 'cpu/utilization': 50, - 'energy-network': 0.000811, - carbon: 10, - }, - ], - }, - }, - }, - }, - }, - }, - }, - }, - }, -}; diff --git a/src/__tests__/unit/util/aggregation-helper.test.ts b/src/__tests__/unit/util/aggregation-helper.test.ts index 20690bc2f..1a23bc3c1 100644 --- a/src/__tests__/unit/util/aggregation-helper.test.ts +++ b/src/__tests__/unit/util/aggregation-helper.test.ts @@ -1,11 +1,11 @@ +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + import {aggregateInputsIntoOne} from '../../../util/aggregation-helper'; -import {ERRORS} from '../../../util/errors'; import {STRINGS} from '../../../config'; -import {PluginParams} from '../../../types/interface'; - -const {InvalidAggregationParamsError} = ERRORS; +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; describe('util/aggregation-helper: ', () => { @@ -20,9 +20,9 @@ describe('util/aggregation-helper: ', () => { try { aggregateInputsIntoOne(inputs, metrics, isTemporal); } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationParamsError); + expect(error).toBeInstanceOf(InvalidAggregationMethodError); - if (error instanceof InvalidAggregationParamsError) { + if (error instanceof InvalidAggregationMethodError) { expect(error.message).toEqual(INVALID_AGGREGATION_METHOD(metrics[0])); } } @@ -38,9 +38,9 @@ describe('util/aggregation-helper: ', () => { try { aggregateInputsIntoOne(inputs, metrics, isTemporal); } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationParamsError); + expect(error).toBeInstanceOf(MissingAggregationParamError); - if (error instanceof InvalidAggregationParamsError) { + if (error instanceof MissingAggregationParamError) { expect(error.message).toEqual(METRIC_MISSING(metrics[0], 0)); } } diff --git a/src/__tests__/unit/util/args.test.ts b/src/__tests__/unit/util/args.test.ts index d40d36cae..f4238cbce 100644 --- a/src/__tests__/unit/util/args.test.ts +++ b/src/__tests__/unit/util/args.test.ts @@ -1,5 +1,20 @@ const processRunningPath = process.cwd(); +jest.mock('../../../util/fs', () => ({ + isFileExists: () => { + if (process.env.fileExists === 'true') { + return true; + } + return false; + }, + isDirectoryExists: () => { + if (process.env.directoryExists === 'true') { + return true; + } + return false; + }, +})); + jest.mock('ts-command-line-args', () => ({ __esModule: true, parse: () => { @@ -60,6 +75,27 @@ jest.mock('ts-command-line-args', () => ({ throw new Error('mock-error'); case 'diff-throw': throw 'mock-error'; + /** If-env mocks */ + case 'manifest-install-provided': + return { + install: true, + manifest: 'mock-manifest.yaml', + }; + case 'manifest-is-not-yaml': + return {manifest: 'manifest'}; + case 'manifest-path-invalid': + throw new Error(MANIFEST_NOT_FOUND); + case 'env-throw-error': + throw new Error('mock-error'); + case 'env-throw': + throw 'mock-error'; + /** If-check */ + case 'manifest-is-provided': + return {manifest: 'mock-manifest.yaml'}; + case 'directory-is-provided': + return {directory: '/mock-directory'}; + case 'flags-are-not-provided': + return {manifest: undefined, directory: undefined}; default: return { manifest: 'mock-manifest.yaml', @@ -69,21 +105,33 @@ jest.mock('ts-command-line-args', () => ({ }, })); -import path = require('path'); +import * as path from 'node:path'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {parseIEProcessArgs, parseIfDiffArgs} from '../../../util/args'; -import {ERRORS} from '../../../util/errors'; +import { + parseIEProcessArgs, + parseIfCheckArgs, + parseIfDiffArgs, + parseIfEnvArgs, +} from '../../../util/args'; import {STRINGS} from '../../../config'; -const {CliInputError} = ERRORS; +const { + CliSourceFileError, + ParseCliParamsError, + InvalidDirectoryError, + MissingCliFlagsError, +} = ERRORS; const { MANIFEST_IS_MISSING, - FILE_IS_NOT_YAML, TARGET_IS_NOT_YAML, INVALID_TARGET, SOURCE_IS_NOT_YAML, + MANIFEST_NOT_FOUND, + DIRECTORY_NOT_FOUND, + IF_CHECK_FLAGS_MISSING, } = STRINGS; describe('util/args: ', () => { @@ -106,8 +154,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(MANIFEST_IS_MISSING)); + expect(error).toBeInstanceOf(ParseCliParamsError); + expect(error).toEqual(new ParseCliParamsError(MANIFEST_IS_MISSING)); } process.env.result = 'manifest-is-missing'; @@ -115,8 +163,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(MANIFEST_IS_MISSING)); + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(MANIFEST_IS_MISSING)); } }); @@ -195,8 +243,8 @@ describe('util/args: ', () => { try { parseIEProcessArgs(); } catch (error) { - expect(error).toBeInstanceOf(CliInputError); - expect(error).toEqual(new CliInputError(FILE_IS_NOT_YAML)); + expect(error).toBeInstanceOf(CliSourceFileError); + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); } }); @@ -226,7 +274,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(INVALID_TARGET)); + expect(error).toEqual(new ParseCliParamsError(INVALID_TARGET)); } } }); @@ -239,7 +287,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(TARGET_IS_NOT_YAML)); + expect(error).toEqual(new ParseCliParamsError(TARGET_IS_NOT_YAML)); } } }); @@ -260,7 +308,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError(SOURCE_IS_NOT_YAML)); + expect(error).toEqual(new ParseCliParamsError(SOURCE_IS_NOT_YAML)); } } }); @@ -282,7 +330,7 @@ describe('util/args: ', () => { parseIfDiffArgs(); } catch (error) { if (error instanceof Error) { - expect(error).toEqual(new CliInputError('mock-error')); + expect(error).toEqual(new ParseCliParamsError('mock-error')); } } }); @@ -299,5 +347,176 @@ describe('util/args: ', () => { }); }); + describe('parseIfEnvArgs(): ', () => { + it('executes if `manifest` is missing.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-missing'; + const response = await parseIfEnvArgs(); + + expect.assertions(1); + + expect(response).toEqual({install: undefined}); + }); + + it('executes if `manifest` and `install` are provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-install-provided'; + + const response = await parseIfEnvArgs(); + + expect.assertions(2); + expect(response).toHaveProperty('install'); + expect(response).toHaveProperty('manifest'); + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfEnvArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + + describe('parseIfCheckArgs(): ', () => { + it('executes when `manifest` is provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-provided'; + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({manifest: 'mock-manifest.yaml'}); + }); + + it('executes when the `directory` is provided.', async () => { + process.env.directoryExists = 'true'; + process.env.result = 'directory-is-provided'; + + const response = await parseIfCheckArgs(); + + expect.assertions(1); + + expect(response).toEqual({directory: '/mock-directory'}); + }); + + it('throws an error when the `directory` does not exist.', async () => { + process.env.directoryExists = 'false'; + process.env.result = 'directory-is-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new InvalidDirectoryError(DIRECTORY_NOT_FOUND)); + } + }); + + it('throws an error when both `manifest` and `directory` flags are not provided.', async () => { + process.env.result = 'flags-are-not-provided'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual(new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING)); + } + }); + + it('throws an error if `manifest` is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new CliSourceFileError(SOURCE_IS_NOT_YAML)); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError(MANIFEST_NOT_FOUND)); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfCheckArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + process.env = originalEnv; }); diff --git a/src/__tests__/unit/util/errors.test.ts b/src/__tests__/unit/util/errors.test.ts deleted file mode 100644 index 47e3e9e9a..000000000 --- a/src/__tests__/unit/util/errors.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {ERRORS} from '../../../util/errors'; - -describe('util/errors: ', () => { - describe('ERRORS: ', () => { - it('checks for properties.', () => { - const errors = Object.values(ERRORS); - - errors.forEach(error => { - expect(error).toBeInstanceOf(Function); - }); - }); - }); -}); diff --git a/src/__tests__/unit/util/fs.test.ts b/src/__tests__/unit/util/fs.test.ts new file mode 100644 index 000000000..77b3c0370 --- /dev/null +++ b/src/__tests__/unit/util/fs.test.ts @@ -0,0 +1,144 @@ +import * as fs from 'fs/promises'; + +import { + getFileName, + isDirectoryExists, + isFileExists, + getYamlFiles, + removeFileIfExists, +} from '../../../util/fs'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +describe('util/fs: ', () => { + describe('isFileExists(): ', () => { + it('returns true if the file exists.', async () => { + const result = await isFileExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns fale if the file does not exist.', async () => { + const result = await isFileExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('isDirectoryExists(): ', () => { + it('returns true if directory exists.', async () => { + const result = await isDirectoryExists('true'); + + expect.assertions(1); + expect(result).toEqual(true); + }); + + it('returns false if directory does not exist.', async () => { + const result = await isDirectoryExists('false'); + + expect.assertions(1); + expect(result).toEqual(false); + }); + }); + + describe('getFileName(): ', () => { + it('returns the file name without extension for a file with an extension.', () => { + const filePath = '/path/to/file/example.yaml'; + const result = getFileName(filePath); + + expect.assertions(1); + expect(result).toBe('example'); + }); + + it('returns the file name without extension for a file with multiple dots.', () => { + const filePath = '/path/to/file/example.test.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example.test'); + }); + + it('returns the file name as is if there is no extension.', () => { + const filePath = '/path/to/file/example'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles file names with special characters.', () => { + const filePath = + '/path/to/file/complex-file.name.with-multiple.parts.yaml'; + const result = getFileName(filePath); + expect(result).toBe('complex-file.name.with-multiple.parts'); + }); + + it('handles file names with no path.', () => { + const filePath = 'example.yaml'; + const result = getFileName(filePath); + expect(result).toBe('example'); + }); + + it('handles empty string as file path.', () => { + const filePath = ''; + const result = getFileName(filePath); + expect(result).toBe(''); + }); + }); + + describe('getYamlFiles(): ', () => { + it('returns an empty array if the directory is empty.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + const result = await getYamlFiles('/mock-empty-directory'); + + expect(result).toEqual([]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-empty-directory'); + }); + + it('returns YAML files in the directory', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + + const result = await getYamlFiles('/mock-directory'); + expect.assertions(2); + expect(result).toEqual([ + '/mock-directory/file1.yaml', + '/mock-directory/file2.yml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + + it('recursively finds YAML files in nested directories.', async () => { + const fsReaddirSpy = jest.spyOn(fs, 'readdir'); + jest + .spyOn(fs, 'lstat') + .mockResolvedValue({isDirectory: () => false} as any); + const result = await getYamlFiles('/mock-sub-directory'); + + expect.assertions(2); + expect(result).toEqual([ + '/mock-sub-directory/subdir/file2.yml', + '/mock-sub-directory/file1.yaml', + ]); + expect(fsReaddirSpy).toHaveBeenCalledWith('/mock-directory'); + }); + }); + + describe('removeFileIfExists(): ', () => { + it('successfully delete file if exists.', async () => { + await isFileExists('true'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + + it('does not throw an error if the file not exists.', async () => { + await isFileExists('false'); + const result = await removeFileIfExists('mock-path'); + + expect.assertions(1); + expect(result).toEqual(undefined); + }); + }); +}); diff --git a/src/__tests__/unit/util/helpers.test.ts b/src/__tests__/unit/util/helpers.test.ts index d627790e4..ed46dc0d9 100644 --- a/src/__tests__/unit/util/helpers.test.ts +++ b/src/__tests__/unit/util/helpers.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -10,6 +11,131 @@ jest.mock('../../../util/logger', () => ({ error: mockError, }, })); + +jest.mock('path', () => { + const actualPath = jest.requireActual('path') as Record; + return { + __esModule: true, + ...actualPath, + dirname: jest.fn(() => './mock-path'), + }; +}); + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +jest.mock('../../../lib/load', () => ({ + load: jest.fn(() => { + if (process.env.manifest === 'true') { + return { + rawManifest: { + name: 'divide', + initialize: { + plugins: { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + 'global-config': { + numerator: 'vcpus-allocated', + denominator: 2, + output: 'cpu/number-cores', + }, + }, + }, + }, + execution: { + environment: { + dependencies: [ + '@grnsft/if-core@0.0.7', + '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models', + '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', + ], + }, + }, + }, + }; + } + return { + rawManifest: { + initialize: { + plugins: {'@grnsft/if-plugins': '1.0.0'}, + }, + execution: { + environment: { + dependencies: [], + }, + }, + }, + }; + }), +})); + +const initPackage = jest.fn(() => Promise.resolve('mock-path')); +const updatePackage = jest.fn(() => Promise.resolve(true)); +const installdeps = jest.fn(); +const updatedeps = jest.fn(); +jest.mock('../../../util/npm', () => { + const actualNPMUtil = jest.requireActual('../../../util/npm'); + + return { + ...actualNPMUtil, + initPackageJsonIfNotExists: (folderPath: string) => { + if (process.env.NPM_MOCK === 'true') { + return initPackage(); + } + + if (process.env.NPM_MOCK === 'error') { + throw new Error('mock-error'); + } + + return actualNPMUtil.initPackageJsonIfNotExists(folderPath); + }, + updatePackageJsonProperties: ( + newPackageJsonPath: string, + appendDependencies: boolean + ) => { + if (process.env.NPM_MOCK === 'true') { + return updatePackage(); + } + + return actualNPMUtil.updatePackageJsonProperties( + newPackageJsonPath, + appendDependencies + ); + }, + installDependencies: ( + folderPath: string, + dependencies: {[path: string]: string} + ) => { + if (process.env.NPM_MOCK === 'true') { + return installdeps(); + } + + return actualNPMUtil.installDependencies(folderPath, dependencies); + }, + updatePackageJsonDependencies: ( + packageJsonPath: string, + dependencies: any, + cwd: boolean + ) => { + if (process.env.NPM_MOCK === 'true') { + return updatedeps(); + } + + return actualNPMUtil.updatePackageJsonDependencies( + packageJsonPath, + dependencies, + cwd + ); + }, + }; +}); + +import {ERRORS} from '@grnsft/if-core/utils'; + import { andHandle, checkIfEqual, @@ -17,10 +143,17 @@ import { mergeObjects, oneIsPrimitive, parseManifestFromStdin, + getOptionsFromArgs, + addTemplateManifest, + initializeAndInstallLibs, + logStdoutFailMessage, } from '../../../util/helpers'; -import {ERRORS} from '../../../util/errors'; +import {CONFIG} from '../../../config'; import {Difference} from '../../../types/lib/compare'; +const {IF_ENV} = CONFIG; +const {FAILURE_MESSAGE_DEPENDENCIES, FAILURE_MESSAGE} = IF_ENV; + const {WriteFileError} = ERRORS; describe('util/helpers: ', () => { @@ -30,15 +163,6 @@ describe('util/helpers: ', () => { mockError.mockReset(); }); - it('logs error and warn in case of error is unknown.', () => { - const message = 'mock-message'; - const MockError = class extends Error {}; - - andHandle(new MockError(message)); - expect(mockWarn).toHaveBeenCalledTimes(1); - expect(mockError).toHaveBeenCalledTimes(1); - }); - it('logs error in case of error is unknown.', () => { const message = 'mock-message'; @@ -47,9 +171,7 @@ describe('util/helpers: ', () => { expect(mockError).toHaveBeenCalledTimes(1); }); }); -}); -describe('util/helpers: ', () => { describe('mergeObjects(): ', () => { it('does not override input.', () => { expect.assertions(1); @@ -364,16 +486,11 @@ describe('util/helpers: ', () => { it('throws error if there is no manifest in stdin.', async () => { process.env.readline = 'no_manifest'; - const expectedMessage = 'Manifest not found in STDIN.'; expect.assertions(1); - try { - await parseManifestFromStdin(); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual(expectedMessage); - } - } + const response = await parseManifestFromStdin(); + + expect(response).toEqual(''); }); it('returns empty string if there is no data in stdin.', async () => { @@ -413,4 +530,158 @@ description: mock-description expect(response).toBeFalsy(); }); }); + + describe('getOptionsFromArgs(): ', () => { + it('returns the correct options when dependencies are present.', async () => { + const commandArgs = { + manifest: '/path/to/mock-manifest.json', + install: false, + }; + + process.env.manifest = 'true'; + + const result = await getOptionsFromArgs(commandArgs); + expect.assertions(1); + + expect(result).toEqual({ + folderPath: './mock-path', + dependencies: { + '@grnsft/if-plugins': '^v0.3.2', + }, + install: false, + }); + }); + + it('throws an error when there are no dependencies.', async () => { + const commandArgs = { + manifest: '/path/to/mock-manifest.json', + install: false, + }; + + process.env.manifest = 'false'; + + expect.assertions(1); + try { + await getOptionsFromArgs(commandArgs); + } catch (error) { + expect(error).toEqual(new Error(FAILURE_MESSAGE_DEPENDENCIES)); + } + }); + }); + + describe('addTemplateManifest(): ', () => { + it('successfully adds the template manifest to the directory.', async () => { + await addTemplateManifest('./'); + + expect.assertions(1); + }); + + it('throws an error when the manifest is not added into the directory.', async () => { + expect.assertions(1); + + try { + await addTemplateManifest(''); + } catch (error) { + const logSpy = jest.spyOn(global.console, 'log'); + expect(logSpy).toEqual(FAILURE_MESSAGE); + } + }); + }); + + describe('initializeAndInstallLibs(): ', () => { + beforeEach(() => { + initPackage.mockReset(); + updatePackage.mockReset(); + installdeps.mockReset(); + updatedeps.mockReset(); + }); + + it('installs dependencies if install flag is truthy.', async () => { + process.env.NPM_MOCK = 'true'; + // @ts-ignore + process.exit = (code: any) => code; + const options = { + folderPath: 'mock-folderPath', + install: true, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(4); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(1); + expect(updatePackage).toHaveBeenCalledTimes(1); + expect(installdeps).toHaveBeenCalledTimes(1); + expect(updatedeps).toHaveBeenCalledTimes(0); + }); + + it('updates dependencies if install flag is falsy.', async () => { + process.env.NPM_MOCK = 'true'; + // @ts-ignore + process.exit = (code: any) => code; + const options = { + folderPath: 'mock-folderPath', + install: false, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(4); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(1); + expect(updatePackage).toHaveBeenCalledTimes(1); + expect(installdeps).toHaveBeenCalledTimes(0); + expect(updatedeps).toHaveBeenCalledTimes(1); + }); + + it('exits process if error is thrown.', async () => { + process.env.NPM_MOCK = 'error'; + const originalProcessExit = process.exit; + const mockExit = jest.fn(); + // @ts-ignore + process.exit = mockExit; + const options = { + folderPath: 'mock-folderPath', + install: false, + cwd: true, + dependencies: { + mock: 'mock-dependencies', + }, + }; + + expect.assertions(5); + await initializeAndInstallLibs(options); + + expect(initPackage).toHaveBeenCalledTimes(0); + expect(updatePackage).toHaveBeenCalledTimes(0); + expect(installdeps).toHaveBeenCalledTimes(0); + expect(updatedeps).toHaveBeenCalledTimes(0); + expect(mockExit).toHaveBeenCalledTimes(1); + + process.exit = originalProcessExit; + }); + }); + + describe('logStdoutFailMessage(): ', () => { + it('successfully logs the failed message.', () => { + const errorMessage = {stdout: '\n\nmock error message'}; + const mockFilename = 'mock-filename.yaml'; + const logSpy = jest.spyOn(global.console, 'log'); + logStdoutFailMessage(errorMessage, mockFilename); + + expect.assertions(2); + + expect(logSpy).toHaveBeenCalledWith( + `✖ if-check could not verify ${mockFilename}. The re-executed file does not match the original.\n` + ); + + expect(logSpy).toHaveBeenCalledWith('mock error message'); + }); + }); }); diff --git a/src/__tests__/unit/util/npm.test.ts b/src/__tests__/unit/util/npm.test.ts new file mode 100644 index 000000000..6d1476b42 --- /dev/null +++ b/src/__tests__/unit/util/npm.test.ts @@ -0,0 +1,265 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +jest.mock('fs/promises', () => require('../../../__mocks__/fs')); + +const mockInfo = jest.fn(); + +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); +jest.mock('../../../util/logger', () => ({ + logger: { + info: mockInfo, + }, +})); + +jest.mock('../../../util/helpers', () => { + const originalModule = jest.requireActual('../../../util/helpers'); + return { + ...originalModule, + execPromise: async (param: any) => { + switch (process.env.NPM_INSTALL) { + case 'true': + expect(param).toEqual('npm install @grnsft/if@0.3.3-beta.0'); + break; + case 'npm init -y': + expect(param).toEqual('npm init -y'); + break; + case 'if-check': + expect(param).toEqual( + "npm run if-env -- -m ./src/__mocks__/mock-manifest.yaml && npm run if-run -- -m ./src/__mocks__/mock-manifest.yaml -o src/__mocks__/re-mock-manifest && node -p 'Boolean(process.stdout.isTTY)' | npm run if-diff -- -s src/__mocks__/re-mock-manifest.yaml -t ./src/__mocks__/mock-manifest.yaml" + ); + break; + } + return; + }, + }; +}); + +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, + executeCommands, +} from '../../../util/npm'; +import {isFileExists} from '../../../util/fs'; + +import {STRINGS} from '../../../config/strings'; +import {ManifestPlugin} from '../../../types/npm'; + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES} = STRINGS; + +describe('util/npm: ', () => { + const folderPath = path.resolve(__dirname, 'npm-test'); + + describe('initPackageJsonIfNotExists(): ', () => { + it('initializes package.json if it does not exist.', async () => { + process.env.NPM_INSTALL = 'npm init -y'; + isFileExists('true'); + + await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INITIALIZING_PACKAGE_JSON); + }); + + it('returns the package.json path if it exists.', async () => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + isFileExists('false'); + + const result = await initPackageJsonIfNotExists(folderPath); + + expect.assertions(2); + expect(result).toBe(packageJsonPath); + }); + }); + + describe('installDependencies(): ', () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + it('calls execPromise with the correct arguments.', async () => { + process.env.NPM_INSTALL = 'true'; + expect.assertions(1); + + await installDependencies(folderPath, dependencies); + }); + + it('logs the installation message.', async () => { + const dependencies = { + '@grnsft/if': '^0.3.3-beta.0', + }; + + await installDependencies(folderPath, dependencies); + + expect.assertions(2); + expect(mockInfo).toHaveBeenCalledWith(INSTALLING_NPM_PACKAGES); + }); + }); + + describe('updatePackageJsonDependencies(): ', () => { + it('successfully updates the package.json dependencies when cwd is false.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, false); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + + it('successfully updates the package.json dependencies when cwd is true.', async () => { + const dependencies = { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }; + const packageJsonPath = path.join(folderPath, 'package.json-npm'); + + const expectedPackageJsonContent = JSON.stringify( + { + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonDependencies(packageJsonPath, dependencies, true); + + expect.assertions(2); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + }); + + describe('extractPathsWithVersion(): ', () => { + it('extracts paths with correct versions.', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + '@commitlint/cli@18.6.0', + '@commitlint/config-conventional@18.6.0', + '@grnsft/if-core@0.0.7', + '@grnsft/if-plugins@v0.3.2', + '@grnsft/if-unofficial-plugins@v0.3.0 extraneous -> file:../../../if-unofficial-models', + '@jest/globals@29.7.0', + ]; + + const result = extractPathsWithVersion(plugins, dependencies); + + expect.assertions(1); + expect(result).toEqual({ + '@grnsft/if-plugins': '^v0.3.2', + '@grnsft/if-unofficial-plugins': '^v0.3.0', + }); + }); + + it('returns an empty object if no matches found', () => { + const plugins: ManifestPlugin = { + 'cloud-metadata': { + path: '@grnsft/if-plugins', + method: 'CloudMetadata', + }, + divide: { + path: 'builtin', + method: 'Divide', + }, + 'boavizta-cpu': { + path: '@grnsft/if-unofficial-plugins', + method: 'BoaviztaCpuOutput', + }, + }; + const dependencies = [ + '@babel/core@7.22.10', + '@babel/preset-typescript@7.23.3', + ]; + + expect.assertions(1); + const result = extractPathsWithVersion(plugins, dependencies); + expect(result).toEqual({}); + }); + }); + + describe('updatePackageJsonProperties(): ', () => { + it('updates the package.json properties correctly.', async () => { + const packageJsonPath = path.join(folderPath, 'package.json-npm1'); + + const expectedPackageJsonContent = JSON.stringify( + { + name: 'if-environment', + description: 'mock-description', + author: {}, + bugs: {}, + engines: {}, + homepage: 'mock-homepage', + dependencies: { + '@grnsft/if-plugins': '^0.3.3-beta.0', + }, + }, + null, + 2 + ); + + const fsReadSpy = jest + .spyOn(fs, 'readFile') + .mockResolvedValue(expectedPackageJsonContent); + await updatePackageJsonProperties(packageJsonPath, true); + + expect.assertions(8); + + expect(fsReadSpy).toHaveBeenCalledWith(packageJsonPath, 'utf8'); + }); + }); + + describe('executeCommands(): ', () => { + it('successfully executes with correct commands.', async () => { + process.env.NPM_INSTALL = 'if-check'; + const manifest = './src/__mocks__/mock-manifest.yaml'; + const logSpy = jest.spyOn(global.console, 'log'); + + await executeCommands(manifest, false); + + expect.assertions(2); + expect(logSpy).toHaveBeenCalledWith( + '✔ if-check successfully verified mock-manifest.yaml\n' + ); + }); + }); +}); diff --git a/src/__tests__/unit/util/plugin-storage.test.ts b/src/__tests__/unit/util/plugin-storage.test.ts index b2bd25011..8b76f36cd 100644 --- a/src/__tests__/unit/util/plugin-storage.test.ts +++ b/src/__tests__/unit/util/plugin-storage.test.ts @@ -1,7 +1,8 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {pluginStorage} from '../../../util/plugin-storage'; -import {ERRORS} from '../../../util/errors'; -const {PluginInitalizationError} = ERRORS; +const {PluginInitializationError} = ERRORS; describe('util/pluginStorage: ', () => { describe('pluginStorage(): ', () => { @@ -30,9 +31,9 @@ describe('util/pluginStorage: ', () => { try { storage.get(pluginName); } catch (error) { - expect(error).toBeInstanceOf(PluginInitalizationError); + expect(error).toBeInstanceOf(PluginInitializationError); - if (error instanceof PluginInitalizationError) { + if (error instanceof PluginInitializationError) { expect(error.message).toEqual; } } diff --git a/src/builtins/README.md b/src/builtins/README.md index b9906921d..c37e143a1 100644 --- a/src/builtins/README.md +++ b/src/builtins/README.md @@ -305,7 +305,7 @@ Then, you must select the metric you want to export to CSV. The name of that met For example, to export the `carbon` data from your tree to a CSV file: ```sh -ie --manifest example.yml --output example#carbon +if-run --manifest example.yml --output example#carbon ``` This will save a CSV file called `example.csv`. The contents will look similar to the following: diff --git a/src/builtins/coefficient/README.md b/src/builtins/coefficient/README.md index 096d20ab5..4579cd5b8 100644 --- a/src/builtins/coefficient/README.md +++ b/src/builtins/coefficient/README.md @@ -86,7 +86,25 @@ tree: You can run this example by saving it as `./examples/manifests/coefficient.yml` and executing the following command from the project root: ```sh -ie --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml +if-run --manifest ./examples/manifests/coefficient.yml --output ./examples/outputs/coefficient.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Coefficient` exposes one of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameter`: this must be a string +- `coefficient`: this must be a number +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/coefficient/index.ts b/src/builtins/coefficient/index.ts index 627e5f64e..2d4f6a1c9 100644 --- a/src/builtins/coefficient/index.ts +++ b/src/builtins/coefficient/index.ts @@ -1,13 +1,17 @@ import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + CoefficientConfig, + ExecutePlugin, + PluginParams, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; -import {CoefficientConfig} from './types'; +import {STRINGS} from '../../config'; -const {ConfigNotFoundError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { const metadata = { @@ -24,6 +28,8 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { const coefficient = safeGlobalConfig['coefficient']; return inputs.map(input => { + validateSingleInput(input, inputParameter); + return { ...input, [outputParameter]: calculateProduct(input, inputParameter, coefficient), @@ -31,6 +37,19 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { }); }; + /** + * Checks for required fields in input. + */ + const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); + + return input; + }; + /** * Calculates the product of the energy components. */ @@ -45,7 +64,7 @@ export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ diff --git a/src/builtins/coefficient/types.ts b/src/builtins/coefficient/types.ts deleted file mode 100644 index 9cbb78b7d..000000000 --- a/src/builtins/coefficient/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type CoefficientConfig = { - 'input-parameter': string; - coefficient: number; - 'output-parameter': string; -}; diff --git a/src/builtins/copy-param/README.md b/src/builtins/copy-param/README.md new file mode 100644 index 000000000..78ab5f656 --- /dev/null +++ b/src/builtins/copy-param/README.md @@ -0,0 +1,104 @@ +# Copy-param + +`copy-param` is a generic plugin that duplicates an existing parameter in the `input` data and assigns it to a new key. You can either keep or delete the original copied parameter. A common use case for this is to rename parameters in the `inputs` array. + +You provide the name of the value you want to copy, and a name to assign the copy to. You also toggle a `keep-existing` parameter to either persist or delete the original copied value. + +For example, you could copy `energy` into `energy-copy`, with `keep-existing=true`. In this case your inputs: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 +``` + +would become + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy: 30 + energy-copy: 30 +``` + +but with `keep-existing=false`, the same inputs would yield: + +```yaml +- timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + energy-copy: 30 +``` + +## Parameters + +### Config + +Three parameters are required in config: `from` and `to` and `keep-existing`. + +`from`: an array of strings. Each string should match an existing key in the `inputs` array +`to`: a string defining the name to use to add the result of summing the input parameters to the output array. +`keep-existing`: toggles whether to keep or delete the copied parameter (defined in `to`) + +### Inputs + +As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. + +## Returns + +The plugin adds a new parameter with the name defined in `to` to the `input` data. + + +## Implementation + +To run the plugin, you must first create an instance of `Copy`. Then, you can call `execute()`. + +```typescript +import { Copy } from "."; + +const plugin = Copy({ 'keep-existing': true, from: 'from-param', to: 'to-param' }); + +const result = plugin.execute([{ + timestamp: "2023-12-12T00:00:13.000Z", + duration: 30, + 'from-param': 'hello', +}]) + +console.log(result) + +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `copy-param`: + +```yaml +name: copy-param +description: +tags: +initialize: + plugins: + copy-param: + path: builtin + method: Copy + global-config: + keep-existing: true + from: original + to: copy +tree: + children: + child-1: + pipeline: + - copy-param + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + original: 'hello' + +``` + +You can run this example by saving it as `./manifests/examples/copy.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./manifests/examples/copy.yml -s +``` + +The results will be displayed in the console. diff --git a/src/builtins/copy-param/index.ts b/src/builtins/copy-param/index.ts new file mode 100644 index 000000000..6301bbf25 --- /dev/null +++ b/src/builtins/copy-param/index.ts @@ -0,0 +1,89 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; + +import {validate} from '../../util/validations'; + +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): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const globalConfigSchema = z.object({ + 'keep-existing': z.boolean(), + from: z.string().min(1), + to: z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + + /** + * Checks for required fields in input. + */ + const validateSingleInput = ( + input: PluginParams, + inputParameters: string[] + ) => { + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.string()); + + validate(validationSchema, inputData); + + return input; + }; + + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const keepExisting = safeGlobalConfig['keep-existing'] === true; + const from = safeGlobalConfig['from']; + const to = safeGlobalConfig['to']; + + return inputs.map(input => { + const safeInput = validateSingleInput(input, [from]); + + const outputValue = safeInput[from]; + if (safeInput[from]) { + if (!keepExisting) { + delete safeInput[from]; + } + } + return { + ...safeInput, // need to return or what you provide won't be outputted, don't be evil! + [to]: outputValue, + }; + }); + }; + + return { + metadata, + execute, + }; +}; diff --git a/src/builtins/csv-lookup/README.md b/src/builtins/csv-lookup/README.md index 2c52969ae..3663f4123 100644 --- a/src/builtins/csv-lookup/README.md +++ b/src/builtins/csv-lookup/README.md @@ -136,7 +136,45 @@ You can run this example by saving it as `./examples/manifests/csv-lookup.yml` a ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup +if-run --manifest manifests/plugins/csv-lookup.yml --output manifests/outputs/csv-lookup ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +Coefficient exposes six of the IF error classes. + +### FetchingFileError + +This error is caused by problems finding the file at the path provided in the `filepath`. If the file is on your local filesystem, you can check that the file is definitely there. For a remote file, check your internet connection. You can check your connection to the server using a tool such as `ping` or `curl`. if you still experience problems, you could retrieve the remote file onto your local filesystem using a tool such as `wget`. + +### ReadFileError, + +This error is caused by problems reading the CSV file provided in the `filepath`. To fix it, check that the file contains valid CSV data. The file should have a `.csv` file extension and the data inside should be formatted correctly. + +### MissingCSVColumnError, + +This error is caused by `CsvLookup` failing to find a column in the CSV file whose name matches what was provided in `query`. To debug, check that you do not have any typos in your `query` and confirm that the requested column name definitely exists in the target file. + +### QueryDataNotFoundError, + +This error is caused by the `CsvLookup` plugin failing to find data that matches your query. Try revising your query parameters. + +### CSVParseError, + +This error arises due to problems parsing CSV data into IF. This can occur when the CSV data is incorrectly formatted or contains unexpected characters that IF does not recognize. These errors are expected to be unusual edge cases as incorrectly formatted data will usually be identified during file loading and cause a `ReadFileError`. To debug, check your CSV file for any unexpected formatting or unusual characters. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `filepath`: This must be a path to a csv file +- `query`: this must be an array of key-value pairs where the key is a string containing a column name an the value is a string containing the name of a value in `inputs` +- `output`: this must be a string containing a name or a wildcard character (`"*"`) + +You can fix this error by checking you are providing valid values for each parameter in the config. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/csv-lookup/index.ts b/src/builtins/csv-lookup/index.ts index 2539a14cf..8243a6391 100644 --- a/src/builtins/csv-lookup/index.ts +++ b/src/builtins/csv-lookup/index.ts @@ -4,13 +4,29 @@ import {readFile} from 'fs/promises'; import axios from 'axios'; import {z} from 'zod'; import {parse} from 'csv-parse/sync'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; -const {ConfigNotFoundError, FileNotFoundError, InputValidationError} = ERRORS; +import {STRINGS} from '../../config'; + +const { + FILE_FETCH_FAILED, + FILE_READ_FAILED, + MISSING_CSV_COLUMN, + NO_QUERY_DATA, + MISSING_GLOBAL_CONFIG, +} = STRINGS; + +const { + FetchingFileError, + ReadFileError, + MissingCSVColumnError, + QueryDataNotFoundError, + GlobalConfigError, + CSVParseError, +} = ERRORS; export const CSVLookup = (globalConfig: any): ExecutePlugin => { const metadata = { @@ -36,18 +52,16 @@ export const CSVLookup = (globalConfig: any): ExecutePlugin => { const retrieveFile = async (filepath: string) => { if (isURL(filepath)) { const {data} = await axios.get(filepath).catch(error => { - throw new FileNotFoundError(`Something went wrong while reading the file: ${filepath}. - ${error.response.message}`); + throw new FetchingFileError( + FILE_FETCH_FAILED(filepath, error.response.message) + ); }); return data; } return readFile(filepath).catch(error => { - throw new FileNotFoundError( - `Something went wrong while reading the file: ${filepath}. -${error}` - ); + throw new ReadFileError(FILE_READ_FAILED(filepath, error)); }); }; @@ -81,7 +95,7 @@ ${error}` */ const fieldAccessor = (field: string, object: any) => { if (!(`${field}` in object)) { - throw new InputValidationError(`There is no column with name: ${field}.`); + throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); } return nanifyEmptyValues(object[field]); @@ -149,6 +163,24 @@ ${error}` return ifMatchesCriteria.every(value => value === true); }; + /** + * Parses CSV file. + */ + const parseCSVFile = (file: string | Buffer) => { + try { + const parsedCSV: any[] = parse(file, { + columns: true, + skip_empty_lines: true, + cast: true, + }); + + return parsedCSV; + } catch (error: any) { + console.error(error); + throw new CSVParseError(error); + } + }; + /** * 1. Validates global config. * 2. Tries to retrieve given file (with url or local path). @@ -160,41 +192,29 @@ ${error}` const {filepath, query, output} = safeGlobalConfig; const file = await retrieveFile(filepath); - - try { - const parsedCSV: any[] = parse(file, { - columns: true, - skip_empty_lines: true, - cast: true, + const parsedCSV = parseCSVFile(file); + + return inputs.map(input => { + /** Collects query values from input. */ + const queryData: any = {}; + const queryKeys = Object.keys(query); + queryKeys.forEach(queryKey => { + const queryValue = query[queryKey]; + queryData[queryKey] = input[queryValue]; }); - return inputs.map(input => { - /** Collects query values from input. */ - const queryData: any = {}; - const queryKeys = Object.keys(query); - queryKeys.forEach(queryKey => { - const queryValue = query[queryKey]; - queryData[queryKey] = input[queryValue]; - }); - - /** Gets related data from CSV. */ - const relatedData = parsedCSV.find(withCriteria(queryData)); + /** Gets related data from CSV. */ + const relatedData = parsedCSV.find(withCriteria(queryData)); - if (!relatedData) { - throw new InputValidationError( - 'One or more of the given query parameters are not found in the target CSV file column headers.' - ); - } + if (!relatedData) { + throw new QueryDataNotFoundError(NO_QUERY_DATA); + } - return { - ...input, - ...filterOutput(relatedData, {output, query}), - }; - }); - } catch (error) { - throw new InputValidationError(`Error happened while parsing given CSV file: ${filepath} -${error}`); - } + return { + ...input, + ...filterOutput(relatedData, {output, query}), + }; + }); }; /** @@ -202,7 +222,7 @@ ${error}`); */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ diff --git a/src/builtins/divide/README.md b/src/builtins/divide/README.md index d403d0361..9a4d04f36 100644 --- a/src/builtins/divide/README.md +++ b/src/builtins/divide/README.md @@ -4,8 +4,6 @@ You provide the names of the values you want to divide, and a name to use to add the divide to the output array. -For example, `boavizta-cpu` need `cpu/number-cores` to work, however `cloud-metadata` returns `vcpus-allocated`, to get number of cores you divide `vcpus-allocated` by 2. - ## Parameters ### Plugin config @@ -26,6 +24,8 @@ For example, `boavizta-cpu` need `cpu/number-cores` to work, however `cloud-meta The plugin throws an exception if the division result is not a number. +>Note: Plugin will warn and return `numerator` value in case if `denominator` is zero. + ## Calculation ```pseudocode @@ -89,7 +89,33 @@ You can run this example by saving it as `./examples/manifests/divide.yml` and e ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml +if-run --manifest ./examples/manifests/divide.yml --output ./examples/outputs/divide.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + +## Errors + +`Divide` exposes two of IF's error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `numerator`: a string containing the name of the input parameter whose value should be divided by `denominator` +- `denominator`: a number to use as the denominator +- ``output`: a string containing the name to assign the result of the division + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `numerator` + + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/divide/index.ts b/src/builtins/divide/index.ts index b91d4c9fa..453a50921 100644 --- a/src/builtins/divide/index.ts +++ b/src/builtins/divide/index.ts @@ -1,11 +1,13 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; -import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; -import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; +import {STRINGS} from '../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -19,16 +21,16 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { const safeGlobalConfig = validateGlobalConfig(); const {numerator, denominator, output} = safeGlobalConfig; - return inputs.map(input => { + return inputs.map((input, index) => { const safeInput = Object.assign( {}, input, - validateSingleInput(input, numerator, denominator) + validateSingleInput(input, {numerator, denominator}) ); return { ...input, - [output]: calculateDivide(safeInput, numerator, denominator), + [output]: calculateDivide(safeInput, index, {numerator, denominator}), }; }); }; @@ -38,12 +40,12 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z.object({ numerator: z.string().min(1), - denominator: z.string().or(z.number().gt(0)), + denominator: z.string().or(z.number()), output: z.string(), }); @@ -55,9 +57,13 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateSingleInput = ( input: PluginParams, - numerator: string, - denominator: number | string + params: { + numerator: string; + denominator: number | string; + } ) => { + const {numerator, denominator} = params; + const schema = z .object({ [numerator]: z.number(), @@ -65,10 +71,9 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { }) .refine(() => { if (typeof denominator === 'string' && !input[denominator]) { - throw new InputValidationError( - `\`${denominator}\` is missing from the input.` - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(denominator)); } + return true; }); @@ -80,9 +85,22 @@ export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { */ const calculateDivide = ( input: PluginParams, - numerator: string, - denominator: number | string - ) => input[numerator] / (input[denominator] || denominator); + index: number, + params: { + numerator: string; + denominator: number | string; + } + ) => { + const {denominator, numerator} = params; + const finalDenominator = input[denominator] || denominator; + + if (finalDenominator === 0) { + console.warn(ZERO_DIVISION(Divide.name, index)); + return input[numerator]; + } + + return input[numerator] / finalDenominator; + }; return { metadata, diff --git a/src/builtins/exponent/README.md b/src/builtins/exponent/README.md index 48a67965a..91d938cef 100644 --- a/src/builtins/exponent/README.md +++ b/src/builtins/exponent/README.md @@ -91,7 +91,27 @@ You can run this example by saving it as `manifests/examples/test/exponent.yml` ```sh npm i -g @grnsft/if -ie --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml +if-run --manifest manifests/examples/test/exponent.yml --output manifests/outputs/exponent.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Exponent` exposes two of IF's error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: + +- `timestamp` +- `duration` +- whatever value you passed to `input-parameter` + + +### `InputValidationError` + +This error arises when an invalid value is passed to `Exponent`. 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 diff --git a/src/builtins/exponent/index.ts b/src/builtins/exponent/index.ts index 404161e63..ce4e959ef 100644 --- a/src/builtins/exponent/index.ts +++ b/src/builtins/exponent/index.ts @@ -1,16 +1,13 @@ import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + ExponentConfig, +} from '@grnsft/if-core/types'; -import {ERRORS} from '../../util/errors'; -import {buildErrorMessage} from '../../util/helpers'; import {validate} from '../../util/validations'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ExponentConfig} from './types'; - -const {InputValidationError} = ERRORS; - export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Exponent.name); const metadata = { kind: 'execute', }; @@ -21,7 +18,7 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const validateGlobalConfig = () => { const globalConfigSchema = z.object({ 'input-parameter': z.string().min(1), - exponent: z.number().min(1), + exponent: z.number(), 'output-parameter': z.string().min(1), }); @@ -35,28 +32,13 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { * Checks for required fields in input. */ const validateSingleInput = (input: PluginParams, inputParameter: string) => { - validateParamExists(input, inputParameter); - validateNumericString(input[inputParameter]); - }; + const inputData = { + 'input-parameter': input[inputParameter], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); - const validateParamExists = (input: PluginParams, param: string) => { - if (input[param] === undefined) { - throw new InputValidationError( - errorBuilder({ - message: `${param} is missing from the input array`, - }) - ); - } - }; - - const validateNumericString = (str: string) => { - if (isNaN(+Number(str))) { - throw new InputValidationError( - errorBuilder({ - message: `${str} is not numeric`, - }) - ); - } + return input; }; /** @@ -65,9 +47,10 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { const execute = (inputs: PluginParams[]): PluginParams[] => { const { 'input-parameter': inputParameter, - exponent: exponent, + exponent, 'output-parameter': outputParameter, } = validateGlobalConfig(); + return inputs.map(input => { validateSingleInput(input, inputParameter); @@ -87,6 +70,7 @@ export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { exponent: number ) => { const base = input[inputParameter]; + return Math.pow(base, exponent); }; diff --git a/src/builtins/exponent/types.ts b/src/builtins/exponent/types.ts deleted file mode 100644 index 54e8b2efc..000000000 --- a/src/builtins/exponent/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ExponentConfig = { - 'input-parameter': string; - exponent: number; - 'output-parameter': string; -}; diff --git a/src/builtins/export-csv-raw.ts b/src/builtins/export-csv-raw.ts index 223680759..7afc21cb2 100644 --- a/src/builtins/export-csv-raw.ts +++ b/src/builtins/export-csv-raw.ts @@ -1,16 +1,14 @@ import * as fs from 'fs/promises'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../util/errors'; +import {STRINGS} from '../config'; -import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; -import {STRINGS} from '../config/strings'; +const {ExhaustOutputArgError, WriteFileError} = ERRORS; +const {OUTPUT_REQUIRED, WRITE_CSV_ERROR, EXPORTING_RAW_CSV_FILE} = STRINGS; -const {ExhaustError} = ERRORS; -const {EXPORTING_RAW_CSV_FILE} = STRINGS; - -export const ExportCSVRaw = (): ExhaustPluginInterface => { +export const ExportCSVRaw = () => { /** * handle a tree leaf, where there are no child nodes, by adding it as key->value pair to the flat map * and capturing key as a header @@ -130,7 +128,7 @@ export const ExportCSVRaw = (): ExhaustPluginInterface => { try { await fs.writeFile(`${outputPath}.csv`, content); } catch (error) { - throw new ExhaustError(`Failed to write CSV to ${outputPath}: ${error}`); + throw new WriteFileError(WRITE_CSV_ERROR(outputPath, error)); } }; @@ -139,7 +137,7 @@ export const ExportCSVRaw = (): ExhaustPluginInterface => { */ const execute = async (tree: any, _context: Context, outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } console.debug(EXPORTING_RAW_CSV_FILE(outputPath)); diff --git a/src/builtins/export-csv.ts b/src/builtins/export-csv.ts index 7accbf932..53a105733 100644 --- a/src/builtins/export-csv.ts +++ b/src/builtins/export-csv.ts @@ -1,15 +1,15 @@ import {writeFile} from 'fs/promises'; + import {stringify} from 'csv-stringify/sync'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; -import {ERRORS} from '../util/errors'; +import {STRINGS} from '../config'; import {Context} from '../types/manifest'; -import {PluginParams} from '../types/interface'; - -import {STRINGS} from '../config/strings'; -const {ExhaustError} = ERRORS; -const {EXPORTING_TO_CSV_FILE} = STRINGS; +const {ExhaustOutputArgError} = ERRORS; +const {CSV_EXPORT, OUTPUT_REQUIRED, EXPORTING_TO_CSV_FILE} = STRINGS; /** * Extension to IF that outputs the tree in a CSV format. @@ -19,15 +19,13 @@ export const ExportCSV = () => { const validatedPath = validateOutputPath(outputPath); const paths = validatedPath.split('#'); - const output = paths.slice(0, paths.length - 1).join(''); const criteria = paths[paths.length - 1]; if (paths.length <= 1 || !criteria) { - throw new ExhaustError( - 'CSV export criteria is not found in output path. Please append it after --output #.' - ); + throw new ExhaustOutputArgError(CSV_EXPORT); } + const output = paths.slice(0, paths.length - 1).join(''); console.debug(EXPORTING_TO_CSV_FILE(output)); return { @@ -41,11 +39,7 @@ export const ExportCSV = () => { */ const validateOutputPath = (outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); - } - - if (!outputPath.includes('#')) { - throw new ExhaustError('Output path should contain `#`.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } return outputPath; diff --git a/src/builtins/export-log.ts b/src/builtins/export-log.ts index 3120f3386..fee267dc2 100644 --- a/src/builtins/export-log.ts +++ b/src/builtins/export-log.ts @@ -1,4 +1,5 @@ import * as YAML from 'js-yaml'; + import {Context} from '../types/manifest'; export const ExportLog = () => { diff --git a/src/builtins/export-yaml.ts b/src/builtins/export-yaml.ts index 99bb35f5a..624e1298f 100644 --- a/src/builtins/export-yaml.ts +++ b/src/builtins/export-yaml.ts @@ -1,12 +1,13 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + import {saveYamlFileAs} from '../util/yaml'; -import {ERRORS} from '../util/errors'; -import {Context} from '../types/manifest'; +import {STRINGS} from '../config'; -import {STRINGS} from '../config/strings'; +import {Context} from '../types/manifest'; -const {ExhaustError} = ERRORS; -const {EXPORTING_TO_YAML_FILE} = STRINGS; +const {ExhaustOutputArgError} = ERRORS; +const {OUTPUT_REQUIRED, EXPORTING_TO_YAML_FILE} = STRINGS; export const ExportYaml = () => { /** Takes string before hashtag. */ @@ -17,7 +18,7 @@ export const ExportYaml = () => { */ const execute = async (tree: any, context: Context, outputPath: string) => { if (!outputPath) { - throw new ExhaustError('Output path is required.'); + throw new ExhaustOutputArgError(OUTPUT_REQUIRED); } const outputFile = { diff --git a/src/builtins/group-by.ts b/src/builtins/group-by.ts index 6a7036adf..63c4cd5c5 100644 --- a/src/builtins/group-by.ts +++ b/src/builtins/group-by.ts @@ -1,16 +1,18 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + GroupByPlugin, + PluginParams, + GroupByConfig, +} from '@grnsft/if-core/types'; import {STRINGS} from '../config'; -import {GroupByPlugin, PluginParams} from '../types/interface'; -import {GroupByConfig} from '../types/group-by'; - -import {ERRORS} from '../util/errors'; import {validate} from '../util/validations'; -const {InvalidGroupingError, InputValidationError} = ERRORS; +const {InvalidGroupingError, GlobalConfigError} = ERRORS; -const {INVALID_GROUP_BY} = STRINGS; +const {INVALID_GROUP_BY, MISSING_GLOBAL_CONFIG} = STRINGS; /** * Plugin for inputs grouping. @@ -79,7 +81,7 @@ export const GroupBy = (): GroupByPlugin => { */ const validateConfig = (config: GroupByConfig) => { if (!config) { - throw new InputValidationError('Config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z.object({ diff --git a/src/builtins/index.ts b/src/builtins/index.ts index 1a98e3273..d22491aca 100644 --- a/src/builtins/index.ts +++ b/src/builtins/index.ts @@ -13,3 +13,4 @@ export {Exponent} from './exponent'; export {CSVLookup} from './csv-lookup'; export {Shell} from './shell'; export {Regex} from './regex'; +export {Copy} from './copy-param'; diff --git a/src/builtins/interpolation/README.md b/src/builtins/interpolation/README.md index cfcca2fa1..498c26c6e 100644 --- a/src/builtins/interpolation/README.md +++ b/src/builtins/interpolation/README.md @@ -164,5 +164,33 @@ You can execute this by passing it to `ie`. Run the impact using the following c ```sh npm i -g @grnsft/if -ie --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml +if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/outputs/interpolation.yml ``` + +## Errors + +`Interpolation` exposes one of IF's error classes. + +## `GlobalConfigError` + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `method`: a string containing either `linear`, `spline` or `polynomial` +- `x`: an array of numbers +- `y`: an array of numbers +- `input-parameter`: a string containing the name of a value present in the `inputs` array' +- `output-parameter`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### Validation errors + +There are also several validation errors that can arise, including: +- if the lengths of `x` and `y` are not equal +- if `x` or `y` are empty +- if the requested point to interpolate at is outside the range of `x` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/interpolation/index.ts b/src/builtins/interpolation/index.ts index 3c0e0381b..98a84ad8a 100644 --- a/src/builtins/interpolation/index.ts +++ b/src/builtins/interpolation/index.ts @@ -1,14 +1,24 @@ import Spline from 'typescript-cubic-spline'; import {z} from 'zod'; - -import {ExecutePlugin, PluginParams, ConfigParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + Method, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; -import {Method} from './types'; +import {STRINGS} from '../../config'; -const {ConfigNotFoundError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const { + MISSING_GLOBAL_CONFIG, + X_Y_EQUAL, + ARRAY_LENGTH_NON_EMPTY, + WITHIN_THE_RANGE, +} = STRINGS; export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { /** @@ -118,7 +128,7 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const schema = z @@ -130,10 +140,10 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { 'output-parameter': z.string(), }) .refine(data => data.x && data.y && data.x.length === data.y.length, { - message: 'The length of `x` and `y` should be equal', + message: X_Y_EQUAL, }) .refine(data => data.x.length > 1 && data.y.length > 1, { - message: 'the length of the input arrays must be greater than 1', + message: ARRAY_LENGTH_NON_EMPTY, }); const defaultMethod = globalConfig.method ?? Method.LINEAR; @@ -171,8 +181,7 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { data[inputParameter] >= globalConfig.x[0] && data[inputParameter] <= globalConfig.x[globalConfig.x.length - 1], { - message: - 'The target x value must be within the range of the given x values', + message: WITHIN_THE_RANGE, } ); diff --git a/src/builtins/interpolation/types.ts b/src/builtins/interpolation/types.ts deleted file mode 100644 index 09b7abb5e..000000000 --- a/src/builtins/interpolation/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum Method { - LINEAR = 'linear', - SPLINE = 'spline', - POLYNOMIAL = 'polynomial', -} diff --git a/src/builtins/mock-observations/README.md b/src/builtins/mock-observations/README.md index 629e27f2d..1af4cd6d6 100644 --- a/src/builtins/mock-observations/README.md +++ b/src/builtins/mock-observations/README.md @@ -91,7 +91,7 @@ You can run this example `manifest` by saving it as `manifests/plugins/mock-obse ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation +if-run --manifest ./examples/manifests/test/mock-observation.yml --output ./examples/outputs/mock-observation ``` The results will be saved to a new `yaml` file in `./examples/outputs`. diff --git a/src/builtins/mock-observations/helpers/common-generator.ts b/src/builtins/mock-observations/helpers/common-generator.ts index 24bea4c94..8283cf1bd 100644 --- a/src/builtins/mock-observations/helpers/common-generator.ts +++ b/src/builtins/mock-observations/helpers/common-generator.ts @@ -1,37 +1,31 @@ -import {KeyValuePair} from '../../../types/common'; -import {ERRORS} from '../../../util/errors'; -import {buildErrorMessage} from '../../../util/helpers'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ConfigParams} from '@grnsft/if-core/types'; -import {Generator} from '../interfaces'; - -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../config'; -export const CommonGenerator = (config: KeyValuePair): Generator => { - const errorBuilder = buildErrorMessage(CommonGenerator.name); +import {Generator} from '../interfaces'; - /** - * Creates new copy of the given `object`. - */ - const copyObject = (object: T): T => ({...object}); +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; +export const CommonGenerator = (config: ConfigParams): Generator => { /** + * Generates next value by copying the validated config. * Validates the provided config is not null or empty. - * returns a copy of the validated config, otherwise throws an InputValidationError. + * Returns a copy of the validated config, otherwise throws an GlobalConfigError. */ const validateConfig = (config: object) => { if (!config || Object.keys(config).length === 0) { - throw new InputValidationError( - errorBuilder({message: 'Config must not be null or empty'}) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } - return copyObject(config); + return structuredClone(config); }; /** * Generates next value by copying the validated config. */ - const next = (): Object => copyObject(validateConfig(config)); + const next = (): Object => validateConfig(config); return { next, diff --git a/src/builtins/mock-observations/helpers/rand-int-generator.ts b/src/builtins/mock-observations/helpers/rand-int-generator.ts index e27d694c3..1cb4d161f 100644 --- a/src/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/builtins/mock-observations/helpers/rand-int-generator.ts @@ -1,70 +1,55 @@ -import {KeyValuePair} from '../../../types/common'; -import {ERRORS} from '../../../util/errors'; -import {buildErrorMessage} from '../../../util/helpers'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {RandIntGeneratorParams, ConfigParams} from '@grnsft/if-core/types'; + +import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; -import {RandIntGeneratorParams} from '../types'; -const {InputValidationError} = ERRORS; +const {GlobalConfigError} = ERRORS; + +const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = + STRINGS; export const RandIntGenerator = ( name: string, - config: KeyValuePair + config: ConfigParams ): Generator => { - const errorBuilder = buildErrorMessage(RandIntGenerator.name); - const next = () => ({ [validatedName]: generateRandInt(getFieldToPopulate()), }); const validateName = (name: string | null): string => { if (!name || name.trim() === '') { - throw new InputValidationError( - errorBuilder({ - message: '`name` is empty or all spaces', - }) - ); + throw new GlobalConfigError(INVALID_NAME); } + return name; }; - const validateConfig = (config: KeyValuePair): {min: number; max: number} => { + const validateConfig = (config: ConfigParams): {min: number; max: number} => { if (!config || Object.keys(config).length === 0) { - throw new InputValidationError( - errorBuilder({ - message: 'Config must not be null or empty', - }) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } if (!config.min || !config.max) { - throw new InputValidationError( - errorBuilder({ - message: 'Config is missing min or max', - }) - ); + throw new GlobalConfigError(MISSING_MIN_MAX); } if (config.min >= config.max) { - throw new InputValidationError( - errorBuilder({ - message: `Min value should not be greater than or equal to max value of ${validatedName}`, - }) - ); + throw new GlobalConfigError(INVALID_MIN_MAX(validatedName)); } + return {min: config.min, max: config.max}; }; const validatedName = validateName(name); const validatedConfig = validateConfig(config); - const getFieldToPopulate = () => { - return { - name: validatedName, - min: validatedConfig.min, - max: validatedConfig.max, - }; - }; + const getFieldToPopulate = () => ({ + name: validatedName, + min: validatedConfig.min, + max: validatedConfig.max, + }); const generateRandInt = ( randIntGenerator: RandIntGeneratorParams @@ -73,6 +58,7 @@ export const RandIntGenerator = ( const scaledNumber = randomNumber * (randIntGenerator.max - randIntGenerator.min) + randIntGenerator.min; + return Math.trunc(scaledNumber); }; diff --git a/src/builtins/mock-observations/index.ts b/src/builtins/mock-observations/index.ts index 2d65f4643..c7488de0f 100644 --- a/src/builtins/mock-observations/index.ts +++ b/src/builtins/mock-observations/index.ts @@ -1,15 +1,18 @@ import {DateTime, Duration} from 'luxon'; import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams, KeyValuePair} from '../../types/common'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + ObservationParams, +} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; + import {Generator} from './interfaces/index'; -import {ObservationParams} from './types'; export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -122,11 +125,10 @@ export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { CommonGenerator(config), ]; - const createRandIntGenerators = (config: any): Generator[] => { - return Object.entries(config).map(([fieldToPopulate, value]) => - RandIntGenerator(fieldToPopulate, value as KeyValuePair) + const createRandIntGenerators = (config: any): Generator[] => + Object.entries(config).map(([fieldToPopulate, value]) => + RandIntGenerator(fieldToPopulate, value as Record) ); - }; return Object.entries(generatorsConfig).flatMap(([key, value]) => key === 'randint' diff --git a/src/builtins/mock-observations/types.ts b/src/builtins/mock-observations/types.ts deleted file mode 100644 index 82591207c..000000000 --- a/src/builtins/mock-observations/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {DateTime} from 'luxon'; - -import {Generator} from './interfaces/index'; - -export type ObservationParams = { - duration: number; - timeBucket: DateTime; - component: Record; - generators: Generator[]; -}; - -export type RandIntGeneratorParams = { - name: string; - min: number; - max: number; -}; diff --git a/src/builtins/multiply/README.md b/src/builtins/multiply/README.md index d4e27674c..7e9c2dfbd 100644 --- a/src/builtins/multiply/README.md +++ b/src/builtins/multiply/README.md @@ -88,7 +88,22 @@ You can run this example by saving it as `./examples/manifests/test/multiply.yml ```sh npm i -g @grnsft/if -ie --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml +if-run --manifest ./examples/manifests/test/multiply.yml --output ./examples/outputs/multiply.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs` + + +## Errors + +`Multiply` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/multiply/index.ts b/src/builtins/multiply/index.ts index 5666a6093..cd2a74837 100644 --- a/src/builtins/multiply/index.ts +++ b/src/builtins/multiply/index.ts @@ -1,16 +1,13 @@ import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + MultiplyConfig, +} from '@grnsft/if-core/types'; -import {buildErrorMessage} from '../../util/helpers'; -import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {MultiplyConfig} from './types'; - -const {InputValidationError} = ERRORS; - export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Multiply.name); const metadata = { kind: 'execute', }; @@ -37,18 +34,18 @@ export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToMultiply => { - if ( - input[metricToMultiply] === undefined || - isNaN(input[metricToMultiply]) - ) { - throw new InputValidationError( - errorBuilder({ - message: `${metricToMultiply} is missing from the input array`, - }) - ); - } - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + + const validationSchema = z.record(z.string(), z.number()); + + validate(validationSchema, inputData); return input; }; @@ -62,17 +59,17 @@ export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { const outputParameter = safeGlobalConfig['output-parameter']; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); + validateSingleInput(input, inputParameters); return { ...input, - [outputParameter]: calculateProduct(safeInput, inputParameters), + [outputParameter]: calculateProduct(input, inputParameters), }; }); }; /** - * Calculates the product of the energy components. + * Calculates the product of the components. */ const calculateProduct = (input: PluginParams, inputParameters: string[]) => inputParameters.reduce( diff --git a/src/builtins/multiply/types.ts b/src/builtins/multiply/types.ts deleted file mode 100644 index 88f4cae49..000000000 --- a/src/builtins/multiply/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type MultiplyConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; diff --git a/src/builtins/regex/README.md b/src/builtins/regex/README.md index 52a99db9f..a0fa5d624 100644 --- a/src/builtins/regex/README.md +++ b/src/builtins/regex/README.md @@ -4,8 +4,6 @@ You provide the name of the value you want to match, and a name to use to add the regex to the output array. -For example, `boavizta-cpu` need `cpu/name` to work, however `cloud-metadata` returns `physical-processor` which usually contains a long string of processors that the instance could be separated by `,`, like so: - ``` 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 ``` @@ -89,3 +87,35 @@ if --manifest manifests/examples/regex.yml --output manifests/outputs/regex.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + +## Errors + +`Regex` uses three of IF's error classes: + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- whatever value you passed to `parameter` + + +### `GlobalConfigError` + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: + +- `parameter`: a string containing the name of a value in the inputs array +- `match`: a valid regex pattern +- `output`: a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + + +### `RegexMismatchError` + +This error arises when the requested regex cannot find any matches in the given data. If there are multiple matches, the plugin returns the first, but if there are none, it throws this error. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/regex/index.ts b/src/builtins/regex/index.ts index 7dc854461..8d382ec74 100644 --- a/src/builtins/regex/index.ts +++ b/src/builtins/regex/index.ts @@ -1,16 +1,15 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; -import {buildErrorMessage} from '../../util/helpers'; -import {ERRORS} from '../../util/errors'; import {validate} from '../../util/validations'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; +import {STRINGS} from '../../config'; -const {InputValidationError, ConfigValidationError} = ERRORS; +const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; +const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Regex.name); const metadata = { kind: 'execute', }; @@ -20,10 +19,9 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigValidationError( - errorBuilder({message: 'Configuration data is missing'}) - ); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } + const schema = z.object({ parameter: z.string().min(1), match: z.string().min(1), @@ -38,11 +36,7 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { */ const validateSingleInput = (input: PluginParams, parameter: string) => { if (!input[parameter]) { - throw new InputValidationError( - errorBuilder({ - message: `\`${parameter}\` is missing from the input`, - }) - ); + throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); } return input; @@ -89,11 +83,7 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { const matchedItem = input[parameter].match(regex); if (!matchedItem || !matchedItem[0]) { - throw new InputValidationError( - errorBuilder({ - message: `\`${input[parameter]}\` does not match the ${match} regex expression`, - }) - ); + throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); } return matchedItem[0]; diff --git a/src/builtins/sci-embodied/README.md b/src/builtins/sci-embodied/README.md index 90fc01d58..97b6ce4af 100644 --- a/src/builtins/sci-embodied/README.md +++ b/src/builtins/sci-embodied/README.md @@ -104,7 +104,21 @@ You can run this example `manifest` by executing the following command from the ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml +if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`SciEmbodied` uses one of IF's error classes + +### `SciEmbodiedError` + +This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. + +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 diff --git a/src/builtins/sci-embodied/index.ts b/src/builtins/sci-embodied/index.ts index 162099860..a88017e9f 100644 --- a/src/builtins/sci-embodied/index.ts +++ b/src/builtins/sci-embodied/index.ts @@ -1,9 +1,12 @@ import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../util/validations'; +import {STRINGS} from '../../config'; + +const {SCI_EMBODIED_ERROR} = STRINGS; + export const SciEmbodied = (): ExecutePlugin => { const metadata = { kind: 'execute', @@ -21,8 +24,8 @@ export const SciEmbodied = (): ExecutePlugin => { /** * Calculate the Embodied carbon for a list of inputs. */ - const execute = (inputs: PluginParams[]) => { - return inputs.map(input => { + const execute = (inputs: PluginParams[]) => + inputs.map(input => { const safeInput = validateInput(input); return { @@ -30,7 +33,6 @@ export const SciEmbodied = (): ExecutePlugin => { 'carbon-embodied': calculateEmbodiedCarbon(safeInput), }; }); - }; /** * Calculate the Embodied carbon for the input. @@ -55,9 +57,6 @@ export const SciEmbodied = (): ExecutePlugin => { * Checks for required fields in input. */ const validateInput = (input: PluginParams) => { - const errorMessage = (unit: string) => - `not a valid number in input. Please provide it as \`${unit}\``; - const commonSchemaPart = (errorMessage: (unit: string) => string) => ({ 'device/emissions-embodied': z .number({ @@ -81,13 +80,13 @@ export const SciEmbodied = (): ExecutePlugin => { const vcpusSchemaPart = { 'vcpus-allocated': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), 'vcpus-total': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), @@ -96,24 +95,24 @@ export const SciEmbodied = (): ExecutePlugin => { const resourcesSchemaPart = { 'resources-reserved': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), 'resources-total': z .number({ - invalid_type_error: errorMessage('count'), + invalid_type_error: SCI_EMBODIED_ERROR('count'), }) .gte(0) .min(0), }; const schemaWithVcpus = z.object({ - ...commonSchemaPart(errorMessage), + ...commonSchemaPart(SCI_EMBODIED_ERROR), ...vcpusSchemaPart, }); const schemaWithResources = z.object({ - ...commonSchemaPart(errorMessage), + ...commonSchemaPart(SCI_EMBODIED_ERROR), ...resourcesSchemaPart, }); diff --git a/src/builtins/sci/README.md b/src/builtins/sci/README.md index 477f74dc0..592bd1ed0 100644 --- a/src/builtins/sci/README.md +++ b/src/builtins/sci/README.md @@ -19,6 +19,8 @@ - `sci`: carbon expressed in terms of the given functional unit +>Note: Plugin will warn and return `carbon` value in case if `functional-unit`'s value is zero. + ## Calculation SCI is calculated as: @@ -83,7 +85,28 @@ You can run this example `manifest` by saving it as `./manifests/plugins/sci.yml ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml +if-run --manifest manifests/plugins/sci.yml --output manifests/outputs/sci.yml ``` The results will be saved to a new `yaml` file. + +## Errors + +`SCI` uses one of the IF error classes. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. + +Every element in the `inputs` array must contain: +- `timestamp` +- `duration` +- `carbon`: a numeric value named `carbon` must exist in the inputs array +- whatever value you passed to `functional-unit` + + +### Validation errors + +There is also a validation step that checks that the `functional-unit` was provided in the plugin config. If you see an error reporting this value as missing, please check you have provided it. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/sci/index.ts b/src/builtins/sci/index.ts index 7a60db439..47d495351 100644 --- a/src/builtins/sci/index.ts +++ b/src/builtins/sci/index.ts @@ -1,16 +1,20 @@ import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../util/validations'; -import {buildErrorMessage} from '../../util/helpers'; -import {ERRORS} from '../../util/errors'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../config'; + +const {MissingInputDataError} = ERRORS; +const { + MISSING_FUNCTIONAL_UNIT_CONFIG, + MISSING_FUNCTIONAL_UNIT_INPUT, + SCI_MISSING_FN_UNIT, + ZERO_DIVISION, +} = STRINGS; export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Sci.name); const metadata = { kind: 'execute', }; @@ -19,15 +23,12 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { * Validates node and gloabl configs. */ const validateConfig = (config?: ConfigParams) => { - const errorMessage = - '`functional-unit` should be provided in your global config'; - const schema = z .object({ 'functional-unit': z.string(), }) .refine(data => data['functional-unit'], { - message: errorMessage, + message: MISSING_FUNCTIONAL_UNIT_CONFIG, }); return validate>(schema, config); @@ -36,40 +37,39 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { /** * Calculate the total emissions for a list of inputs. */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - return inputs.map(input => { + const execute = (inputs: PluginParams[]): PluginParams[] => + inputs.map((input, index) => { const safeInput = validateInput(input); - const sci = - safeInput['carbon'] > 0 - ? safeInput['carbon'] / input[globalConfig['functional-unit']] - : 0; + const functionalUnit = input[globalConfig['functional-unit']]; + + if (functionalUnit === 0) { + console.warn(ZERO_DIVISION(Sci.name, index)); + + return { + ...input, + sci: safeInput['carbon'], + }; + } + return { ...input, - sci, + sci: safeInput['carbon'] / functionalUnit, }; }); - }; /** * Checks for fields in input. */ const validateInput = (input: PluginParams) => { - const message = `'carbon' and ${globalConfig['functional-unit']} should be present in your input data.`; - const validatedConfig = validateConfig(globalConfig); if ( !( validatedConfig['functional-unit'] in input && - input[validatedConfig['functional-unit']] > 0 + input[validatedConfig['functional-unit']] >= 0 ) ) { - throw new InputValidationError( - errorBuilder({ - message: - 'functional-unit value is missing from input data or it is not a positive integer', - }) - ); + throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); } const schema = z @@ -77,7 +77,9 @@ export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { carbon: z.number().gte(0), duration: z.number().gte(1), }) - .refine(allDefined, {message}); + .refine(allDefined, { + message: SCI_MISSING_FN_UNIT(globalConfig['functional-unit']), + }); return validate>(schema, input); }; diff --git a/src/builtins/shell/README.md b/src/builtins/shell/README.md index ea813878b..bacba1255 100644 --- a/src/builtins/shell/README.md +++ b/src/builtins/shell/README.md @@ -124,7 +124,18 @@ You can run this example `manifest` by saving it as `manifests/plugins/shell.yml ```sh npm i -g @grnsft/if -ie --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml +if-run --manifest manifests/plugins/shell.yml --output manifests/outputs/shell.yml ``` The results will be saved to a new `yaml` file. + + +## Errors + +`Shell` uses one of the error classes provided by IF + +### `ProcessExecutionError` + +This error is thrown when the program invoked in the spawned shell fails for some reason that is not known to IF. Since the shell executes arbitrary code, it is difficult for IF to provide specific errors - this is delegated to the developers of the executed program. + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors diff --git a/src/builtins/shell/index.ts b/src/builtins/shell/index.ts index 43b1c224c..352ee6bcd 100644 --- a/src/builtins/shell/index.ts +++ b/src/builtins/shell/index.ts @@ -1,14 +1,13 @@ import {spawnSync, SpawnSyncReturns} from 'child_process'; + import {loadAll, dump} from 'js-yaml'; import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {ConfigParams} from '../../types/common'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; -const {InputValidationError} = ERRORS; +const {ProcessExecutionError} = ERRORS; export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { const metadata = { @@ -55,7 +54,7 @@ export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { return {outputs}; } catch (error: any) { - throw new InputValidationError(error.message); + throw new ProcessExecutionError(error.message); } }; diff --git a/src/builtins/subtract/README.md b/src/builtins/subtract/README.md index 9279220b8..8ff9a922f 100644 --- a/src/builtins/subtract/README.md +++ b/src/builtins/subtract/README.md @@ -88,7 +88,18 @@ You can run this example by saving it as `./examples/manifests/test/subrtact.yml ```sh npm i -g @grnsft/if -ie --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml +if-run --manifest /manifests/plugins/subtract.yml --output manifests/outputs/subtract.yml ``` The results will be saved to a new `yaml` file in `manifests/outputs`. + + +## Errors + +`Subtract` uses one of IF's error classes: + +### `InputValidationError` + +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 diff --git a/src/builtins/subtract/index.ts b/src/builtins/subtract/index.ts index 0af02898a..797b259c1 100644 --- a/src/builtins/subtract/index.ts +++ b/src/builtins/subtract/index.ts @@ -1,16 +1,13 @@ import {z} from 'zod'; +import { + ExecutePlugin, + PluginParams, + SubtractConfig, +} from '@grnsft/if-core/types'; -import {ERRORS} from '../../util/errors'; -import {buildErrorMessage} from '../../util/helpers'; import {validate} from '../../util/validations'; -import {ExecutePlugin, PluginParams} from '../../types/interface'; -import {SubtractConfig} from './types'; - -const {InputValidationError} = ERRORS; - export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { - const errorBuilder = buildErrorMessage(Subtract.name); const metadata = { kind: 'execute', }; @@ -37,32 +34,20 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToSubtract => { - validateParamExists(input, metricToSubtract); - validateNumericString(input[metricToSubtract]); - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; - return input; - }; + return acc; + }, + {} as Record + ); - const validateParamExists = (input: PluginParams, param: string) => { - if (input[param] === undefined) { - throw new InputValidationError( - errorBuilder({ - message: `${param} is missing from the input array`, - }) - ); - } - }; + const validationSchema = z.record(z.string(), z.number()); + + validate(validationSchema, inputData); - const validateNumericString = (str: string) => { - if (isNaN(+Number(str))) { - throw new InputValidationError( - errorBuilder({ - message: `${str} is not numberic`, - }) - ); - } + return input; }; /** @@ -73,6 +58,7 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { 'input-parameters': inputParameters, 'output-parameter': outputParameter, } = validateGlobalConfig(); + return inputs.map(input => { validateSingleInput(input, inputParameters); @@ -88,6 +74,7 @@ export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { */ const calculateDiff = (input: PluginParams, inputParameters: string[]) => { const [firstItem, ...restItems] = inputParameters; + return restItems.reduce( (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], input[firstItem] // Starting accumulator with the value of the first item diff --git a/src/builtins/subtract/types.ts b/src/builtins/subtract/types.ts deleted file mode 100644 index 4dc6775d2..000000000 --- a/src/builtins/subtract/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type SubtractConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; diff --git a/src/builtins/sum/README.md b/src/builtins/sum/README.md index b912c07b3..ea0f0113d 100644 --- a/src/builtins/sum/README.md +++ b/src/builtins/sum/README.md @@ -85,7 +85,34 @@ tree: You can run this example by saving it as `./examples/manifests/sum.yml` and executing the following command from the project root: ```sh -ie --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml +if-run --manifest ./examples/manifests/sum.yml --output ./examples/outputs/sum.yml ``` The results will be saved to a new `yaml` file in `./examples/outputs`. + + +## Errors + +`Sum` exposes two of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: +- `input-parameters`: this must be an array of strings, each being the name of a value in the `inputs` array +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the ``inputs` array must contain: + +- `timestamp` +- `duration` +- whatever values you passed to `input-parameters` + + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors). diff --git a/src/builtins/sum/index.ts b/src/builtins/sum/index.ts index 8eec61c37..57437ba31 100644 --- a/src/builtins/sum/index.ts +++ b/src/builtins/sum/index.ts @@ -1,13 +1,13 @@ import {z} from 'zod'; - -import {ExecutePlugin, PluginParams} from '../../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {ExecutePlugin, PluginParams, SumConfig} from '@grnsft/if-core/types'; import {validate} from '../../util/validations'; -import {ERRORS} from '../../util/errors'; -import {SumConfig} from './types'; +import {STRINGS} from '../../config'; -const {InputValidationError, ConfigNotFoundError} = ERRORS; +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; export const Sum = (globalConfig: SumConfig): ExecutePlugin => { const metadata = { @@ -23,11 +23,11 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { const outputParameter = safeGlobalConfig['output-parameter']; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); + validateSingleInput(input, inputParameters); return { ...input, - [outputParameter]: calculateSum(safeInput, inputParameters), + [outputParameter]: calculateSum(input, inputParameters), }; }); }; @@ -37,7 +37,7 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (!globalConfig) { - throw new ConfigNotFoundError('Global config is not provided.'); + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); } const globalConfigSchema = z.object({ @@ -58,13 +58,16 @@ export const Sum = (globalConfig: SumConfig): ExecutePlugin => { input: PluginParams, inputParameters: string[] ) => { - inputParameters.forEach(metricToSum => { - if (!input[metricToSum]) { - throw new InputValidationError( - `${metricToSum} is missing from the input array.` - ); - } - }); + const inputData = inputParameters.reduce( + (acc, param) => { + acc[param] = input[param]; + + return acc; + }, + {} as Record + ); + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); return input; }; diff --git a/src/builtins/sum/types.ts b/src/builtins/sum/types.ts deleted file mode 100644 index e30c990e5..000000000 --- a/src/builtins/sum/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type SumConfig = { - 'input-parameters': string[]; - 'output-parameter': string; -}; diff --git a/src/builtins/time-sync.ts b/src/builtins/time-sync.ts index 67d5c9079..8b37241b8 100644 --- a/src/builtins/time-sync.ts +++ b/src/builtins/time-sync.ts @@ -1,29 +1,39 @@ import {isDate} from 'node:util/types'; + import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; - -import {parameterize} from '../lib/parameterize'; - -import {ERRORS} from '../util/errors'; - -import {STRINGS} from '../config'; - -import {ExecutePlugin, PluginParams} from '../types/interface'; +import {ERRORS} from '@grnsft/if-core/utils'; import { + ExecutePlugin, + PluginParams, PaddingReceipt, TimeNormalizerConfig, TimeParams, -} from '../types/time-sync'; +} from '@grnsft/if-core/types'; + +import {parameterize} from '../lib/parameterize'; + import {validate} from '../util/validations'; +import {STRINGS} from '../config'; + Settings.defaultZone = 'utc'; -const {InputValidationError} = ERRORS; +const { + GlobalConfigError, + InvalidDateInInputError, + InvalidPaddingError, + InvalidInputError, +} = ERRORS; const { INVALID_TIME_NORMALIZATION, INVALID_OBSERVATION_OVERLAP, AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, + START_LOWER_END, + TIMESTAMP_REQUIRED, + INVALID_DATETIME, } = STRINGS; export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { @@ -64,7 +74,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { seconds: previousInput.duration, }) > currentMoment ) { - throw new InputValidationError(INVALID_OBSERVATION_OVERLAP); + throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); } const compareableTime = previousInputTimestamp.plus({ @@ -106,19 +116,22 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { }; const parseDate = (date: Date | string) => { - if (!date) return DateTime.invalid('Invalid date'); + if (!date) { + return DateTime.invalid('Invalid date'); + } + // dates are passed to time-sync.ts both in ISO 8601 format // and as a Date object (from the deserialization of a YAML file) // if the YAML parser fails to identify as a date, it passes as a string if (isDate(date)) { return DateTime.fromJSDate(date); } + if (typeof date === 'string') { return DateTime.fromISO(date); } - throw new InputValidationError( - `Unexpected date datatype: ${typeof date}: ${date}` - ); + + throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); }; /** @@ -128,10 +141,10 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const schema = z.object({ timestamp: z .string({ - required_error: `required in input[${index}]`, + required_error: TIMESTAMP_REQUIRED(index), }) .datetime({ - message: `invalid datetime in input[${index}]`, + message: INVALID_DATETIME(index), }) .or(z.date()), duration: z.number(), @@ -145,7 +158,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { */ const validateGlobalConfig = () => { if (globalConfig === undefined) { - throw new InputValidationError(INVALID_TIME_NORMALIZATION); + throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); } const schema = z @@ -156,7 +169,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { 'allow-padding': z.boolean(), }) .refine(data => data['start-time'] < data['end-time'], { - message: '`start-time` should be lower than `end-time`', + message: START_LOWER_END, }); return validate>(schema, globalConfig); @@ -176,8 +189,10 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { i: number ) => { const thisMoment = parseDate(currentRoundMoment).startOf('second'); + return thisMoment.plus({seconds: i}); }; + /** * Breaks down input per minimal time unit. */ @@ -259,8 +274,9 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { const {start, end} = pad; const isPaddingNeeded = start || end; + if (!params.allowPadding && isPaddingNeeded) { - throw new InputValidationError(AVOIDING_PADDING_BY_EDGES(start, end)); + throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); } }; @@ -292,8 +308,8 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. * For methods is `avg` and `none` calculating average of the frame. */ - const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => { - return inputsInTimeslot.reduce((acc, input, index, inputs) => { + const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => + inputsInTimeslot.reduce((acc, input, index, inputs) => { const metrics = Object.keys(input); metrics.forEach(metric => { @@ -336,13 +352,12 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, {} as PluginParams); - }; /** * Takes each array frame with interval length, then aggregating them together as from units.yaml file. */ - const resampleInputs = (inputs: PluginParams[], params: TimeParams) => { - return inputs.reduce((acc: PluginParams[], _input, index, inputs) => { + const resampleInputs = (inputs: PluginParams[], params: TimeParams) => + inputs.reduce((acc: PluginParams[], _input, index, inputs) => { const frameStart = index * params.interval; const frameEnd = (index + 1) * params.interval; const inputsFrame = inputs.slice(frameStart, frameEnd); @@ -356,7 +371,6 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, [] as PluginParams[]); - }; /** * Pads zeroish inputs from the beginning or at the end of the inputs if needed. @@ -394,6 +408,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) ); } + return paddedArray; }; @@ -404,6 +419,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) => { const array: PluginParams[] = []; const dateRange = Interval.fromDateTimes(startDate, endDate); + for (const interval of dateRange.splitBy({second: 1})) { array.push( fillWithZeroishInput( @@ -415,6 +431,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { ) ); } + return array; }; @@ -424,8 +441,8 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const trimInputsByGlobalTimeline = ( inputs: PluginParams[], params: TimeParams - ): PluginParams[] => { - return inputs.reduce((acc: PluginParams[], item) => { + ): PluginParams[] => + inputs.reduce((acc: PluginParams[], item) => { const {timestamp} = item; if ( @@ -437,7 +454,6 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; }, [] as PluginParams[]); - }; return {metadata, execute}; }; diff --git a/src/check.ts b/src/check.ts new file mode 100644 index 000000000..f1e8f0cdd --- /dev/null +++ b/src/check.ts @@ -0,0 +1,89 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as path from 'path'; + +import {logger} from './util/logger'; +import {logStdoutFailMessage} from './util/helpers'; +import {parseIfCheckArgs} from './util/args'; +import {getYamlFiles, removeFileIfExists} from './util/fs'; + +import {STRINGS} from './config'; +import {executeCommands} from './util/npm'; + +const { + CHECKING, + DIRECTORY_YAML_FILES_NOT_FOUND, + IF_CHECK_VERIFICATION_FAILURES, + IF_CHECK_SUMMARY_LOG, + IF_CHECK_EXECUTING, +} = STRINGS; + +const IfCheck = async () => { + const commandArgs = await parseIfCheckArgs(); + + console.log(`${CHECKING}\n`); + + if (commandArgs.manifest) { + const manifest = commandArgs.manifest; + + try { + await executeCommands(manifest, false); + } catch (error: any) { + const fileName = path.basename(manifest); + const executedFile = manifest + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); + const manifestDirPath = path.dirname(manifest); + + logStdoutFailMessage(error, fileName); + + await removeFileIfExists(`${manifestDirPath}/package.json`); + await removeFileIfExists(executedFile); + } + } else { + const failedLogs = {count: 0, message: ''}; + const directory = commandArgs.directory; + const files = await getYamlFiles(directory!); + + if (files.length === 0) { + console.log(DIRECTORY_YAML_FILES_NOT_FOUND); + process.exit(1); + } + + for await (const file of files) { + const fileName = path.basename(file); + console.log(IF_CHECK_EXECUTING(fileName)); + + try { + await executeCommands(file, true); + } catch (error: any) { + const fileName = path.basename(file); + const executedFile = file + .replace(fileName, `re-${fileName}`) + .replace('yml', 'yaml'); + + const failedFilesLog = logStdoutFailMessage(error, fileName); + failedLogs.message = failedLogs.message.concat(failedFilesLog); + failedLogs.count++; + + await removeFileIfExists(executedFile); + } + } + + if (failedLogs.count > 0) { + const passedFilesCount = files.length - failedLogs.count; + + console.log(IF_CHECK_VERIFICATION_FAILURES); + console.log(failedLogs.message); + console.log(IF_CHECK_SUMMARY_LOG(passedFilesCount, files.length)); + process.exit(1); + } + } +}; + +IfCheck().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); diff --git a/src/config/config.ts b/src/config/config.ts index 5df3f3439..b8f676924 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -2,7 +2,12 @@ import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; import {STRINGS} from './strings'; -import {IFDiffArgs, IEArgs} from '../types/process-args'; +import { + IFDiffArgs, + IEArgs, + IFEnvArgs, + IFCheckArgs, +} from '../types/process-args'; const {DISCLAIMER_MESSAGE} = STRINGS; @@ -83,6 +88,68 @@ export const CONFIG = { SUCCESS_MESSAGE: 'Files match!', FAILURE_MESSAGE: 'Files do not match!', }, + IF_ENV: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + install: { + type: Boolean, + optional: true, + alias: 'i', + description: '[command to install package.json]', + }, + cwd: { + type: Boolean, + optional: true, + alias: 'c', + description: + '[command to generate the package.json in the command working directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + SUCCESS_MESSAGE: 'The environment is successfully setup!', + FAILURE_MESSAGE: 'Faied to create the environment!', + FAILURE_MESSAGE_TEMPLATE: + 'Faied to create the environment with the template manifest!', + FAILURE_MESSAGE_DEPENDENCIES: 'Manifest dependencies are not available!', + }, + IF_CHECK: { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + directory: { + type: String, + optional: true, + alias: 'd', + description: '[path to the manifests directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Check Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + }, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], diff --git a/src/config/env-template.yml b/src/config/env-template.yml new file mode 100644 index 000000000..f5fd65a6a --- /dev/null +++ b/src/config/env-template.yml @@ -0,0 +1,24 @@ +name: template manifest # rename me! +description: auto-generated template # update description! +tags: # add any tags that will help you to track your manifests +initialize: + outputs: + - yaml # you can add - csv to export to csv + plugins: # add more plugins for your use-case + memory-energy-from-memory-util: # you can name this any way you like! + method: Coefficient # the name of the function exported from the plugin + path: "builtin" # the import path + global-config: # anmy config required by the plugin + input-parameter: "memory/utilization" + coefficient: 0.0001 #kwH/GB + output-parameter: "memory/energy" +tree: + children: # add a chile for each distinct component you want to measure + child: + pipeline: # the pipeline is an ordered list of plugins you want to execute + - memory-energy-from-memory-util # must match the name in initialize! + config: # any plugin specific, node-level config + inputs: + - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string + duration: 3600 # units of seconds + memory/utilization: 10 diff --git a/src/config/params.ts b/src/config/params.ts index 377538391..76732e57b 100644 --- a/src/config/params.ts +++ b/src/config/params.ts @@ -62,12 +62,6 @@ export const PARAMETERS: Parameters = { unit: 'none', aggregation: 'sum', }, - 'functional-unit-time': { - description: - 'string describing the unit of time in which the final SCI calculation should be expressed, e.g. "1-min"', - unit: 'none', - aggregation: 'none', - }, 'gpu-util': { description: 'refers to CPU utilization.', unit: 'percentage', diff --git a/src/config/strings.ts b/src/config/strings.ts index a03192345..b6f3410b4 100644 --- a/src/config/strings.ts +++ b/src/config/strings.ts @@ -1,7 +1,6 @@ import {ManifestParameter} from '../types/manifest'; export const STRINGS = { - FILE_IS_NOT_YAML: 'Provided manifest is not in yaml format.', MANIFEST_IS_MISSING: 'Manifest is missing.', MISSING_METHOD: "Initalization param 'method' is missing.", MISSING_PATH: "Initalization param 'path' is missing.", @@ -17,12 +16,9 @@ Incubation projects are experimental, offer no support guarantee, have minimal g NOT_NATIVE_PLUGIN: (path: string) => ` You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, - SOMETHING_WRONG: 'Something wrong with cli arguments. Please check docs.', - ISSUE_TEMPLATE: ` -Impact Framework is an alpha release from the Green Software Foundation and is released to capture early feedback. If you'd like to offer some feedback, please use this issue template: -https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+`, - INVALID_MODULE_PATH: (path: string) => - `Provided module: '${path}' is invalid or not found.`, + INVALID_MODULE_PATH: (path: string, error?: any) => + `Provided module \`${path}\` is invalid or not found. ${error ?? ''} +`, INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', UNEXPECTED_TIME_CONFIG: 'Unexpected node-level config provided for time-sync plugin.', @@ -33,7 +29,6 @@ https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=fee `Avoiding padding at ${ start && end ? 'start and end' : start ? 'start' : 'end' }`, - INVALID_OBSERVATION_OVERLAP: 'Observation timestamps overlap.', INVALID_AGGREGATION_METHOD: (metric: string) => `Aggregation is not possible for given ${metric} since method is 'none'.`, METRIC_MISSING: (metric: string, index: number) => @@ -53,9 +48,68 @@ You have not selected an output method. To see your output data, you can choose --output : this will save your output data to the given filepath (do not provide file extension) Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`, SOURCE_IS_NOT_YAML: 'Given source file is not in yaml format.', - TARGET_IS_NOT_YAML: 'Given target is not in yaml format.', + TARGET_IS_NOT_YAML: 'Given target file is not in yaml format.', INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', + UNSUPPORTED_ERROR: (errorName: string) => + `UnsupportedErrorClass: plugin threw error class: ${errorName} that is not recognized by Impact Framework`, + /** Plugin messages */ + MISSING_GLOBAL_CONFIG: 'Global config is not provided.', + MISSING_INPUT_DATA: (param: string) => + `${param} is missing from the input array, or has nullish value.`, + MANIFEST_NOT_FOUND: 'Manifest file not found.', + INITIALIZING_PACKAGE_JSON: 'Initializing package.json.', + INSTALLING_NPM_PACKAGES: 'Installing npm packages...', + NOT_NUMERIC_VALUE: (str: any) => `${str} is not numberic.`, + MISSING_FUNCTIONAL_UNIT_CONFIG: + '`functional-unit` should be provided in your global config', + MISSING_FUNCTIONAL_UNIT_INPUT: + '`functional-unit` value is missing from input data or it is not a positive integer', + REGEX_MISMATCH: (input: any, match: string) => + `\`${input}\` does not match the ${match} regex expression`, + SCI_EMBODIED_ERROR: (unit: string) => + `invalid number. please provide it as \`${unit}\` to input`, + MISSING_MIN_MAX: 'Config is missing min or max value', + INVALID_MIN_MAX: (name: string) => + `Min value should not be greater than or equal to max value of ${name}`, + FILE_FETCH_FAILED: ( + filepath: string, + message: string + ) => `Failed fetching the file: ${filepath}. +${message}`, + FILE_READ_FAILED: ( + filepath: string, + error: string + ) => `Failed reading the file: ${filepath}. +${error}`, + MISSING_CSV_COLUMN: (columnName: string) => + `There is no column with the name: ${columnName}.`, + NO_QUERY_DATA: + 'One or more of the given query parameters are not found in the target CSV file column headers.', + INVALID_DATE_TYPE: (date: any) => + `Unexpected date datatype: ${typeof date}: ${date}`, + INVALID_OBSERVATION_OVERLAP: + 'Observation timestamps overlap, please check inputs.', + SCI_MISSING_FN_UNIT: (functionalUnit: string) => + `'carbon' and ${functionalUnit} should be present in your input data.`, + /** Exhaust messages */ + OUTPUT_REQUIRED: + 'Output path is required, please make sure output is configured properly.', + CSV_EXPORT: + 'CSV export criteria is not found in output path. Please append it after --output #.', + WRITE_CSV_ERROR: (outputPath: string, error: any) => + `Failed to write CSV file to ${outputPath}: ${error}`, + INVALID_NAME: + '`name` global config parameter is empty or contains all spaces', + START_LOWER_END: '`start-time` should be lower than `end-time`', + TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, + INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, + X_Y_EQUAL: 'The length of `x` and `y` should be equal', + ARRAY_LENGTH_NON_EMPTY: + 'the length of the input arrays must be greater than 1', + WITHIN_THE_RANGE: + 'The target x value must be within the range of the given x values', + /** Debugging logs */ STARTING_IF: 'Starting IF', EXITING_IF: 'Exiting IF', LOADING_MANIFEST: 'Loading manifest', @@ -80,4 +134,23 @@ Note that for the '--output' option you also need to define the output type in y `Exporting to csv file: ${savepath}`, EXPORTING_RAW_CSV_FILE: (savepath: string) => `Exporting raw csv file: ${savepath}`, + CHECKING: 'Checking...', + IF_CHECK_FLAGS_MISSING: + 'Either the `--manifest` or `--directory` command should be provided with a path', + DIRECTORY_NOT_FOUND: 'Directory not found.', + DIRECTORY_YAML_FILES_NOT_FOUND: + 'The directory does not contain any YAML/YML files.\n', + IF_CHECK_EXECUTING: (filename: string) => `Executing \`${filename}\``, + IF_CHECK_VERIFICATION_FAILURES: + '---------\nif-check verification failures:\n', + IF_CHECK_FAILED: (filename: string) => + `✖ if-check could not verify ${filename}. The re-executed file does not match the original.\n`, + IF_CHECK_VERIFIED: (filename: string) => + `✔ if-check successfully verified ${filename}\n`, + IF_CHECK_SUMMARY_ERROR_MESSAGE: (filename: string, message: string) => + `Executing \`${filename}\`\n✖ ${message}`, + IF_CHECK_SUMMARY_LOG: (passedCount: number, totalCount: number) => + `---------\nCheck summary:\n${passedCount} of ${totalCount} files are passed.\n`, + ZERO_DIVISION: (moduleName: string, index: number) => + `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, }; diff --git a/src/diff.ts b/src/diff.ts index 7deb09e35..aad02482c 100644 --- a/src/diff.ts +++ b/src/diff.ts @@ -4,21 +4,28 @@ import {loadIfDiffFiles} from './lib/load'; import {compare} from './lib/compare'; import {parseIfDiffArgs} from './util/args'; -import {formatNotMatchingLog} from './util/helpers'; +import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; import {validateManifest} from './util/validations'; -import {CONFIG} from './config'; import {logger} from './util/logger'; +import {debugLogger} from './util/debug-logger'; + +import {CONFIG} from './config'; const {IF_DIFF} = CONFIG; const {SUCCESS_MESSAGE, FAILURE_MESSAGE} = IF_DIFF; const IfDiff = async () => { + const pipedSourceManifest = await parseManifestFromStdin(); const {sourcePath, targetPath} = parseIfDiffArgs(); + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + const {rawSourceManifest, rawTargetManifest} = await loadIfDiffFiles({ targetPath, sourcePath, + pipedSourceManifest, }); const [sourceManifest, targetManifest] = [ rawSourceManifest, diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 000000000..48b0b76b9 --- /dev/null +++ b/src/env.ts @@ -0,0 +1,50 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import {parseIfEnvArgs} from './util/args'; +import {logger} from './util/logger'; + +import {CONFIG} from './config'; + +import {EnvironmentOptions} from './types/if-env'; +import { + addTemplateManifest, + getOptionsFromArgs, + initializeAndInstallLibs, +} from './util/helpers'; + +const {IF_ENV} = CONFIG; +const {SUCCESS_MESSAGE} = IF_ENV; + +const IfEnv = async () => { + const commandArgs = await parseIfEnvArgs(); + const options: EnvironmentOptions = { + folderPath: process.env.CURRENT_DIR || process.cwd(), + install: !!commandArgs.install, + dependencies: {}, + cwd: !!commandArgs.cwd, + }; + + if (commandArgs && commandArgs.manifest) { + const {folderPath, install, dependencies} = + await getOptionsFromArgs(commandArgs); + options.folderPath = commandArgs.cwd ? options.folderPath : folderPath; + options.install = !!install; + options.dependencies = {...dependencies}; + } + + await initializeAndInstallLibs(options); + + if (!commandArgs || !commandArgs.manifest) { + await addTemplateManifest(options.folderPath); + } + + console.log(SUCCESS_MESSAGE); + process.exit(0); +}; + +IfEnv().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); diff --git a/src/lib/aggregate.ts b/src/lib/aggregate.ts index 977f30300..c6eef11cc 100644 --- a/src/lib/aggregate.ts +++ b/src/lib/aggregate.ts @@ -1,10 +1,11 @@ -import {aggregateInputsIntoOne} from '../util/aggregation-helper'; +import {PluginParams} from '@grnsft/if-core/types'; -import {PluginParams} from '../types/interface'; -import {AggregationParams, AggregationParamsSure} from '../types/manifest'; +import {aggregateInputsIntoOne} from '../util/aggregation-helper'; import {STRINGS} from '../config/strings'; +import {AggregationParams, AggregationParamsSure} from '../types/manifest'; + const {AGGREGATING_NODE, AGGREGATING_OUTPUTS} = STRINGS; /** diff --git a/src/lib/compute.ts b/src/lib/compute.ts index 40db1a42a..b83a22d2e 100644 --- a/src/lib/compute.ts +++ b/src/lib/compute.ts @@ -1,9 +1,10 @@ +import {PluginParams, GroupByConfig} from '@grnsft/if-core/types'; + import {debugLogger} from '../util/debug-logger'; import {mergeObjects} from '../util/helpers'; import {ComputeParams, Node, Params} from '../types/compute'; -import {PluginParams, isExecute, isGroupBy} from '../types/interface'; -import {GroupByConfig} from '../types/group-by'; +import {isExecute, isGroupBy} from '../types/interface'; import {STRINGS} from '../config/strings'; diff --git a/src/lib/exhaust.ts b/src/lib/exhaust.ts index 6bcc9824a..1b65ca898 100644 --- a/src/lib/exhaust.ts +++ b/src/lib/exhaust.ts @@ -1,3 +1,5 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + /** * @todo This is temporary solution, will be refactored to support dynamic plugins. */ @@ -6,15 +8,13 @@ import {ExportCSVRaw} from '../builtins/export-csv-raw'; import {ExportLog} from '../builtins/export-log'; import {ExportYaml} from '../builtins/export-yaml'; -import {ERRORS} from '../util/errors'; - import {STRINGS} from '../config'; import {ExhaustPluginInterface} from '../types/exhaust-plugin-interface'; import {Context} from '../types/manifest'; import {Options} from '../types/process-args'; -const {ExhaustError} = ERRORS; +const {InvalidExhaustPluginError} = ERRORS; const {INVALID_EXHAUST_PLUGIN, PREPARING_OUTPUT_DATA} = STRINGS; /** @@ -35,7 +35,7 @@ const initializeExhaustPlugin = (name: string): ExhaustPluginInterface => { case 'csv-raw': return ExportCSVRaw(); default: - throw new ExhaustError(INVALID_EXHAUST_PLUGIN(name)); + throw new InvalidExhaustPluginError(INVALID_EXHAUST_PLUGIN(name)); } }; diff --git a/src/lib/initialize.ts b/src/lib/initialize.ts index c66e08c28..212d98e37 100644 --- a/src/lib/initialize.ts +++ b/src/lib/initialize.ts @@ -1,6 +1,7 @@ -import pathLib = require('path'); +import * as path from 'node:path'; + +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../util/errors'; import {logger} from '../util/logger'; import {memoizedLog} from '../util/log-memoize'; import {pluginStorage} from '../util/plugin-storage'; @@ -11,7 +12,11 @@ import {PluginInterface} from '../types/interface'; import {GlobalPlugins, PluginOptions} from '../types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; -const {ModuleInitializationError, PluginCredentialError} = ERRORS; +const { + PluginInitializationError, + MissingPluginMethodError, + MissingPluginPathError, +} = ERRORS; const {GITHUB_PATH, NATIVE_PLUGIN} = CONFIG; const { @@ -28,14 +33,11 @@ const { * Imports module by given `path`. */ const importModuleFrom = async (path: string) => { - try { - const module = await import(path); + const module = await import(path).catch(error => { + throw new PluginInitializationError(INVALID_MODULE_PATH(path, error)); + }); - return module; - } catch (error) { - logger.error(error); - throw new ModuleInitializationError(INVALID_MODULE_PATH(path)); - } + return module; }; /** @@ -52,23 +54,23 @@ const importAndVerifyModule = async (method: string, path: string) => { * Then checks if `path` is starting with github, then grabs the repository name. * Imports module, then checks if it's a valid plugin. */ -const handModule = (method: string, path: string) => { - console.debug(LOADING_PLUGIN_FROM_PATH(method, path)); +const handModule = (method: string, pluginPath: string) => { + console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath)); - if (path === 'builtin') { - path = pathLib.normalize(`${__dirname}/../builtins`); + if (pluginPath === 'builtin') { + pluginPath = path.normalize(`${__dirname}/../builtins`); } else { - if (path?.startsWith(GITHUB_PATH)) { - const parts = path.split('/'); - path = parts[parts.length - 1]; + if (pluginPath?.startsWith(GITHUB_PATH)) { + const parts = pluginPath.split('/'); + pluginPath = parts[parts.length - 1]; } - if (!path.includes(NATIVE_PLUGIN)) { - memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(path)); + if (!pluginPath.includes(NATIVE_PLUGIN)) { + memoizedLog(logger.warn, NOT_NATIVE_PLUGIN(pluginPath)); } } - return importAndVerifyModule(method, path); + return importAndVerifyModule(method, pluginPath); }; /** @@ -82,11 +84,11 @@ const initPlugin = async ( console.debug(INITIALIZING_PLUGIN(method)); if (!method) { - throw new PluginCredentialError(MISSING_METHOD); + throw new MissingPluginMethodError(MISSING_METHOD); } if (!path) { - throw new PluginCredentialError(MISSING_PATH); + throw new MissingPluginPathError(MISSING_PATH); } const plugin = await handModule(method, path); diff --git a/src/lib/load.ts b/src/lib/load.ts index 9b9508ded..61f2b6cf5 100644 --- a/src/lib/load.ts +++ b/src/lib/load.ts @@ -1,9 +1,8 @@ import * as YAML from 'js-yaml'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from '../util/errors'; import {openYamlFileAsObject} from '../util/yaml'; import {readAndParseJson} from '../util/json'; -import {parseManifestFromStdin} from '../util/helpers'; import {PARAMETERS} from '../config'; import {STRINGS} from '../config'; @@ -12,7 +11,7 @@ import {Parameters} from '../types/parameters'; import {LoadDiffParams} from '../types/util/args'; import {Manifest} from '../types/manifest'; -const {CliInputError} = ERRORS; +const {CliSourceFileError} = ERRORS; const {INVALID_SOURCE, LOADING_MANIFEST} = STRINGS; @@ -41,11 +40,10 @@ export const load = async (inputPath: string, paramPath?: string) => { * Loads files to compare. As a source file checks if data is piped and then decides which one to take. */ export const loadIfDiffFiles = async (params: LoadDiffParams) => { - const {sourcePath, targetPath} = params; - const pipedSourceManifest = await parseManifestFromStdin(); + const {sourcePath, targetPath, pipedSourceManifest} = params; if (!sourcePath && !pipedSourceManifest) { - throw new CliInputError(INVALID_SOURCE); + throw new CliSourceFileError(INVALID_SOURCE); } const loadFromSource = diff --git a/src/types/common.ts b/src/types/common.ts deleted file mode 100644 index f7d337392..000000000 --- a/src/types/common.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type KeyValuePair = { - [key: string]: any; -}; - -export type ConfigParams = Record; diff --git a/src/types/compute.ts b/src/types/compute.ts index 739d86742..2de3e6e33 100644 --- a/src/types/compute.ts +++ b/src/types/compute.ts @@ -1,4 +1,5 @@ -import {PluginParams} from './interface'; +import {PluginParams} from '@grnsft/if-core/types'; + import {Context} from './manifest'; import {PluginStorageInterface} from './plugin-storage'; diff --git a/src/types/group-by.ts b/src/types/group-by.ts deleted file mode 100644 index 72dd6d61b..000000000 --- a/src/types/group-by.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type GroupByConfig = { - group: string[]; -}; diff --git a/src/types/helpers.ts b/src/types/helpers.ts deleted file mode 100644 index ed413174b..000000000 --- a/src/types/helpers.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type ErrorFormatParams = { - scope?: string; - message: string; -}; diff --git a/src/types/if-env.ts b/src/types/if-env.ts new file mode 100644 index 000000000..03ace8ec9 --- /dev/null +++ b/src/types/if-env.ts @@ -0,0 +1,6 @@ +export type EnvironmentOptions = { + folderPath: string; + install: boolean; + cwd: boolean; + dependencies: {[path: string]: string}; +}; diff --git a/src/types/interface.ts b/src/types/interface.ts index f06449bc6..6834a3ebb 100644 --- a/src/types/interface.ts +++ b/src/types/interface.ts @@ -1,27 +1,4 @@ -import {GroupByConfig} from './group-by'; - -export type PluginParams = Record; - -export type ConfigParams = Record; - -export type ExecutePlugin = { - execute: ( - inputs: PluginParams[], - config?: Record - ) => PluginParams[] | Promise; - metadata: { - kind: string; - }; - [key: string]: any; -}; - -export type GroupByPlugin = { - execute: (inputs: PluginParams[], config: GroupByConfig) => {children: any}; - metadata: { - kind: string; - }; - [key: string]: any; -}; +import {ExecutePlugin, GroupByPlugin} from '@grnsft/if-core/types'; export type PluginInterface = ExecutePlugin | GroupByPlugin; diff --git a/src/types/npm.ts b/src/types/npm.ts new file mode 100644 index 000000000..cbb3e0680 --- /dev/null +++ b/src/types/npm.ts @@ -0,0 +1,3 @@ +export type PathWithVersion = {[path: string]: string}; + +export type ManifestPlugin = {[key: string]: {path: string; method: string}}; diff --git a/src/types/process-args.ts b/src/types/process-args.ts index 1a637082f..0f3799f5a 100644 --- a/src/types/process-args.ts +++ b/src/types/process-args.ts @@ -11,6 +11,17 @@ export interface IFDiffArgs { target: string; } +export interface IFEnvArgs { + manifest?: string; + install?: boolean; + cwd?: boolean; +} + +export interface IFCheckArgs { + manifest?: string; + directory?: string; +} + export interface Options { outputPath?: string; stdout?: boolean; diff --git a/src/types/util/args.ts b/src/types/util/args.ts index d9debf3cd..ae78fa4d0 100644 --- a/src/types/util/args.ts +++ b/src/types/util/args.ts @@ -1,4 +1,5 @@ export type LoadDiffParams = { sourcePath?: string; targetPath: string; + pipedSourceManifest?: string; }; diff --git a/src/util/aggregation-helper.ts b/src/util/aggregation-helper.ts index 3be503ffc..408a4e9f7 100644 --- a/src/util/aggregation-helper.ts +++ b/src/util/aggregation-helper.ts @@ -1,12 +1,13 @@ -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + import {parameterize} from '../lib/parameterize'; import {CONFIG, STRINGS} from '../config'; import {AggregationResult} from '../types/aggregation'; -import {PluginParams} from '../types/interface'; -const {InvalidAggregationParamsError} = ERRORS; +const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; @@ -19,7 +20,7 @@ const checkIfMetricsAreValid = (metrics: string[]) => { const method = parameterize.getAggregationMethod(metric); if (method === 'none') { - throw new InvalidAggregationParamsError( + throw new InvalidAggregationMethodError( INVALID_AGGREGATION_METHOD(metric) ); } @@ -41,7 +42,7 @@ export const aggregateInputsIntoOne = ( return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { if (!(metric in input)) { - throw new InvalidAggregationParamsError(METRIC_MISSING(metric, index)); + throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); } /** Checks if metric is timestamp or duration, then adds to aggregated value. */ diff --git a/src/util/args.ts b/src/util/args.ts index dfbd7e703..31da90461 100644 --- a/src/util/args.ts +++ b/src/util/args.ts @@ -1,26 +1,44 @@ import * as path from 'path'; + import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; import {checkIfFileIsYaml} from './yaml'; -import {ERRORS} from './errors'; + +import {isDirectoryExists, isFileExists} from './fs'; + import {logger} from './logger'; import {CONFIG, STRINGS} from '../config'; -import {IFDiffArgs, IEArgs, ProcessArgsOutputs} from '../types/process-args'; +import { + IFDiffArgs, + IEArgs, + ProcessArgsOutputs, + IFEnvArgs, + IFCheckArgs, +} from '../types/process-args'; import {LoadDiffParams} from '../types/util/args'; -const {CliInputError} = ERRORS; +const { + ParseCliParamsError, + CliTargetFileError, + CliSourceFileError, + InvalidDirectoryError, + MissingCliFlagsError, +} = ERRORS; -const {IE, IF_DIFF} = CONFIG; +const {IE, IF_DIFF, IF_ENV, IF_CHECK} = CONFIG; const { - FILE_IS_NOT_YAML, MANIFEST_IS_MISSING, + MANIFEST_NOT_FOUND, NO_OUTPUT, SOURCE_IS_NOT_YAML, TARGET_IS_NOT_YAML, INVALID_TARGET, + IF_CHECK_FLAGS_MISSING, + DIRECTORY_NOT_FOUND, } = STRINGS; /** @@ -31,7 +49,7 @@ const validateAndParseProcessArgs = () => { return parse(IE.ARGS, IE.HELP); } catch (error) { if (error instanceof Error) { - throw new CliInputError(error.message); + throw new ParseCliParamsError(error.message); } throw error; @@ -57,7 +75,7 @@ const prependFullFilePath = (filePath: string) => { * 3. If output params are missing, warns user about it. * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. * If it is, then returns object containing full path. - * 4. If params are missing or invalid, then rejects with `CliInputError`. + * 4. If params are missing or invalid, then rejects with `ParseCliParamsError`. */ export const parseIEProcessArgs = (): ProcessArgsOutputs => { const { @@ -85,10 +103,10 @@ export const parseIEProcessArgs = (): ProcessArgsOutputs => { }; } - throw new CliInputError(FILE_IS_NOT_YAML); + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); } - throw new CliInputError(MANIFEST_IS_MISSING); + throw new CliSourceFileError(MANIFEST_IS_MISSING); }; /** -- IF Diff -- */ @@ -101,7 +119,7 @@ const validateAndParseIfDiffArgs = () => { return parse(IF_DIFF.ARGS, IF_DIFF.HELP); } catch (error) { if (error instanceof Error) { - throw new CliInputError(error.message); + throw new ParseCliParamsError(error.message); } throw error; @@ -116,7 +134,7 @@ export const parseIfDiffArgs = () => { if (target) { if (source && !checkIfFileIsYaml(source)) { - throw new CliInputError(SOURCE_IS_NOT_YAML); + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); } if (checkIfFileIsYaml(target)) { @@ -131,8 +149,100 @@ export const parseIfDiffArgs = () => { return response; } - throw new CliInputError(TARGET_IS_NOT_YAML); + throw new CliTargetFileError(TARGET_IS_NOT_YAML); + } + + throw new ParseCliParamsError(INVALID_TARGET); +}; + +/** -- IF Env -- */ + +/** + * Parses `if-env` process arguments. + */ +const validateAndParseIfEnvArgs = () => { + try { + return parse(IF_ENV.ARGS, IF_ENV.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if the `manifest` command is provided and it is valid manifest file. + */ +export const parseIfEnvArgs = async () => { + const {manifest, install, cwd} = validateAndParseIfEnvArgs(); + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest: response, install, cwd}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + return {install, cwd}; +}; + +/** -- IF Check -- */ + +/** + * Parses `if-check` process arguments. + */ +const validateAndParseIfCheckArgs = () => { + try { + return parse(IF_CHECK.ARGS, IF_CHECK.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if either `manifest` or `directory` command is provided. + */ +export const parseIfCheckArgs = async () => { + const {manifest, directory} = validateAndParseIfCheckArgs(); + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } else if (directory) { + const isDirExists = await isDirectoryExists(directory); + + if (!isDirExists) { + throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); + } + + const response = prependFullFilePath(directory); + + return {directory: response}; } - throw new CliInputError(INVALID_TARGET); + throw new MissingCliFlagsError(IF_CHECK_FLAGS_MISSING); }; diff --git a/src/util/debug-logger.ts b/src/util/debug-logger.ts index 1a2481b16..f1f34ae0e 100644 --- a/src/util/debug-logger.ts +++ b/src/util/debug-logger.ts @@ -81,14 +81,16 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { return; } - const isDebugLog = logMessagesKeys.some(key => { - const message = - typeof STRINGS[key] === 'function' - ? (STRINGS[key] as Function).call(null, '') - : (STRINGS[key] as string); - - return args[0].includes(message); - }); + const isDebugLog = + typeof args[0] === 'string' && + logMessagesKeys.some(key => { + const message = + typeof STRINGS[key] === 'function' + ? (STRINGS[key] as Function).call(null, '') + : (STRINGS[key] as string); + + return args[0].includes(message); + }); if (!isDebugLog) { originalConsole.log(...args); diff --git a/src/util/errors.ts b/src/util/errors.ts deleted file mode 100644 index a65a603be..000000000 --- a/src/util/errors.ts +++ /dev/null @@ -1,35 +0,0 @@ -const CUSTOM_ERRORS = [ - 'CliInputError', - 'ConfigNotFoundError', - 'ConfigValidationError', - 'ExhaustError', - 'FileNotFoundError', - 'MakeDirectoryError', - 'ManifestValidationError', - 'ModuleInitializationError', - 'InputValidationError', - 'InvalidAggregationParamsError', - 'InvalidGroupingError', - 'PluginCredentialError', - 'PluginInitalizationError', - 'WriteFileError', - 'ConfigNotFoundError', -] as const; - -type CustomErrors = { - [K in (typeof CUSTOM_ERRORS)[number]]: ErrorConstructor; -}; - -export const ERRORS = CUSTOM_ERRORS.reduce((acc, className) => { - acc = { - ...acc, - [className]: class extends Error { - constructor(message: string) { - super(message); - this.name = this.constructor.name; - } - }, - }; - - return acc; -}, {} as CustomErrors); diff --git a/src/util/fs.ts b/src/util/fs.ts new file mode 100644 index 000000000..bf10af9ba --- /dev/null +++ b/src/util/fs.ts @@ -0,0 +1,68 @@ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +/** + * Checks if file exists with the given `filePath`. + */ +export const isFileExists = async (filePath: string) => { + try { + await fs.stat(filePath); + return true; + } catch (error) { + return false; + } +}; + +/** + * Checks if the directory exists with the given `filePath`. + */ +export const isDirectoryExists = async (directoryPath: string) => { + try { + await fs.access(directoryPath); + return true; + } catch (error) { + return false; + } +}; + +/** + * Gets all files that have either .yml or .yaml extension in the given directory. + */ +export const getYamlFiles = async (directory: string) => { + let yamlFiles: string[] = []; + + const files = await fs.readdir(directory); + + for (const file of files) { + const fullPath = path.join(directory, file); + const stat = await fs.lstat(fullPath); + + if (stat.isDirectory()) { + yamlFiles = yamlFiles.concat(await getYamlFiles(fullPath)); + } else { + if (file.endsWith('.yml') || file.endsWith('.yaml')) { + yamlFiles.push(fullPath); + } + } + } + + return yamlFiles; +}; + +/** + * Gets fileName from the given path without an extension. + */ +export const getFileName = (filePath: string) => { + const baseName = path.basename(filePath); + const extension = path.extname(filePath); + return baseName.replace(extension, ''); +}; + +/** + * Removes the given file if exists. + */ +export const removeFileIfExists = async (filePath: string) => { + if (await isFileExists(filePath)) { + await fs.unlink(filePath); + } +}; diff --git a/src/util/helpers.ts b/src/util/helpers.ts index b15863cef..c55b43724 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -1,24 +1,41 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ import {createInterface} from 'node:readline/promises'; import {exec} from 'node:child_process'; import {promisify} from 'node:util'; -import {ErrorFormatParams} from '../types/helpers'; -import {ERRORS} from './errors'; -import {logger} from './logger'; -import {STRINGS} from '../config'; + +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS, CONFIG} from '../config'; import {Difference} from '../types/lib/compare'; -const {ISSUE_TEMPLATE} = STRINGS; +import {load} from '../lib/load'; -/** - * Formats given error according to class instance, scope and message. - */ -export const buildErrorMessage = - (classInstanceName: string) => (params: ErrorFormatParams) => { - const {scope, message} = params; +import { + installDependencies, + initPackageJsonIfNotExists, + updatePackageJsonDependencies, + extractPathsWithVersion, + updatePackageJsonProperties, +} from './npm'; - return `${classInstanceName}${scope ? `(${scope})` : ''}: ${message}.`; - }; +import {logger} from './logger'; +import {EnvironmentOptions} from '../types/if-env'; + +const {IF_ENV} = CONFIG; +const { + FAILURE_MESSAGE, + FAILURE_MESSAGE_TEMPLATE, + FAILURE_MESSAGE_DEPENDENCIES, +} = IF_ENV; + +const {UNSUPPORTED_ERROR, IF_CHECK_FAILED, IF_CHECK_SUMMARY_ERROR_MESSAGE} = + STRINGS; +const {MissingPluginDependenciesError} = ERRORS; /** * Impact engine error handler. Logs errors and appends issue template if error is unknown. @@ -29,7 +46,9 @@ export const andHandle = (error: Error) => { logger.error(error); if (!knownErrors.includes(error.name)) { - logger.warn(ISSUE_TEMPLATE); + logger.error(UNSUPPORTED_ERROR(error.name)); + // eslint-disable-next-line no-process-exit + process.exit(2); } }; @@ -164,7 +183,7 @@ const collectPipedData = async () => { /** * Checks if there is piped data, tries to parse yaml from it. - * Throws error if there is piped info, but there is no valid manifest. + * Returns empty string if haven't found anything. */ export const parseManifestFromStdin = async () => { const pipedSourceManifest = await collectPipedData(); @@ -177,8 +196,90 @@ export const parseManifestFromStdin = async () => { const match = regex.exec(pipedSourceManifest); if (!match) { - throw new Error('Manifest not found in STDIN.'); + return ''; } return match![1]; }; + +/** + * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + */ +export const getOptionsFromArgs = async (commandArgs: { + manifest: string; + install: boolean | undefined; +}) => { + const {manifest, install} = commandArgs; + const folderPath = path.dirname(manifest); + const loadedManifest = await load(manifest); + const rawManifest = loadedManifest.rawManifest; + const plugins = rawManifest?.initialize?.plugins || {}; + const dependencies = rawManifest?.execution?.environment.dependencies || []; + + if (!dependencies.length) { + throw new MissingPluginDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); + } + + const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); + + return { + folderPath, + dependencies: pathsWithVersion, + install, + }; +}; + +/** + * Creates folder if not exists, installs dependencies if required, update depenedencies. + */ +export const initializeAndInstallLibs = async (options: EnvironmentOptions) => { + try { + const {folderPath, install, cwd, dependencies} = options; + const packageJsonPath = await initPackageJsonIfNotExists(folderPath); + + await updatePackageJsonProperties(packageJsonPath, cwd); + + if (install) { + await installDependencies(folderPath, dependencies); + } else { + await updatePackageJsonDependencies(packageJsonPath, dependencies, cwd); + } + } catch (error) { + console.log(FAILURE_MESSAGE); + process.exit(2); + } +}; + +/** + * Adds a manifest template to the folder where the if-env CLI command runs. + */ +export const addTemplateManifest = async (destinationDir: string) => { + try { + const templateManifest = path.resolve( + __dirname, + '../config/env-template.yml' + ); + + const destinationPath = path.resolve(destinationDir, 'manifest.yml'); + const data = await fs.readFile(templateManifest, 'utf-8'); + + await fs.writeFile(destinationPath, data, 'utf-8'); + } catch (error) { + console.log(FAILURE_MESSAGE_TEMPLATE); + process.exit(1); + } +}; + +/** + * Logs the failure message from the stdout of an error. + */ +export const logStdoutFailMessage = (error: any, fileName: string) => { + console.log(IF_CHECK_FAILED(fileName)); + + const stdout = error.stdout; + const logs = stdout.split('\n\n'); + const failMessage = logs[logs.length - 1]; + + console.log(failMessage); + return IF_CHECK_SUMMARY_ERROR_MESSAGE(fileName, failMessage); +}; diff --git a/src/util/npm.ts b/src/util/npm.ts new file mode 100644 index 000000000..de27ae4de --- /dev/null +++ b/src/util/npm.ts @@ -0,0 +1,193 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as fs from 'fs/promises'; +import * as path from 'path'; + +import {execPromise} from './helpers'; +import { + isDirectoryExists, + getFileName, + isFileExists, + removeFileIfExists, +} from './fs'; +import {logger} from './logger'; + +import {STRINGS} from '../config'; +import {ManifestPlugin, PathWithVersion} from '../types/npm'; + +const packageJson = require('../../package.json'); + +const {INITIALIZING_PACKAGE_JSON, INSTALLING_NPM_PACKAGES, IF_CHECK_VERIFIED} = + STRINGS; + +/** + * Checks if the package.json is exists, if not, initializes it. + */ +export const initPackageJsonIfNotExists = async (folderPath: string) => { + const packageJsonPath = path.resolve(folderPath, 'package.json'); + const isPackageJsonExists = await isFileExists(packageJsonPath); + + if (!isPackageJsonExists) { + logger.info(INITIALIZING_PACKAGE_JSON); + + const nodeModulesPath = path.resolve(folderPath, 'node_modules'); + const isNodeModulesExists = await isDirectoryExists(nodeModulesPath); + + if (isNodeModulesExists) { + await fs.rm(nodeModulesPath, {recursive: true}); + } + + await execPromise('npm init -y', {cwd: folderPath}); + } + + return packageJsonPath; +}; + +/** + * Installs packages from the specified dependencies in the specified folder. + */ +export const installDependencies = async ( + folderPath: string, + dependencies: {[path: string]: string} +) => { + const packages = Object.entries(dependencies).map( + ([dependency, version]) => `${dependency}@${version.replace('^', '')}` + ); + + logger.info(INSTALLING_NPM_PACKAGES); + await execPromise(`npm install ${packages.join(' ')}`, { + cwd: folderPath, + }); +}; + +/** + * Updates package.json dependencies. + */ +export const updatePackageJsonDependencies = async ( + packageJsonPath: string, + dependencies: PathWithVersion, + cwd: boolean +) => { + const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); + + const parsedPackageJson = JSON.parse(packageJsonContent); + + if (cwd) { + parsedPackageJson.dependencies = { + ...parsedPackageJson.dependencies, + ...dependencies, + }; + } else { + parsedPackageJson.dependencies = {...dependencies}; + } + + await fs.writeFile( + packageJsonPath, + JSON.stringify(parsedPackageJson, null, 2) + ); +}; + +/** + * Gets depencecies with versions. + */ +export const extractPathsWithVersion = ( + plugins: ManifestPlugin, + dependencies: string[] +) => { + const paths = Object.keys(plugins).map(plugin => plugins[plugin].path); + const uniquePaths = [...new Set(paths)].filter(path => path !== 'builtin'); + const pathsWithVersion: PathWithVersion = {}; + + uniquePaths.forEach(pluginPath => { + const dependency = dependencies.find((dependency: string) => + dependency.startsWith(pluginPath) + ); + + if (dependency) { + const splittedDependency = dependency.split('@'); + const version = + splittedDependency.length > 2 + ? splittedDependency[2].split(' ')[0] + : splittedDependency[1]; + + pathsWithVersion[pluginPath] = `^${version}`; + } + }); + + return pathsWithVersion; +}; + +/** + * Update the package.json properties. + */ +export const updatePackageJsonProperties = async ( + newPackageJsonPath: string, + appendDependencies: boolean +) => { + const packageJsonContent = await fs.readFile(newPackageJsonPath, 'utf8'); + const parsedPackageJsonContent = JSON.parse(packageJsonContent); + + const properties = { + name: 'if-environment', + description: packageJson.description, + author: packageJson.author, + bugs: packageJson.bugs, + engines: packageJson.engines, + homepage: packageJson.homepage, + dependencies: appendDependencies + ? parsedPackageJsonContent.dependencies + : {}, + }; + + const newPackageJson = Object.assign( + {}, + parsedPackageJsonContent, + properties + ); + + await fs.writeFile( + newPackageJsonPath, + JSON.stringify(newPackageJson, null, 2) + ); +}; + +/** + * Executes a series of npm commands based on the provided manifest file. + */ +export const executeCommands = async (manifest: string, cwd: boolean) => { + // TODO: After release remove isGlobal and appropriate checks + const isGlobal = !!process.env.npm_config_global; + const manifestDirPath = path.dirname(manifest); + const manifestFileName = getFileName(manifest); + const executedManifest = path.join(manifestDirPath, `re-${manifestFileName}`); + const prefixFlag = + process.env.CURRENT_DIR && process.env.CURRENT_DIR !== process.cwd() + ? `--prefix=${path.relative(process.env.CURRENT_DIR!, process.cwd())}` + : ''; + const ifEnv = `${ + isGlobal ? `if-env ${prefixFlag}` : `npm run if-env ${prefixFlag} --` + } -m ${manifest}`; + const ifEnvCommand = cwd ? `${ifEnv} -c` : ifEnv; + const ifRunCommand = `${ + isGlobal ? `if-run ${prefixFlag}` : `npm run if-run ${prefixFlag} --` + } -m ${manifest} -o ${executedManifest}`; + const ifDiffCommand = `${ + isGlobal ? `if-diff ${prefixFlag}` : `npm run if-diff ${prefixFlag} --` + } -s ${executedManifest}.yaml -t ${manifest}`; + const ttyCommand = " node -p 'Boolean(process.stdout.isTTY)'"; + + await execPromise( + `${ifEnvCommand} && ${ifRunCommand} && ${ttyCommand} | ${ifDiffCommand}`, + { + cwd: process.env.CURRENT_DIR || process.cwd(), + } + ); + + if (!cwd) { + await removeFileIfExists(`${manifestDirPath}/package.json`); + } + + await removeFileIfExists(`${executedManifest}.yaml`); + + console.log(IF_CHECK_VERIFIED(path.basename(manifest))); +}; diff --git a/src/util/plugin-storage.ts b/src/util/plugin-storage.ts index 7667d5e07..1f9711943 100644 --- a/src/util/plugin-storage.ts +++ b/src/util/plugin-storage.ts @@ -1,10 +1,11 @@ -import {ERRORS} from '../util/errors'; +import {ERRORS} from '@grnsft/if-core/utils'; + import {STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; import {PluginStorage} from '../types/plugin-storage'; -const {PluginInitalizationError} = ERRORS; +const {PluginInitializationError} = ERRORS; const {NOT_INITALIZED_PLUGIN} = STRINGS; /** @@ -21,7 +22,7 @@ export const pluginStorage = () => { const plugin = storage[name]; if (!plugin) { - throw new PluginInitalizationError(NOT_INITALIZED_PLUGIN(name)); + throw new PluginInitializationError(NOT_INITALIZED_PLUGIN(name)); } return plugin; diff --git a/src/util/validations.ts b/src/util/validations.ts index 3cd1dd6b9..920e7cbdb 100644 --- a/src/util/validations.ts +++ b/src/util/validations.ts @@ -1,14 +1,14 @@ import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; -import {ERRORS} from './errors'; +import {STRINGS} from '../config/strings'; import {AGGREGATION_METHODS} from '../types/aggregation'; import {AGGREGATION_TYPES} from '../types/parameters'; -import {STRINGS} from '../config/strings'; - const {ManifestValidationError, InputValidationError} = ERRORS; const {VALIDATING_MANIFEST} = STRINGS; + /** * At least one property defined handler. */ @@ -148,5 +148,6 @@ const flattenPath = (path: (string | number)[]): string => { const flattenPath = path.map(part => typeof part === 'number' ? `[${part}]` : part ); + return flattenPath.join('.'); }; From a461cdf5c3d82e43d95af20d1de3a8107a2d56cf Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 23:39:38 +0400 Subject: [PATCH 346/863] revert(.github): remove integration test from nodejs ci --- .github/workflows/nodejs-ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/nodejs-ci.yml b/.github/workflows/nodejs-ci.yml index 306833939..fac415dc3 100644 --- a/.github/workflows/nodejs-ci.yml +++ b/.github/workflows/nodejs-ci.yml @@ -21,6 +21,3 @@ jobs: - name: Run unit tests run: npm run test --silent - - - name: Run integration tests - run: npm run if-check -- -d outputs From e1b0984855a7bee1526f4179a3b9e992a2db7b30 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 23:40:34 +0400 Subject: [PATCH 347/863] feat(.github): add integration tests to release commit and publish --- .github/workflows/release-commit.yml | 4 ++-- .github/workflows/release-publish.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-commit.yml b/.github/workflows/release-commit.yml index ddc87cd69..58b862e2d 100644 --- a/.github/workflows/release-commit.yml +++ b/.github/workflows/release-commit.yml @@ -28,8 +28,8 @@ jobs: - name: Run unit tests run: npm test - - name: Install dependencies - run: npm ci + - name: Run integration tests + run: npm run if-check -- -d outputs - name: Initialize git user email run: git config --global user.email "${{ vars.RELEASE_USER_EMAIL }}" diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 146c77c87..9243d9ff7 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -23,8 +23,8 @@ jobs: - name: Run unit tests run: npm test - - name: Install dependencies - run: npm ci + - name: Run integration tests + run: npm run if-check -- -d outputs - name: Initialize git user email run: git config --global user.email "${{ env.RELEASE_USER_EMAIL }}" From 73e01a84cd6f05ab1a6f9e2e1c6e7ea9c71e72a1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 23:43:29 +0400 Subject: [PATCH 348/863] fix(config): add success message to if diff --- src/if-diff/config/strings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-diff/config/strings.ts b/src/if-diff/config/strings.ts index 19154d8dd..0222ca105 100644 --- a/src/if-diff/config/strings.ts +++ b/src/if-diff/config/strings.ts @@ -2,4 +2,5 @@ export const STRINGS = { INVALID_TARGET: 'Target is invalid.', INVALID_SOURCE: 'Source is invalid.', FAILURE_MESSAGE: 'Files do not match!', + SUCCESS_MESSAGE: 'Files match!', }; From 3faef74e6b4e87395369cb014c1fe590f18ef0ab Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 5 Jul 2024 23:44:11 +0400 Subject: [PATCH 349/863] fix(src): use updated success message --- src/if-diff/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/if-diff/index.ts b/src/if-diff/index.ts index fc367330b..52a6a9b4e 100644 --- a/src/if-diff/index.ts +++ b/src/if-diff/index.ts @@ -11,10 +11,8 @@ import {logger} from '../common/util/logger'; import {debugLogger} from '../common/util/debug-logger'; import {STRINGS} from './config'; -import {STRINGS as COMMON_STRINGS} from '../common/config'; -const {FAILURE_MESSAGE} = STRINGS; -const {SUCCESS_MESSAGE} = COMMON_STRINGS; +const {FAILURE_MESSAGE, SUCCESS_MESSAGE} = STRINGS; const IfDiff = async () => { const pipedSourceManifest = await parseManifestFromStdin(); From 9ed63ee4c9e3464b677a9cd56c5fc60d12fa729b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sat, 6 Jul 2024 09:13:01 +0400 Subject: [PATCH 350/863] revert(manifests): remove ones with validation problem --- .../bugs/initialize-error-no-config.yaml | 78 ---------------- .../bugs/initialize-error-no-path.yaml | 91 ------------------- .../bugs/initialize-error-no-plugins.yaml | 74 --------------- 3 files changed, 243 deletions(-) delete mode 100644 manifests/outputs/bugs/initialize-error-no-config.yaml delete mode 100644 manifests/outputs/bugs/initialize-error-no-path.yaml delete mode 100644 manifests/outputs/bugs/initialize-error-no-plugins.yaml diff --git a/manifests/outputs/bugs/initialize-error-no-config.yaml b/manifests/outputs/bugs/initialize-error-no-config.yaml deleted file mode 100644 index 56be9add7..000000000 --- a/manifests/outputs/bugs/initialize-error-no-config.yaml +++ /dev/null @@ -1,78 +0,0 @@ -name: initialize-error-no-config -description: >- - a negative test case that fails due to plugin initialization missing some - required config -tags: null -initialize: - outputs: - - yaml - plugins: - interpolate: - method: Interpolation - path: builtin - global-config: null -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-config.yml -o - manifests/outputs/bugs/initialize-error-no-config - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:45:41.936Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.interpolate.global-config" - parameter is expected object, received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-path.yaml b/manifests/outputs/bugs/initialize-error-no-path.yaml deleted file mode 100644 index e2ee4d616..000000000 --- a/manifests/outputs/bugs/initialize-error-no-path.yaml +++ /dev/null @@ -1,91 +0,0 @@ -name: initialize-error-no-path -description: >- - a negative test case that fails because the path is mising in a plugin - initialization -tags: null -initialize: - plugins: - interpolate: - method: Interpolation - path: null - 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-factor - outputs: - - yaml -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-path.yml -o - manifests/outputs/bugs/initialize-error-no-path - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:57:11.499Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.interpolate.path" parameter is - expected string, received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - interpolate - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 diff --git a/manifests/outputs/bugs/initialize-error-no-plugins.yaml b/manifests/outputs/bugs/initialize-error-no-plugins.yaml deleted file mode 100644 index 208010e00..000000000 --- a/manifests/outputs/bugs/initialize-error-no-plugins.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: initialize-error-no-path -description: >- - a negative test case that fails becuase no plugins are included in the - initialize block -tags: null -initialize: - plugins: null - outputs: - - yaml -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/initialize-error-no-plugins.yml -o - manifests/outputs/bugs/initialize-error-no-plugins - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-01T19:52:35.214Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins" parameter is expected object, - received null. Error code: invalid_type. -tree: - children: - child-0: - defaults: - cpu/thermal-design-power: 100 - pipeline: - - teads-curve - inputs: - - timestamp: 2023-07-06T00:00 - duration: 1 - cpu/utilization: 20 - - timestamp: 2023-07-06T00:01 - duration: 1 - cpu/utilization: 80 - - timestamp: 2023-07-06T00:02 - duration: 1 - cpu/utilization: 20 From 1b2713fb767756c30d4769e34fa9bbbbb6eb2ddc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sat, 6 Jul 2024 11:41:00 +0400 Subject: [PATCH 351/863] chore(manifests): fix manifest updates after rebase --- .../mock-obs-group-by-cloud-meta.yaml | 645 ------------------ .../outputs/pipelines/mock-obs-groupby.yaml | 178 ----- .../failure-invalid-vendor.yaml | 27 - .../outputs/plugins/groupby/success.yaml | 101 --- .../failure-config-start-later-end.yaml | 1 - .../failure-missing-global-config.yaml | 78 --- 6 files changed, 1030 deletions(-) delete mode 100644 manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml delete mode 100644 manifests/outputs/pipelines/mock-obs-groupby.yaml delete mode 100644 manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml delete mode 100644 manifests/outputs/plugins/groupby/success.yaml delete mode 100644 manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml diff --git a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml b/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml deleted file mode 100644 index 5585d4c42..000000000 --- a/manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yaml +++ /dev/null @@ -1,645 +0,0 @@ -name: My Manifest File -description: integration of mock observations, group by and cloud metadata -aggregation: - metrics: - - cpu/utilization - type: both -initialize: - plugins: - group-by: - path: builtin - method: GroupBy - global-config: - input-parameters: - - cpu/energy - - grid/carbon-intensity - output-parameter: carbon - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv - query: - instance-class: cloud/instance-type - output: - - cpu-tdp - mock-observations: - path: builtin - method: MockObservations - global-config: - timestamp-from: 2024-03-05T00:00 - timestamp-to: 2024-03-05T01:00 - duration: 300 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/pipelines/mock-obs-group-by-cloud-meta.yml -o - manifests/outputs/pipelines/mock-obs-group-by-cloud-meta - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T05:21:45.561Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - pipeline: - - mock-observations - - group-by - - cloud-metadata - config: - group-by: - group: - - name - - cloud/instance-type - children: - server-1: - children: - Standard_E64_v3: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 93 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 6 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 6 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 3 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 83 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 85 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 8 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 59 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 55 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 85 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 52 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 54 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 93 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 6 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 6 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 3 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 83 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 85 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 8 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 59 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 55 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 85 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 52 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: eastus - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 54 - cpu-tdp: 270 - aggregated: - cpu/utilization: 49.083333333333336 - outputs: - - cpu/utilization: 93 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: 6 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: 6 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: 3 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: 83 - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: 85 - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: 8 - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: 59 - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: 55 - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: 85 - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: 52 - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: 54 - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: 49.083333333333336 - server-2: - children: - Standard_E64_v3: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 4 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 63 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 38 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 10 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 88 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 81 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 17 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 11 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 76 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 63 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 81 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 74 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 4 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 63 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 38 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 10 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 88 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 81 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 17 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 11 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 76 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 63 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 81 - cpu-tdp: 270 - - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - geolocation: 37.7749,-122.4194 - cloud/vendor: azure - cpu/utilization: 74 - cpu-tdp: 270 - aggregated: - cpu/utilization: 50.5 - outputs: - - cpu/utilization: 4 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: 63 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: 38 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: 10 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: 88 - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: 81 - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: 17 - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: 11 - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: 76 - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: 63 - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: 81 - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: 74 - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: 50.5 - outputs: - - cpu/utilization: 48.5 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - cpu/utilization: 34.5 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - cpu/utilization: 22 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - cpu/utilization: 6.5 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - - cpu/utilization: 85.5 - timestamp: '2024-03-05T00:20:00.000Z' - duration: 300 - - cpu/utilization: 83 - timestamp: '2024-03-05T00:25:00.000Z' - duration: 300 - - cpu/utilization: 12.5 - timestamp: '2024-03-05T00:30:00.000Z' - duration: 300 - - cpu/utilization: 35 - timestamp: '2024-03-05T00:35:00.000Z' - duration: 300 - - cpu/utilization: 65.5 - timestamp: '2024-03-05T00:40:00.000Z' - duration: 300 - - cpu/utilization: 74 - timestamp: '2024-03-05T00:45:00.000Z' - duration: 300 - - cpu/utilization: 66.5 - timestamp: '2024-03-05T00:50:00.000Z' - duration: 300 - - cpu/utilization: 64 - timestamp: '2024-03-05T00:55:00.000Z' - duration: 300 - aggregated: - cpu/utilization: 49.791666666666664 diff --git a/manifests/outputs/pipelines/mock-obs-groupby.yaml b/manifests/outputs/pipelines/mock-obs-groupby.yaml deleted file mode 100644 index 4783dffde..000000000 --- a/manifests/outputs/pipelines/mock-obs-groupby.yaml +++ /dev/null @@ -1,178 +0,0 @@ -name: Mock observations + Group by -description: Integration of `mock observations` + `groupby plugins` -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - global-config: - timestamp-from: '2024-03-05T00:00:00.000Z' - timestamp-to: '2024-03-05T00:01:00.000Z' - duration: 10 - components: - - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - generators: - common: - cloud/vendor: azure - randint: - cpu/utilization: - min: 1 - max: 99 - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/pipelines/mock-obs-groupby.yml -o - manifests/outputs/pipelines/mock-obs-groupby - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T05:27:34.757Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - pipeline: - - mock-observations - - group-by - defaults: null - config: - group-by: - group: - - cloud/region - - name - children: - westus3: - children: - server-1: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 12 - - timestamp: '2024-03-05T00:00:10.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 71 - - timestamp: '2024-03-05T00:00:20.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 75 - - timestamp: '2024-03-05T00:00:30.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 39 - - timestamp: '2024-03-05T00:00:40.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 42 - - timestamp: '2024-03-05T00:00:50.000Z' - duration: 10 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 98 - france: - children: - server-2: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 14 - - timestamp: '2024-03-05T00:00:10.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 80 - - timestamp: '2024-03-05T00:00:20.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 53 - - timestamp: '2024-03-05T00:00:30.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 10 - - timestamp: '2024-03-05T00:00:40.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 40 - - timestamp: '2024-03-05T00:00:50.000Z' - duration: 10 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 92 diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml deleted file mode 100644 index c474c91fe..000000000 --- a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: cloud-metadata -description: failure with invalid `inputs.cloud/vendor` -tags: -initialize: - #outputs: ['yaml'] - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ['cpu-cores-utilized', 'vcpus-allocated'] -tree: - children: - child: - pipeline: - - cloud-metadata - config: - inputs: - - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred - cloud/vendor: gcp - cloud/instance-type: m5n.large - duration: 100 - cpu/utilization: 10 diff --git a/manifests/outputs/plugins/groupby/success.yaml b/manifests/outputs/plugins/groupby/success.yaml deleted file mode 100644 index 04d54837b..000000000 --- a/manifests/outputs/plugins/groupby/success.yaml +++ /dev/null @@ -1,101 +0,0 @@ -name: groupby -description: successful path -initialize: - plugins: - group-by: - path: builtin - method: GroupBy - outputs: - - yaml -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/groupby/success.yml -o - manifests/outputs/plugins/groupby/success - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T19:08:31.858Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - cloud/instance-type - children: - uk-west: - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml index e0957366a..ae7ec532b 100644 --- a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml +++ b/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml @@ -34,7 +34,6 @@ execution: - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' diff --git a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml deleted file mode 100644 index 79f3bb69e..000000000 --- a/manifests/outputs/plugins/time-sync/failure-missing-global-config.yaml +++ /dev/null @@ -1,78 +0,0 @@ -name: time-sync -description: missing global config -tags: null -initialize: - outputs: - - yaml - plugins: - time-sync: - method: TimeSync - path: builtin - global-config: null -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/time-sync/failure-missing-global-config.yml -o - manifests/outputs/plugins/time-sync/failure-missing-global-config - environment: - if-version: 0.4.0 - os: macOS - os-version: '13.2' - node-version: 18.14.2 - date-time: 2024-07-02T21:13:12.360Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - ManifestValidationError: "initialize.plugins.time-sync.global-config" - parameter is expected object, received null. Error code: invalid_type. -tree: - children: - child: - pipeline: - - time-sync - config: null - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 3 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - energy-cpu: 0.001 From 61201ce5a967d9402c948be8d706d7450006e39a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:27:30 +0400 Subject: [PATCH 352/863] feat(src): add util functions for if-csv --- src/if-csv/util/args.ts | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/if-csv/util/args.ts diff --git a/src/if-csv/util/args.ts b/src/if-csv/util/args.ts new file mode 100644 index 000000000..4b9674882 --- /dev/null +++ b/src/if-csv/util/args.ts @@ -0,0 +1,60 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {checkIfFileIsYaml} from '../../common/util/yaml'; +import {prependFullFilePath} from '../../common/util/helpers'; + +import {CONFIG, STRINGS} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFCsvArgs} from '../types/process-args'; +import {isFileExists} from '../../common/util/fs'; + +const {ParseCliParamsError, CliSourceFileError} = ERRORS; + +const {ARGS, HELP} = CONFIG; +const {PARAMS_NOT_PRESENT} = STRINGS; +const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = COMMON_STRINGS; + +/** + * Parses `if-csv` process arguments. + */ +const validateAndParseIfCsvArgs = () => { + try { + return parse(ARGS, HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks for `manifest` and `params` flags to be present. + */ +export const parseIfCsvArgs = async () => { + const {manifest, output, params} = validateAndParseIfCsvArgs(); + + if (!params) { + throw new ParseCliParamsError(PARAMS_NOT_PRESENT); + } + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest, output, params}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + return {output, params}; +}; From 04a57638c837d6a24d6907508280078b46c69bcc Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:30:16 +0400 Subject: [PATCH 353/863] feat(src): add executeCsv helper function for if-csv --- src/if-csv/util/helpers.ts | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/if-csv/util/helpers.ts diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts new file mode 100644 index 000000000..b70ca2194 --- /dev/null +++ b/src/if-csv/util/helpers.ts @@ -0,0 +1,66 @@ +import {stringify} from 'csv-stringify/sync'; +import * as fs from 'fs/promises'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {CsvOptions} from '../types/csv'; + +/** + * Executes a CSV generation based on the provided tree structure, context, output path, and params. + */ +export const executeCsv = async (options: CsvOptions) => { + const {tree, context, outputPath, params} = options; + const columns = ['Path']; + const matrix = [columns]; + const aggregationIsEnabled = !!context.aggregation; + + const traverseTree = (node: any, params: string, path = 'tree') => { + if (node.aggregated) { + if (path === 'tree') { + columns.push('Aggregated'); + } + matrix.push([`${path}.${params}`, node.aggregated[params]]); + } + + if (node.outputs) { + node.outputs.forEach((output: PluginParams) => { + const {timestamp} = output; + + if (!columns.includes(timestamp)) { + columns.push(timestamp); + } + + const lastRow = matrix[matrix.length - 1]; + + if (aggregationIsEnabled) { + lastRow.push(output[params]); + } else { + if (matrix.length === 1 || lastRow.length === columns.length) { + matrix.push([`${path}.${params}`, output[params]]); + } else { + lastRow.push(output[params]); + } + } + }); + } + + if (node.children) { + Object.keys(node.children).forEach(childKey => { + traverseTree( + node.children![childKey], + params, + `${path}.children.${childKey}` + ); + }); + } + }; + + traverseTree(tree, params); + + const csvString = stringify(matrix, {columns}); + + if (!outputPath) { + return csvString; + } + + return await fs.writeFile(`${outputPath}.csv`, csvString); +}; From 142d957d62ea194bd00b477b81595a939c2c8146 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:33:38 +0400 Subject: [PATCH 354/863] feat(src): move `parseManifestFromStdin` function from if-diff helpers to common helpers file --- src/common/util/helpers.ts | 44 +++++++++++++++++++++++++++++++++++++ src/if-diff/index.ts | 3 ++- src/if-diff/util/helpers.ts | 44 ------------------------------------- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index 8399e5b3e..01b87c79d 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -1,3 +1,4 @@ +import {createInterface} from 'node:readline/promises'; import {exec} from 'child_process'; import * as path from 'path'; import {promisify} from 'util'; @@ -19,3 +20,46 @@ export const prependFullFilePath = (filePath: string) => { return path.normalize(`${processRunningPath}/${filePath}`); }; + +/** + * Checks if there is data piped, then collects it. + * Otherwise returns empty string. + */ +const collectPipedData = async () => { + if (process.stdin.isTTY) { + return ''; + } + + const readline = createInterface({ + input: process.stdin, + }); + + const data: string[] = []; + + for await (const line of readline) { + data.push(line); + } + + return data.join('\n'); +}; + +/** + * Checks if there is piped data, tries to parse yaml from it. + * Returns empty string if haven't found anything. + */ +export const parseManifestFromStdin = async () => { + const pipedSourceManifest = await collectPipedData(); + + if (!pipedSourceManifest) { + return ''; + } + + const regex = /# start((?:.*\n)+?)# end/; + const match = regex.exec(pipedSourceManifest); + + if (!match) { + return ''; + } + + return match![1]; +}; diff --git a/src/if-diff/index.ts b/src/if-diff/index.ts index 52a6a9b4e..aa4ae1871 100644 --- a/src/if-diff/index.ts +++ b/src/if-diff/index.ts @@ -4,7 +4,8 @@ import {loadIfDiffFiles} from './lib/load'; import {compare} from './lib/compare'; import {parseIfDiffArgs} from './util/args'; -import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; +import {formatNotMatchingLog} from './util/helpers'; +import {parseManifestFromStdin} from '../common/util/helpers'; import {validateManifest} from '../common/util/validations'; import {logger} from '../common/util/logger'; diff --git a/src/if-diff/util/helpers.ts b/src/if-diff/util/helpers.ts index 858d5333c..9552e8f5b 100644 --- a/src/if-diff/util/helpers.ts +++ b/src/if-diff/util/helpers.ts @@ -1,4 +1,3 @@ -import {createInterface} from 'node:readline/promises'; import {Difference} from '../types/compare'; /** @@ -83,46 +82,3 @@ export const formatNotMatchingLog = (message: Difference) => { } }); }; - -/** - * Checks if there is data piped, then collects it. - * Otherwise returns empty string. - */ -const collectPipedData = async () => { - if (process.stdin.isTTY) { - return ''; - } - - const readline = createInterface({ - input: process.stdin, - }); - - const data: string[] = []; - - for await (const line of readline) { - data.push(line); - } - - return data.join('\n'); -}; - -/** - * Checks if there is piped data, tries to parse yaml from it. - * Returns empty string if haven't found anything. - */ -export const parseManifestFromStdin = async () => { - const pipedSourceManifest = await collectPipedData(); - - if (!pipedSourceManifest) { - return ''; - } - - const regex = /# start((?:.*\n)+?)# end/; - const match = regex.exec(pipedSourceManifest); - - if (!match) { - return ''; - } - - return match![1]; -}; From db51036b4828ee1bce98f0c4f59ec462ca241a71 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:35:48 +0400 Subject: [PATCH 355/863] test(src): update tests according to changes --- src/__tests__/common/lib/load.test.ts | 2 +- src/__tests__/common/util/helpers.test.ts | 44 ++++++++++++++++++++++ src/__tests__/if-diff/lib/load.test.ts | 4 +- src/__tests__/if-diff/util/helpers.test.ts | 40 -------------------- 4 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 src/__tests__/common/util/helpers.test.ts diff --git a/src/__tests__/common/lib/load.test.ts b/src/__tests__/common/lib/load.test.ts index 43f6ee2af..a76d3bd27 100644 --- a/src/__tests__/common/lib/load.test.ts +++ b/src/__tests__/common/lib/load.test.ts @@ -14,7 +14,7 @@ jest.mock( }), {virtual: true} ); -jest.mock('../../../if-diff/util/helpers', () => ({ +jest.mock('../../../common/util/helpers', () => ({ parseManifestFromStdin: () => { if (process.env.readline === 'valid-source') { return ` diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts new file mode 100644 index 000000000..92b4f9dab --- /dev/null +++ b/src/__tests__/common/util/helpers.test.ts @@ -0,0 +1,44 @@ +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); + +import {parseManifestFromStdin} from '../../../common/util/helpers'; + +describe('common/util/helpers: ', () => { + describe('parseManifestFromStdin(): ', () => { + it('returns empty string if there is no data in stdin.', async () => { + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + }); + + it('returns empty string if nothing is piped.', async () => { + const originalIsTTY = process.stdin.isTTY; + process.stdin.isTTY = true; + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + process.stdin.isTTY = originalIsTTY; + }); + + it('throws error if there is no manifest in stdin.', async () => { + process.env.readline = 'no_manifest'; + expect.assertions(1); + + const response = await parseManifestFromStdin(); + + expect(response).toEqual(''); + }); + + it('returns empty string if there is no data in stdin.', async () => { + process.env.readline = 'manifest'; + const response = await parseManifestFromStdin(); + const expectedMessage = + '\nname: mock-name\ndescription: mock-description\n'; + + expect(response).toEqual(expectedMessage); + }); + }); +}); diff --git a/src/__tests__/if-diff/lib/load.test.ts b/src/__tests__/if-diff/lib/load.test.ts index f722757e5..8a703df76 100644 --- a/src/__tests__/if-diff/lib/load.test.ts +++ b/src/__tests__/if-diff/lib/load.test.ts @@ -14,7 +14,7 @@ jest.mock( }), {virtual: true} ); -jest.mock('../../../if-diff/util/helpers', () => ({ +jest.mock('../../../common/util/helpers', () => ({ parseManifestFromStdin: () => { if (process.env.readline === 'valid-source') { return ` @@ -44,7 +44,7 @@ import {PluginParams} from '@grnsft/if-core/types'; import {loadIfDiffFiles} from '../../../if-diff/lib/load'; -import {parseManifestFromStdin} from '../../../if-diff/util/helpers'; +import {parseManifestFromStdin} from '../../../common/util/helpers'; import {STRINGS} from '../../../if-diff/config'; diff --git a/src/__tests__/if-diff/util/helpers.test.ts b/src/__tests__/if-diff/util/helpers.test.ts index a7d25599e..eb9a0e553 100644 --- a/src/__tests__/if-diff/util/helpers.test.ts +++ b/src/__tests__/if-diff/util/helpers.test.ts @@ -7,7 +7,6 @@ import { checkIfEqual, formatNotMatchingLog, oneIsPrimitive, - parseManifestFromStdin, } from '../../../if-diff/util/helpers'; describe('if-diff/util/helpers: ', () => { @@ -193,43 +192,4 @@ describe('if-diff/util/helpers: ', () => { console.log = actualLogger; }); }); - - describe('parseManifestFromStdin(): ', () => { - it('returns empty string if there is no data in stdin.', async () => { - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - }); - - it('returns empty string if nothing is piped.', async () => { - const originalIsTTY = process.stdin.isTTY; - process.stdin.isTTY = true; - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - process.stdin.isTTY = originalIsTTY; - }); - - it('throws error if there is no manifest in stdin.', async () => { - process.env.readline = 'no_manifest'; - expect.assertions(1); - - const response = await parseManifestFromStdin(); - - expect(response).toEqual(''); - }); - - it('returns empty string if there is no data in stdin.', async () => { - process.env.readline = 'manifest'; - const response = await parseManifestFromStdin(); - const expectedMessage = ` -name: mock-name -description: mock-description -`; - - expect(response).toEqual(expectedMessage); - }); - }); }); From 981e925933a425e9cb3b317c39541319ce8b9d6e Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:37:07 +0400 Subject: [PATCH 356/863] feat(src): add string and types files for if-csv --- src/if-csv/config/index.ts | 2 ++ src/if-csv/config/strings.ts | 3 +++ src/if-csv/types/csv.ts | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 src/if-csv/config/index.ts create mode 100644 src/if-csv/config/strings.ts create mode 100644 src/if-csv/types/csv.ts diff --git a/src/if-csv/config/index.ts b/src/if-csv/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-csv/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-csv/config/strings.ts b/src/if-csv/config/strings.ts new file mode 100644 index 000000000..be90a4547 --- /dev/null +++ b/src/if-csv/config/strings.ts @@ -0,0 +1,3 @@ +export const STRINGS = { + PARAMS_NOT_PRESENT: 'Parameter not provided.', +}; diff --git a/src/if-csv/types/csv.ts b/src/if-csv/types/csv.ts new file mode 100644 index 000000000..3e2f969c6 --- /dev/null +++ b/src/if-csv/types/csv.ts @@ -0,0 +1,8 @@ +import {Context} from '../../common/types/manifest'; + +export type CsvOptions = { + tree: any; + context: Context; + outputPath?: string; + params: string; +}; From b96e466e8eef1797ada0324332203a2b5bbcf4da Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:39:23 +0400 Subject: [PATCH 357/863] feat(src): add config and types for args for if-csv --- src/if-csv/config/config.ts | 39 ++++++++++++++++++++++++++++++++ src/if-csv/types/process-args.ts | 5 ++++ 2 files changed, 44 insertions(+) create mode 100644 src/if-csv/config/config.ts create mode 100644 src/if-csv/types/process-args.ts diff --git a/src/if-csv/config/config.ts b/src/if-csv/config/config.ts new file mode 100644 index 000000000..8be9dba75 --- /dev/null +++ b/src/if-csv/config/config.ts @@ -0,0 +1,39 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IFCsvArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + output: { + type: String, + optional: true, + alias: 'o', + description: '[path to the csv output file]', + }, + params: { + type: String, + optional: false, + alias: 'p', + description: '[parameter to export]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Csv Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, +}; diff --git a/src/if-csv/types/process-args.ts b/src/if-csv/types/process-args.ts new file mode 100644 index 000000000..f0bcb44ad --- /dev/null +++ b/src/if-csv/types/process-args.ts @@ -0,0 +1,5 @@ +export interface IFCsvArgs { + manifest?: string; + output?: string; + params: string; +} From 8d199be6b314efef23825ca7256b0386bfbf6f03 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:40:44 +0400 Subject: [PATCH 358/863] test(src): add test for helpers --- src/__tests__/if-csv/util/helpers.test.ts | 196 ++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 src/__tests__/if-csv/util/helpers.test.ts diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts new file mode 100644 index 000000000..61e6f1e9c --- /dev/null +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -0,0 +1,196 @@ +import * as fs from 'fs/promises'; + +import {stringify} from 'csv-stringify/sync'; +import {jest} from '@jest/globals'; + +import {executeCsv} from '../../../if-csv/util/helpers'; + +import {CsvOptions} from '../../../if-csv/types/csv'; + +import { + tree, + context, + outputs, + aggregated, + aggregation, +} from '../../../__mocks__/builtins/export-csv'; + +jest.mock('fs/promises', () => ({ + writeFile: jest.fn<() => Promise>().mockResolvedValue(), +})); + +describe('executeCsv(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + const reformedContext = Object.assign({}, context, {outputs}); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when the `outputs` type is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when `aggregation` persists.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedContext = Object.assign( + {}, + context, + {outputs}, + {aggregation} + ); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('returns string when `outputPath` is not provided', async () => { + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const options: CsvOptions = { + tree, + context, + outputPath: undefined, + params: 'carbon', + }; + + const result = await executeCsv(options); + + expect.assertions(1); + expect(result).toEqual(stringify(matrix, {columns})); + }); + + it('generates CSV file when `aggregation` is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedContext = Object.assign({}, context, {outputs}); + const options: CsvOptions = { + tree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); +}); From a24f1b4a17dc7fdeecd2a1e3567d7dcc42d9b8b1 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:42:59 +0400 Subject: [PATCH 359/863] feat(src): add logic for if-csv --- src/if-csv/index.ts | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/if-csv/index.ts diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts new file mode 100644 index 000000000..a53e54994 --- /dev/null +++ b/src/if-csv/index.ts @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as YAML from 'js-yaml'; + +import {parseManifestFromStdin} from '../common/util/helpers'; +import {validateManifest} from '../common/util/validations'; +import {debugLogger} from '../common/util/debug-logger'; +import {logger} from '../common/util/logger'; +import {load} from '../common/lib/load'; + +import {injectEnvironment} from '../if-run/lib/environment'; +import {initialize} from '../if-run/lib/initialize'; +import {aggregate} from '../if-run/lib/aggregate'; +import {compute} from '../if-run/lib/compute'; + +import {parseIfCsvArgs} from './util/args'; +import {executeCsv} from './util/helpers'; +import {CsvOptions} from './types/csv'; + +const IfCsv = async () => { + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + + const pipedManifest = await parseManifestFromStdin(); + const {manifest, output, params} = await parseIfCsvArgs(); + const resolvedManifest = manifest || pipedManifest; + let envManifest; + + if (resolvedManifest) { + if (pipedManifest) { + envManifest = await YAML.load(pipedManifest!); + } else { + const {rawManifest} = await load(resolvedManifest); + envManifest = await injectEnvironment(rawManifest); + } + + const {tree, ...context} = validateManifest(envManifest); + const pluginStorage = await initialize(context.initialize.plugins); + const computedTree = await compute(tree, {context, pluginStorage}); + const aggregatedTree = aggregate(computedTree, context.aggregation); + const options: CsvOptions = { + tree: aggregatedTree, + context, + outputPath: output, + params, + }; + const result = await executeCsv(options); + + if (!output && result) { + console.log(result); + } + } + + process.exit(0); +}; + +IfCsv().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 2cac2e374f6b9db83aea60b8f94c55ab98145f5c Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:44:08 +0400 Subject: [PATCH 360/863] feat(package): add if-csv script --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b888aa3d..7c80610c5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "if-diff": "./build/if-diff/index.js", "if-run": "./build/if-run/index.js", "if-env": "./build/if-env/index.js", - "if-check": "./build/if-check/index.js" + "if-check": "./build/if-check/index.js", + "if-csv": "./build/if-csv/index.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -76,6 +77,7 @@ "fix": "gts fix", "fix:package": "fixpack", "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-check/index.ts", + "if-csv": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-csv/index.ts", "if-diff": "npx ts-node src/if-diff/index.ts", "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-env/index.ts", "if-run": "npx ts-node src/if-run/index.ts", From 52e14b3419d70795f6a2d9ab215a28920447ce74 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 20:09:36 +0400 Subject: [PATCH 361/863] fix(src): fix merge issue --- src/if-env/index.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/if-env/index.ts b/src/if-env/index.ts index 846d6f7af..001f769a3 100644 --- a/src/if-env/index.ts +++ b/src/if-env/index.ts @@ -1,8 +1,7 @@ #!/usr/bin/env node /* eslint-disable no-process-exit */ -import {debugLogger} from './util/debug-logger'; -import {parseIfEnvArgs} from './util/args'; - +import {debugLogger} from '../common/util/debug-logger'; +import {logger} from '../common/util/logger'; import {STRINGS} from '../common/config'; import { @@ -10,9 +9,8 @@ import { getOptionsFromArgs, initializeAndInstallLibs, } from './util/helpers'; -import {logger} from '../common/util/logger'; - import {EnvironmentOptions} from './types/if-env'; +import {parseIfEnvArgs} from './util/args'; const {SUCCESS_MESSAGE} = STRINGS; From 3c33bdea5dd4d16085be0f305868795a9b978564 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 9 Jul 2024 19:10:24 +0400 Subject: [PATCH 362/863] fix(builtins): validate duration to be gt 0 in mock observations --- src/if-run/builtins/mock-observations/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index d947e7d7c..ab090d7c8 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -55,7 +55,7 @@ export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { const schema = z.object({ 'timestamp-from': z.string(), 'timestamp-to': z.string(), - duration: z.number(), + duration: z.number().gt(0), components: z.array(z.record(z.string())), generators: z.object({ common: z.record(z.string().or(z.number())), From 01ace664f03515b651016808fbec83778ccdf486 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:31:38 +0400 Subject: [PATCH 363/863] fix(config): add failure string for if-csv --- src/if-csv/config/strings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-csv/config/strings.ts b/src/if-csv/config/strings.ts index be90a4547..717461c1b 100644 --- a/src/if-csv/config/strings.ts +++ b/src/if-csv/config/strings.ts @@ -1,3 +1,4 @@ export const STRINGS = { PARAMS_NOT_PRESENT: 'Parameter not provided.', + FAILURE_MESSAGE_OUTPUTS: 'Manifest outputs are not available!', }; From ebf1770ff44469fcea46b13cd45250a71bb689e1 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:33:24 +0400 Subject: [PATCH 364/863] fix(util): add getManifestData function --- src/if-csv/util/helpers.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index b70ca2194..d9f7ec09d 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -1,8 +1,29 @@ -import {stringify} from 'csv-stringify/sync'; import * as fs from 'fs/promises'; +import {stringify} from 'csv-stringify/sync'; import {PluginParams} from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {load} from '../../common/lib/load'; import {CsvOptions} from '../types/csv'; +import {STRINGS} from '../config'; + +const {FAILURE_MESSAGE_OUTPUTS} = STRINGS; +const {ManifestValidationError} = ERRORS; + +/** + * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + */ +export const getManifestData = async (manifest: string) => { + const loadedManifest = await load(manifest); + const children = loadedManifest.rawManifest.tree.children; + + if ((children.child || children['child-0']).outputs) { + return loadedManifest.rawManifest; + } + + throw new ManifestValidationError(FAILURE_MESSAGE_OUTPUTS); +}; /** * Executes a CSV generation based on the provided tree structure, context, output path, and params. From 083340d70f531551d4fe6f7d505578486c60157b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:35:19 +0400 Subject: [PATCH 365/863] fix(src): update logix to accpet executed manifest --- src/if-csv/index.ts | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index a53e54994..94ede0bb4 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -3,18 +3,12 @@ import * as YAML from 'js-yaml'; import {parseManifestFromStdin} from '../common/util/helpers'; -import {validateManifest} from '../common/util/validations'; import {debugLogger} from '../common/util/debug-logger'; +import {Manifest} from '../common/types/manifest'; import {logger} from '../common/util/logger'; -import {load} from '../common/lib/load'; - -import {injectEnvironment} from '../if-run/lib/environment'; -import {initialize} from '../if-run/lib/initialize'; -import {aggregate} from '../if-run/lib/aggregate'; -import {compute} from '../if-run/lib/compute'; +import {executeCsv, getManifestData} from './util/helpers'; import {parseIfCsvArgs} from './util/args'; -import {executeCsv} from './util/helpers'; import {CsvOptions} from './types/csv'; const IfCsv = async () => { @@ -24,23 +18,18 @@ const IfCsv = async () => { const pipedManifest = await parseManifestFromStdin(); const {manifest, output, params} = await parseIfCsvArgs(); const resolvedManifest = manifest || pipedManifest; - let envManifest; + let manifestData: Manifest; if (resolvedManifest) { if (pipedManifest) { - envManifest = await YAML.load(pipedManifest!); + manifestData = (await YAML.load(pipedManifest!)) as Manifest; } else { - const {rawManifest} = await load(resolvedManifest); - envManifest = await injectEnvironment(rawManifest); + manifestData = await getManifestData(manifest!); } - const {tree, ...context} = validateManifest(envManifest); - const pluginStorage = await initialize(context.initialize.plugins); - const computedTree = await compute(tree, {context, pluginStorage}); - const aggregatedTree = aggregate(computedTree, context.aggregation); const options: CsvOptions = { - tree: aggregatedTree, - context, + tree: manifestData.tree, + context: manifestData, outputPath: output, params, }; From bcc872fa23fbc7aff8ed8ff9c43e4e22b927220c Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:36:57 +0400 Subject: [PATCH 366/863] test(util): add tests for getManifestData function --- src/__tests__/if-csv/util/helpers.test.ts | 400 +++++++++++++--------- 1 file changed, 238 insertions(+), 162 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 61e6f1e9c..4712f5773 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -1,12 +1,13 @@ +import {jest} from '@jest/globals'; import * as fs from 'fs/promises'; - import {stringify} from 'csv-stringify/sync'; -import {jest} from '@jest/globals'; - -import {executeCsv} from '../../../if-csv/util/helpers'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {executeCsv, getManifestData} from '../../../if-csv/util/helpers'; import {CsvOptions} from '../../../if-csv/types/csv'; +const {ManifestValidationError} = ERRORS; + import { tree, context, @@ -15,182 +16,257 @@ import { aggregation, } from '../../../__mocks__/builtins/export-csv'; -jest.mock('fs/promises', () => ({ - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('executeCsv(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - const reformedContext = Object.assign({}, context, {outputs}); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, +jest.mock('fs/promises', () => { + const originalModule = + jest.requireActual('fs/promises'); + return { + __esModule: true, + ...originalModule, + writeFile: jest.fn(() => Promise.resolve()), + }; +}); + +describe('if-csv/util/helpers: ', () => { + describe('executeCsv(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + const reformedContext = Object.assign({}, context, {outputs}); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, - }); + }); - const options: CsvOptions = { - tree: reformedTree, - context: reformedContext, - outputPath, - params: 'carbon', - }; + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; - await executeCsv(options); + await executeCsv(options); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); - it('generates CSV file when the `outputs` type is missing.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, + it('generates CSV file when the `outputs` type is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, - }); + }); - const options: CsvOptions = { - tree: reformedTree, - context, - outputPath, - params: 'carbon', - }; + const options: CsvOptions = { + tree: reformedTree, + context, + outputPath, + params: 'carbon', + }; - await executeCsv(options); + await executeCsv(options); - expect.assertions(1); + expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); - it('generates CSV file when `aggregation` persists.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, + it('generates CSV file when `aggregation` persists.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedContext = Object.assign( + {}, + context, + {outputs}, + {aggregation} + ); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); }); - const options: CsvOptions = { - tree: reformedTree, - context: reformedContext, - outputPath, - params: 'carbon', - }; + it('returns string when `outputPath` is not provided', async () => { + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; - await executeCsv(options); + const options: CsvOptions = { + tree, + context, + outputPath: undefined, + params: 'carbon', + }; - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + const result = await executeCsv(options); + + expect.assertions(1); + expect(result).toEqual(stringify(matrix, {columns})); + }); + + it('generates CSV file when `aggregation` is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; - it('returns string when `outputPath` is not provided', async () => { - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const options: CsvOptions = { - tree, - context, - outputPath: undefined, - params: 'carbon', - }; - - const result = await executeCsv(options); - - expect.assertions(1); - expect(result).toEqual(stringify(matrix, {columns})); + const reformedContext = Object.assign({}, context, {outputs}); + const options: CsvOptions = { + tree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); }); - it('generates CSV file when `aggregation` is missing.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedContext = Object.assign({}, context, {outputs}); - const options: CsvOptions = { - tree, - context: reformedContext, - outputPath, - params: 'carbon', - }; - - await executeCsv(options); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); + describe('getManifestData(): ', () => { + it('returns correct manifest data.', async () => { + process.env.MOCK_MANIFEST = 'true'; + const mockManifestPath = './src/__mocks__/mock-manifest.yaml'; + const result = await getManifestData(mockManifestPath); + + expect.assertions(2); + expect(result).toHaveProperty('description'); + expect(result).toHaveProperty('tree'); + }); + + it('throws an error when there is not `outputs` in the manifest.', async () => { + process.env.MOCK_MANIFEST = 'false'; + const mockManifestPath = ''; + const load = require('../../../common/lib/load'); + const spyLoad = jest.spyOn(load, 'load'); + + spyLoad.mockReturnValue({ + rawManifest: {tree: {children: {child: {}}}}, + }); + expect.assertions(1); + try { + await getManifestData(mockManifestPath); + } catch (error) { + expect(error).toEqual( + new ManifestValidationError('Manifest outputs are not available!') + ); + } + }); }); }); From 752c014fb454580871a178679efe325bdf53740b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:43:26 +0400 Subject: [PATCH 367/863] fix(package): add `if-csv` into package-loc.json --- package-lock.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package-lock.json b/package-lock.json index dd24c9128..f01b0fb13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ }, "bin": { "if-check": "build/if-check/index.js", + "if-csv": "build/if-csv/index.js", "if-diff": "build/if-diff/index.js", "if-env": "build/if-env/index.js", "if-run": "build/if-run/index.js" From 96f086c53dfa00831febeba7e7c27e421295acda Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:57:39 +0400 Subject: [PATCH 368/863] fix(util): improve getManifestData function --- src/if-csv/util/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index d9f7ec09d..8ae6dd0e5 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -15,11 +15,11 @@ const {ManifestValidationError} = ERRORS; * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. */ export const getManifestData = async (manifest: string) => { - const loadedManifest = await load(manifest); - const children = loadedManifest.rawManifest.tree.children; + const {rawManifest} = await load(manifest); + const children = rawManifest.tree.children; if ((children.child || children['child-0']).outputs) { - return loadedManifest.rawManifest; + return rawManifest; } throw new ManifestValidationError(FAILURE_MESSAGE_OUTPUTS); From 9d8d1fd8f906c325ea1c401a4b909ab97f153063 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 14:03:26 +0400 Subject: [PATCH 369/863] fix(util): improve getManifestData function --- src/if-csv/util/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index 8ae6dd0e5..397293dd8 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -12,13 +12,13 @@ const {FAILURE_MESSAGE_OUTPUTS} = STRINGS; const {ManifestValidationError} = ERRORS; /** - * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + * Gets the manifest data if `outputs` is present in it. */ export const getManifestData = async (manifest: string) => { const {rawManifest} = await load(manifest); - const children = rawManifest.tree.children; + const {children} = rawManifest.tree; - if ((children.child || children['child-0']).outputs) { + if (children?.child?.outputs || children?.['child-0']?.outputs) { return rawManifest; } From 179238cd0eeb07b3cb23d28a202b4eff667e1749 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 17:20:15 +0400 Subject: [PATCH 370/863] test(util): fix tests conflict after merging with the main --- src/__tests__/if-csv/util/helpers.test.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 4712f5773..1859f4850 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -11,10 +11,9 @@ const {ManifestValidationError} = ERRORS; import { tree, context, - outputs, aggregated, aggregation, -} from '../../../__mocks__/builtins/export-csv'; +} from '../../../__mocks__/builtins/export-yaml'; jest.mock('fs/promises', () => { const originalModule = @@ -45,7 +44,6 @@ describe('if-csv/util/helpers: ', () => { 4000.0000020256216, ], ]; - const reformedContext = Object.assign({}, context, {outputs}); const reformedTree = Object.assign({}, tree, { children: { ...tree.children, @@ -62,7 +60,7 @@ describe('if-csv/util/helpers: ', () => { const options: CsvOptions = { tree: reformedTree, - context: reformedContext, + context, outputPath, params: 'carbon', }; @@ -142,12 +140,7 @@ describe('if-csv/util/helpers: ', () => { ], ]; - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); + const reformedContext = Object.assign({}, context, {aggregation}); const reformedTree = Object.assign({}, tree, { children: { ...tree.children, @@ -221,10 +214,9 @@ describe('if-csv/util/helpers: ', () => { ], ]; - const reformedContext = Object.assign({}, context, {outputs}); const options: CsvOptions = { tree, - context: reformedContext, + context, outputPath, params: 'carbon', }; From e66b168688e87153326d1db0be2be907a39a6c7a Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 16:50:12 +0400 Subject: [PATCH 371/863] fix(util): remove `params` and update `aggregation` in the manifest schema --- src/common/util/validations.ts | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index a4f0fcb5c..76b785d6d 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -3,8 +3,10 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../if-run/config'; -import {AGGREGATION_METHODS} from '../../if-run/types/aggregation'; -import {AGGREGATION_TYPES} from '../../if-run/types/parameters'; +import { + AGGREGATION_METHODS, + AGGREGATION_TYPES, +} from '../../if-run/types/aggregation'; const {ManifestValidationError, InputValidationError} = ERRORS; const {VALIDATING_MANIFEST} = STRINGS; @@ -38,22 +40,15 @@ export const manifestSchema = z.object({ .nullable(), aggregation: z .object({ - metrics: z.array(z.string()), - type: z.enum(AGGREGATION_METHODS), + metrics: z.record( + z.object({ + method: z.enum(AGGREGATION_METHODS), + }) + ), + type: z.enum(AGGREGATION_TYPES), }) .optional() .nullable(), - params: z - .array( - z.object({ - name: z.string(), - description: z.string(), - aggregation: z.enum(AGGREGATION_TYPES), - unit: z.string(), - }) - ) - .optional() - .nullable(), initialize: z.object({ plugins: z.record( z.string(), From 2cc439846da0e10182854e743bbe98f52bf5e614 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 16:54:14 +0400 Subject: [PATCH 372/863] fix(src): remove all files realted to params --- src/__mocks__/json.ts | 14 -- src/__tests__/if-run/lib/parameterize.test.ts | 114 ---------- src/__tests__/if-run/util/json.test.ts | 26 --- src/if-run/config/params.ts | 198 ------------------ src/if-run/lib/parameterize.ts | 79 ------- src/if-run/types/parameters.ts | 7 - src/if-run/util/json.ts | 10 - 7 files changed, 448 deletions(-) delete mode 100644 src/__mocks__/json.ts delete mode 100644 src/__tests__/if-run/lib/parameterize.test.ts delete mode 100644 src/__tests__/if-run/util/json.test.ts delete mode 100644 src/if-run/config/params.ts delete mode 100644 src/if-run/lib/parameterize.ts delete mode 100644 src/if-run/types/parameters.ts delete mode 100644 src/if-run/util/json.ts diff --git a/src/__mocks__/json.ts b/src/__mocks__/json.ts deleted file mode 100644 index d6bb24d2c..000000000 --- a/src/__mocks__/json.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const readAndParseJson = async () => { - return { - 'mock-carbon': { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'mock-cpu': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - }; -}; diff --git a/src/__tests__/if-run/lib/parameterize.test.ts b/src/__tests__/if-run/lib/parameterize.test.ts deleted file mode 100644 index ed3a4b948..000000000 --- a/src/__tests__/if-run/lib/parameterize.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import {LeveledLogMethod} from 'winston'; - -const mockLog = jest.fn((message: string) => message); - -jest.mock('../../../if-run/util/log-memoize', () => ({ - memoizedLog: mockLog, -})); -jest.mock('../../../common/util/logger', () => ({ - logger: { - warn: mockLog, - debug: mockLog, - }, -})); - -import {PARAMETERS} from '../../../if-run/config'; -import {parameterize} from '../../../if-run/lib/parameterize'; - -import {STRINGS} from '../../../if-run/config'; - -import {ManifestParameter} from '../../../common/types/manifest'; - -const {REJECTING_OVERRIDE, CHECKING_AGGREGATION_METHOD} = STRINGS; - -describe('lib/parameterize: ', () => { - afterEach(() => { - (mockLog as jest.Mock).mockReset(); - }); - - describe('getAggregationMethod(): ', () => { - it('returns method for average aggregation method metric.', () => { - const metric = 'cpu/utilization'; - const method = parameterize.getAggregationMethod(metric); - - const expectedMethod = 'avg'; - - expect(method).toEqual(expectedMethod); - }); - - it('returns method for unknown aggregation method metric.', () => { - const metric = 'mock/metric'; - const method = parameterize.getAggregationMethod(metric); - - const expectedMethod = 'sum'; - - expect(method).toEqual(expectedMethod); - expect(mockLog as unknown as LeveledLogMethod).toHaveBeenCalledTimes(2); - }); - - it('prints debug log for first input.', () => { - const unitName = 'timestamp'; - - parameterize.getAggregationMethod(unitName); - - expect(mockLog as typeof console.debug).toHaveBeenCalledWith( - console.debug, - CHECKING_AGGREGATION_METHOD(unitName) - ); - }); - }); - - describe('combine(): ', () => { - it('checks if return type is undefined.', () => { - const params = {}; - const response = parameterize.combine(null, params); - - expect(response).toBeUndefined(); - }); - - it('checks if uninitialized custom param is requested, then returns fallback `sum` method.', () => { - const name = 'mock-name'; - const method = parameterize.getAggregationMethod(name); - - const expectedMethodName = 'sum'; - expect(method).toEqual(expectedMethodName); - }); - - it('checks if custom params are inserted successfully.', () => { - const params = [ - { - name: 'mock-name', - description: 'mock-description', - unit: 'mock/sq', - aggregation: 'none', - }, - ] as ManifestParameter[]; - const object = {}; - - parameterize.combine(params, object); - const method = parameterize.getAggregationMethod(params[0].name); - - expect(method).toEqual(params[0].aggregation); - }); - - it('rejects on default param override.', () => { - const params = [ - { - name: 'carbon', - description: 'mock-description', - unit: 'mock/co', - aggregation: 'none', - }, - ] as ManifestParameter[]; - - parameterize.combine(params, PARAMETERS); - const method = parameterize.getAggregationMethod(params[0].name); - - const expectedMethodName = 'sum'; - const expectedMessage = REJECTING_OVERRIDE(params[0]); - - expect(method).toEqual(expectedMethodName); - expect(mockLog).toHaveBeenCalledWith(expectedMessage); - }); - }); -}); diff --git a/src/__tests__/if-run/util/json.test.ts b/src/__tests__/if-run/util/json.test.ts deleted file mode 100644 index 5836c677a..000000000 --- a/src/__tests__/if-run/util/json.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -jest.mock('fs/promises', () => require('../../../__mocks__/fs')); - -import {readAndParseJson} from '../../../if-run/util/json'; - -describe('util/json: ', () => { - describe('readAndParseJson(): ', () => { - it('returns file content from path.', async () => { - const path = 'mock/path/json'; - expect.assertions(1); - - const response = await readAndParseJson(path); - expect(response).toEqual(path); - }); - - it('throws error if path does not exist.', async () => { - const path = 'mock/path/json-reject'; - expect.assertions(1); - - try { - await readAndParseJson(path); - } catch (error) { - expect(error).toBeInstanceOf(Error); - } - }); - }); -}); diff --git a/src/if-run/config/params.ts b/src/if-run/config/params.ts deleted file mode 100644 index 76732e57b..000000000 --- a/src/if-run/config/params.ts +++ /dev/null @@ -1,198 +0,0 @@ -import {Parameters} from '../types/parameters'; - -export const PARAMETERS: Parameters = { - carbon: { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'cpu/number-cores': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - 'cpu/utilization': { - description: 'refers to CPU utilization.', - unit: 'percentage', - aggregation: 'avg', - }, - 'disk-io': { - description: 'refers to GB of data written/read from disk', - unit: 'GB', - aggregation: 'sum', - }, - duration: { - description: 'refers to the duration of the input', - unit: 'seconds', - aggregation: 'sum', - }, - energy: { - description: 'amount of energy utilised by the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'cpu/energy': { - description: 'Energy consumed by the CPU of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'device/expected-lifespan': { - description: 'Total Expected Lifespan of the Component in Seconds', - unit: 'seconds', - aggregation: 'sum', - }, - 'memory/energy': { - description: 'Energy consumed by the Memory of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'carbon-embodied': { - description: 'Embodied Emissions of the component', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'network/energy': { - description: 'Energy consumed by the Network of the component', - unit: 'kWh', - aggregation: 'sum', - }, - 'functional-unit': { - description: - 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', - unit: 'none', - aggregation: 'sum', - }, - 'gpu-util': { - description: 'refers to CPU utilization.', - unit: 'percentage', - aggregation: 'avg', - }, - 'grid/carbon-intensity': { - description: 'Carbon intensity for the grid', - unit: 'gCO2eq/kWh', - aggregation: 'avg', - }, - 'cloud/instance-type': { - description: 'Type of Cloud Instance name used in the cloud provider APIs', - unit: 'None', - aggregation: 'none', - }, - geolocation: { - description: - 'Geographic location of provider as string (for watt-time model it is provided as latitude and longitude, comma separated, in decimal degrees)', - unit: 'None (decimal degrees for watt-time model)', - aggregation: 'none', - }, - 'carbon-operational': { - description: 'Operational Emissions of the component', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'cpu/name': { - description: 'Name of the physical processor', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region': { - description: 'region cloud instance runs in', - unit: 'None', - aggregation: 'none', - }, - 'cloud/vendor': { - description: - 'Name of the cloud service provider in the ccf model. Can be aws, gcp or azure', - unit: 'None', - aggregation: 'none', - }, - name: { - description: 'arbitrary name parameter.', - unit: 'None', - aggregation: 'none', - }, - 'ram-alloc': { - description: 'refers to GB of memory allocated.', - unit: 'GB', - aggregation: 'avg', - }, - 'ram-util': { - description: 'refers to percentage of memory utilized.', - unit: 'percentage', - aggregation: 'avg', - }, - 'resources-reserved': { - description: 'resources reserved for an application', - unit: 'count', - aggregation: 'none', - }, - 'cpu/thermal-design-power': { - description: 'thermal design power for a processor', - unit: 'kwh', - aggregation: 'avg', - }, - 'device/emissions-embodied': { - description: 'total embodied emissions of some component', - unit: 'gCO2e', - aggregation: 'sum', - }, - timestamp: { - description: 'refers to the time of occurrence of the input', - unit: 'RFC3339', - aggregation: 'none', - }, - 'time-reserved': { - description: 'time reserved for a component', - unit: 'seconds', - aggregation: 'avg', - }, - 'resources-total': { - description: 'total resources available', - unit: 'count', - aggregation: 'none', - }, - 'vcpus-allocated': { - description: 'number of vcpus allocated to particular resource', - unit: 'count', - aggregation: 'none', - }, - 'vcpus-total': { - description: 'total number of vcpus available on a particular resource', - unit: 'count', - aggregation: 'none', - }, - 'memory-available': { - description: 'total amount of memory available on a particular resource', - unit: 'GB', - aggregation: 'none', - }, - 'physical-processor': { - description: - 'name of the physical processor being used in a specific instance type', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-cfe': { - description: 'cloud region name in cfe format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-em-zone-id': { - description: 'cloud region name in electricity maps format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-wt-id': { - description: 'cloud region name in watt-time format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-location': { - description: 'cloud region name in our IF format', - unit: 'None', - aggregation: 'none', - }, - 'cloud/region-geolocation': { - description: 'location expressed as decimal coordinates (lat/lon)', - unit: 'decimal degrees', - aggregation: 'none', - }, -}; diff --git a/src/if-run/lib/parameterize.ts b/src/if-run/lib/parameterize.ts deleted file mode 100644 index 1034e1ce2..000000000 --- a/src/if-run/lib/parameterize.ts +++ /dev/null @@ -1,79 +0,0 @@ -import {debugLogger} from '../../common/util/debug-logger'; -import {logger} from '../../common/util/logger'; -import {memoizedLog} from '../util/log-memoize'; - -import {STRINGS, PARAMETERS} from '../config'; - -import {Parameters} from '../types/parameters'; -import {ManifestParameter} from '../../common/types/manifest'; - -const { - REJECTING_OVERRIDE, - UNKNOWN_PARAM, - SYNCING_PARAMETERS, - CHECKING_AGGREGATION_METHOD, -} = STRINGS; - -/** - * Parameters manager. Provides get aggregation method and combine functionality. - */ -const Parameterize = () => { - let parametersStorage = PARAMETERS; - - /** - * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. - */ - const getAggregationMethod = (unitName: string) => { - debugLogger.setExecutingPluginName(); - memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); - - if (`${unitName}` in parametersStorage) { - return parametersStorage[unitName as keyof typeof PARAMETERS].aggregation; - } - - memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - - return 'sum'; - }; - - /** - * Checks if additional parameters are provided in context. - * If so, then checks if they are coincident with default ones and exits with warning message. - * Otherwise appends context based parameters to defaults. - */ - const combine = ( - contextParameters: ManifestParameter[] | null | undefined, - parameters: Parameters - ) => { - console.debug(SYNCING_PARAMETERS); - - if (contextParameters) { - contextParameters.forEach(param => { - if (`${param.name}` in parameters) { - logger.warn(REJECTING_OVERRIDE(param)); - - return; - } - - const {description, unit, aggregation, name} = param; - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - parameters[name] = { - description, - unit, - aggregation, - }; - }); - } - - parametersStorage = parameters; - }; - - return { - combine, - getAggregationMethod, - }; -}; - -export const parameterize = Parameterize(); diff --git a/src/if-run/types/parameters.ts b/src/if-run/types/parameters.ts deleted file mode 100644 index 939ac2ba6..000000000 --- a/src/if-run/types/parameters.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {ManifestParameter} from '../../common/types/manifest'; - -export const AGGREGATION_TYPES = ['sum', 'none', 'avg'] as const; - -type ParameterProps = Omit; - -export type Parameters = Record; diff --git a/src/if-run/util/json.ts b/src/if-run/util/json.ts deleted file mode 100644 index c9180a788..000000000 --- a/src/if-run/util/json.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as fs from 'fs/promises'; - -/** - * Reads and parses json file. - */ -export const readAndParseJson = async (paramPath: string): Promise => { - const file = await fs.readFile(paramPath, 'utf-8'); - - return JSON.parse(file) as T; -}; From c17a8f2d29dd7786a93034993de2a44e19ec2562 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 16:57:02 +0400 Subject: [PATCH 373/863] fix(src): remove `override-params` from config and from `IfRunArgs` interface --- src/if-run/config/config.ts | 6 ------ src/if-run/types/process-args.ts | 1 - 2 files changed, 7 deletions(-) diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index 99ca34193..91f366543 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -21,12 +21,6 @@ export const CONFIG = { alias: 'o', description: '[path to the output file]', }, - 'override-params': { - type: String, - optional: true, - alias: 'p', - description: '[path to a parameter file that overrides our defaults]', - }, 'no-output': { type: Boolean, optional: true, diff --git a/src/if-run/types/process-args.ts b/src/if-run/types/process-args.ts index a336b0af0..184877bd0 100644 --- a/src/if-run/types/process-args.ts +++ b/src/if-run/types/process-args.ts @@ -1,7 +1,6 @@ export interface IfRunArgs { manifest?: string; output?: string; - 'override-params'?: string; 'no-output'?: boolean; debug?: boolean; } From 793ee6d3fd43f2409a5ffd13bdbadf368f7cfea1 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:09:06 +0400 Subject: [PATCH 374/863] fix(src): remove redundant types and strings --- src/common/types/manifest.ts | 2 -- src/if-run/config/index.ts | 1 - src/if-run/config/strings.ts | 5 ----- 3 files changed, 8 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 2359a3433..1b003be2c 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -14,5 +14,3 @@ export type AggregationParamsSure = Extract; export type Context = Omit; export type ContextWithExec = Omit; - -export type ManifestParameter = Extract[number]; diff --git a/src/if-run/config/index.ts b/src/if-run/config/index.ts index 6aa6e0a98..4972b390b 100644 --- a/src/if-run/config/index.ts +++ b/src/if-run/config/index.ts @@ -1,3 +1,2 @@ export {CONFIG} from './config'; -export {PARAMETERS} from './params'; export {STRINGS} from './strings'; diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 5f5387c1f..0a9c1a455 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -1,5 +1,3 @@ -import {ManifestParameter} from '../../common/types/manifest'; - export const STRINGS = { MISSING_METHOD: "Initalization param 'method' is missing.", MISSING_PATH: "Initalization param 'path' is missing.", @@ -28,8 +26,6 @@ export const STRINGS = { METRIC_MISSING: (metric: string, index: number) => `Aggregation metric ${metric} is not found in inputs[${index}].`, INVALID_GROUP_BY: (type: string) => `Invalid group ${type}.`, - REJECTING_OVERRIDE: (param: ManifestParameter) => - `Rejecting overriding of canonical parameter: ${param.name}.`, INVALID_EXHAUST_PLUGIN: (pluginName: string) => `Invalid exhaust plugin: ${pluginName}.`, UNKNOWN_PARAM: (name: string) => @@ -48,7 +44,6 @@ Note that for the '--output' option you also need to define the output type in y LOADING_MANIFEST: 'Loading manifest', VALIDATING_MANIFEST: 'Validating manifest', CAPTURING_RUNTIME_ENVIRONMENT_DATA: 'Capturing runtime environment data', - SYNCING_PARAMETERS: 'Syncing parameters', CHECKING_AGGREGATION_METHOD: (unitName: string) => `Checking aggregation method for ${unitName}`, INITIALIZING_PLUGINS: 'Initializing plugins', From 99e433611fa8f366b26ffd21126eb1c859e82072 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:13:26 +0400 Subject: [PATCH 375/863] fix(util): remove `override-params` from the args.ts --- src/if-run/util/args.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/if-run/util/args.ts b/src/if-run/util/args.ts index 632a17fd6..140c5d140 100644 --- a/src/if-run/util/args.ts +++ b/src/if-run/util/args.ts @@ -33,7 +33,7 @@ const validateAndParseProcessArgs = () => { }; /** - * 1. Parses process arguments like `manifest`, `output`, `override-params`, `help` and `debug`. + * 1. Parses process arguments like `manifest`, `output`, `help` and `debug`. * 2. Checks if `help` param is provided, then logs help message and exits. * 3. If output params are missing, warns user about it. * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. @@ -44,7 +44,6 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { const { manifest, output, - 'override-params': overrideParams, 'no-output': noOutput, debug, } = validateAndParseProcessArgs(); @@ -61,7 +60,6 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { ...(output && {outputPath: prependFullFilePath(output)}), ...(noOutput && {noOutput}), }, - ...(overrideParams && {paramPath: overrideParams}), debug, }; } From 25be4913c82505d8c3b4a8ecef83a24125c82108 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:15:53 +0400 Subject: [PATCH 376/863] feat(types): update aggregation types --- src/if-run/types/aggregation.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts index d15322d29..a7e895da4 100644 --- a/src/if-run/types/aggregation.ts +++ b/src/if-run/types/aggregation.ts @@ -1,3 +1,9 @@ export type AggregationResult = Record; -export const AGGREGATION_METHODS = ['horizontal', 'vertical', 'both'] as const; +export const AGGREGATION_TYPES = ['horizontal', 'vertical', 'both'] as const; +export const AGGREGATION_METHODS = ['sum', 'avg', 'none'] as const; + +export type AggregationMetric = Record< + string, + {method: 'sum' | 'avg' | 'none'} +>; From 9e484b29b0e895eaf12f29a49a72696cf99db897 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:18:05 +0400 Subject: [PATCH 377/863] feat(util): update metrics type --- src/if-run/util/aggregation-helper.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index 408a4e9f7..87d3e15fc 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -1,11 +1,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {PluginParams} from '@grnsft/if-core/types'; -import {parameterize} from '../lib/parameterize'; - import {CONFIG, STRINGS} from '../config'; -import {AggregationResult} from '../types/aggregation'; +import {AggregationMetric, AggregationResult} from '../types/aggregation'; + +import {getAggregationMethod} from '../lib/aggregate'; const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; @@ -15,9 +15,9 @@ const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; * Validates metrics array before applying aggregator. * If aggregation method is `none`, then throws error. */ -const checkIfMetricsAreValid = (metrics: string[]) => { - metrics.forEach(metric => { - const method = parameterize.getAggregationMethod(metric); +const checkIfMetricsAreValid = (metrics: AggregationMetric) => { + Object.keys(metrics).forEach(metric => { + const method = metrics[metric].method; if (method === 'none') { throw new InvalidAggregationMethodError( @@ -33,11 +33,14 @@ const checkIfMetricsAreValid = (metrics: string[]) => { */ export const aggregateInputsIntoOne = ( inputs: PluginParams[], - metrics: string[], + metrics: AggregationMetric, isTemporal?: boolean ) => { checkIfMetricsAreValid(metrics); - const extendedMetrics = [...metrics, ...AGGREGATION_ADDITIONAL_PARAMS]; + const extendedMetrics = [ + ...Object.keys(metrics), + ...AGGREGATION_ADDITIONAL_PARAMS, + ]; return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { @@ -56,7 +59,7 @@ export const aggregateInputsIntoOne = ( /** Checks for the last iteration. */ if (index === inputs.length - 1) { - if (parameterize.getAggregationMethod(metric) === 'avg') { + if (getAggregationMethod(metric) === 'avg') { acc[metric] /= inputs.length; } } From 1aca2939259ec488cc7f437baa61e3b5a7925305 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:21:20 +0400 Subject: [PATCH 378/863] feat(src): add temp workaround to solve issue related to timeSync --- src/if-run/index.ts | 12 ++++--- src/if-run/lib/aggregate.ts | 70 ++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index fa5d17fa2..5ffb62ded 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -1,10 +1,9 @@ #!/usr/bin/env node -import {aggregate} from './lib/aggregate'; +import {aggregate, storeAggregateMetrics} from './lib/aggregate'; import {compute} from './lib/compute'; import {injectEnvironment} from './lib/environment'; import {exhaust} from './lib/exhaust'; import {initialize} from './lib/initialize'; -import {parameterize} from './lib/parameterize'; import {load} from '../common/lib/load'; import {parseIfRunProcessArgs} from './util/args'; @@ -21,19 +20,22 @@ const {DISCLAIMER_MESSAGE} = COMMON_STRINGS; const impactEngine = async () => { const options = parseIfRunProcessArgs(); - const {inputPath, paramPath, outputOptions, debug} = options; + const {inputPath, outputOptions, debug} = options; debugLogger.overrideConsoleMethods(!!debug); logger.info(DISCLAIMER_MESSAGE); console.info(STARTING_IF); - const {rawManifest, parameters} = await load(inputPath, paramPath); + const {rawManifest} = await load(inputPath); const envManifest = await injectEnvironment(rawManifest); try { const {tree, ...context} = validateManifest(envManifest); - parameterize.combine(context.params, parameters); + + // TODO: remove this after resolving timeSync to be a builtin functionality. + storeAggregateMetrics(context.aggregation); + const pluginStorage = await initialize(context.initialize.plugins); const computedTree = await compute(tree, {context, pluginStorage}); const aggregatedTree = aggregate(computedTree, context.aggregation); diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 4c16a0d0d..7ca0d3f42 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -1,14 +1,25 @@ import {PluginParams} from '@grnsft/if-core/types'; -import {aggregateInputsIntoOne} from '../util/aggregation-helper'; - -import {STRINGS} from '../config/strings'; +import {debugLogger} from '../../common/util/debug-logger'; +import {logger} from '../../common/util/logger'; import { AggregationParams, AggregationParamsSure, } from '../../common/types/manifest'; -const {AGGREGATING_NODE, AGGREGATING_OUTPUTS} = STRINGS; +import {aggregateInputsIntoOne} from '../util/aggregation-helper'; +import {memoizedLog} from '../util/log-memoize'; + +import {AggregationMetric} from '../types/aggregation'; + +import {STRINGS} from '../config/strings'; + +const { + AGGREGATING_NODE, + AGGREGATING_OUTPUTS, + UNKNOWN_PARAM, + CHECKING_AGGREGATION_METHOD, +} = STRINGS; /** * Gets `i`th element from all children outputs and collects them in single array. @@ -27,7 +38,7 @@ const getIthElementsFromChildren = (children: any, i: number) => { * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. */ -const temporalAggregation = (node: any, metrics: string[]) => { +const temporalAggregation = (node: any, metrics: AggregationMetric) => { const outputs: PluginParams[] = []; const values: any = Object.values(node.children); @@ -91,3 +102,52 @@ export const aggregate = (tree: any, aggregationParams: AggregationParams) => { return copyOfTree; }; + +/** + * Gets or stores aggregation metrics. + * @todo Remove these functions after resolving timeSync to be a builtin functionality. + */ +export const storeAggregateMetrics = ( + aggregationParams?: AggregationParams +) => { + if (aggregationParams?.metrics) { + metricManager.metrics = aggregationParams?.metrics; + } + + return metricManager.metrics; +}; + +/** + * Creates an encapsulated object to retrieve the metrics. + */ +const metricManager = (() => { + let metric: AggregationMetric; + + const manager = { + get metrics() { + return metric; + }, + set metrics(value: AggregationMetric) { + metric = value; + }, + }; + + return manager; +})(); + +/** + * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. + */ +export const getAggregationMethod = (unitName: string) => { + debugLogger.setExecutingPluginName(); + memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); + const aggregationMetricsStorage = storeAggregateMetrics(); + + if (`${unitName}` in aggregationMetricsStorage) { + return aggregationMetricsStorage[unitName].method; + } + + memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); + + return 'sum'; +}; From 061df462eaaeb24e915aabdc8a118940dfbbee63 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:22:49 +0400 Subject: [PATCH 379/863] feat(src): update load function to not deal with params --- src/common/lib/load.ts | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/common/lib/load.ts b/src/common/lib/load.ts index 02b44aef1..ade17795d 100644 --- a/src/common/lib/load.ts +++ b/src/common/lib/load.ts @@ -1,30 +1,18 @@ import {openYamlFileAsObject} from '../util/yaml'; -import {readAndParseJson} from '../../if-run/util/json'; -import {PARAMETERS} from '../../if-run/config'; import {STRINGS} from '../../if-run/config'; -import {Parameters} from '../../if-run/types/parameters'; - const {LOADING_MANIFEST} = STRINGS; /** - * Parses manifest file as an object. Checks if parameter file is passed via CLI, then loads it too. - * Returns context, tree and parameters (either the default one, or from CLI). + * Parses manifest file as an object. */ -export const load = async (inputPath: string, paramPath?: string) => { +export const load = async (inputPath: string) => { console.debug(LOADING_MANIFEST); const rawManifest = await openYamlFileAsObject(inputPath); - const parametersFromCli = - paramPath && - (await readAndParseJson(paramPath)); /** @todo validate json */ - const parameters = - parametersFromCli || - PARAMETERS; /** @todo PARAMETERS should be specified in parameterize only */ return { rawManifest, - parameters, }; }; From c0556cc52ddfb17abd31c96282a72ee6d5b6f3fd Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:24:25 +0400 Subject: [PATCH 380/863] fix(util): remove `SYNCING_PARAMETERS` from debugger log --- src/common/util/debug-logger.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts index 7babaaf3f..35dc77ea7 100644 --- a/src/common/util/debug-logger.ts +++ b/src/common/util/debug-logger.ts @@ -6,7 +6,6 @@ const logMessagesKeys: (keyof typeof STRINGS)[] = [ 'LOADING_MANIFEST', 'VALIDATING_MANIFEST', 'CAPTURING_RUNTIME_ENVIRONMENT_DATA', - 'SYNCING_PARAMETERS', 'CHECKING_AGGREGATION_METHOD', 'INITIALIZING_PLUGINS', 'INITIALIZING_PLUGIN', From a4a9fc50c76124ad3fe2e653b737b6720a4c0bb1 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:25:51 +0400 Subject: [PATCH 381/863] feat(src): update `getAggregationMethod` function call --- src/if-run/builtins/time-sync.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index 78b293e75..9c14b63a4 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -11,11 +11,10 @@ import { TimeParams, } from '@grnsft/if-core/types'; -import {parameterize} from '../lib/parameterize'; - import {validate} from '../../common/util/validations'; import {STRINGS} from '../config'; +import {getAggregationMethod} from '../lib/aggregate'; Settings.defaultZone = 'utc'; @@ -200,7 +199,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const inputKeys = Object.keys(input); return inputKeys.reduce((acc, key) => { - const method = parameterize.getAggregationMethod(key); + const method = getAggregationMethod(key); if (key === 'timestamp') { const perSecond = normalizeTimePerSecond(input.timestamp, i); @@ -254,7 +253,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { return acc; } - const method = parameterize.getAggregationMethod(metric); + const method = getAggregationMethod(metric); if (method === 'avg' || method === 'sum') { acc[metric] = 0; @@ -313,7 +312,7 @@ export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { const metrics = Object.keys(input); metrics.forEach(metric => { - const method = parameterize.getAggregationMethod(metric); + const method = getAggregationMethod(metric); acc[metric] = acc[metric] ?? 0; if (metric === 'timestamp') { From 84cfc8f64508c47ba3cedf667241543b8b55447d Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:28:09 +0400 Subject: [PATCH 382/863] test(src): update tests according to changes --- src/__tests__/common/lib/load.test.ts | 35 +--------------- src/__tests__/if-diff/lib/load.test.ts | 3 -- .../if-run/builtins/time-sync.test.ts | 17 ++++++++ src/__tests__/if-run/lib/aggregate.test.ts | 21 ++++++++-- .../if-run/util/aggregation-helper.test.ts | 41 +++++++++++++++---- src/__tests__/if-run/util/args.test.ts | 21 ---------- 6 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/__tests__/common/lib/load.test.ts b/src/__tests__/common/lib/load.test.ts index 43f6ee2af..a4f0289a4 100644 --- a/src/__tests__/common/lib/load.test.ts +++ b/src/__tests__/common/lib/load.test.ts @@ -1,6 +1,3 @@ -jest.mock('../../../if-run/util/json', () => - require('../../../__mocks__/json') -); jest.mock( 'mockavizta', () => ({ @@ -42,45 +39,17 @@ jest.mock('../../../common/util/yaml', () => ({ import {PluginParams} from '@grnsft/if-core/types'; -import {PARAMETERS} from '../../../if-run/config'; import {load} from '../../../common/lib/load'; describe('lib/load: ', () => { describe('load(): ', () => { - it('loads yaml with default parameters.', async () => { - const inputPath = 'load-default.yml'; - const paramPath = undefined; - - const result = await load(inputPath, paramPath); - - const expectedValue = { - rawManifest: 'raw-manifest', - parameters: PARAMETERS, - }; - - expect(result).toEqual(expectedValue); - }); - - it('loads yaml with custom parameters.', async () => { + it('successfully loads yaml.', async () => { const inputPath = 'load-default.yml'; - const paramPath = 'param-mock.json'; - const result = await load(inputPath, paramPath); + const result = await load(inputPath); const expectedValue = { rawManifest: 'raw-manifest', - parameters: { - 'mock-carbon': { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'mock-cpu': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - }, }; expect(result).toEqual(expectedValue); diff --git a/src/__tests__/if-diff/lib/load.test.ts b/src/__tests__/if-diff/lib/load.test.ts index f722757e5..ab69d7d76 100644 --- a/src/__tests__/if-diff/lib/load.test.ts +++ b/src/__tests__/if-diff/lib/load.test.ts @@ -1,6 +1,3 @@ -jest.mock('../../../if-run/util/json', () => - require('../../../__mocks__/json') -); jest.mock( 'mockavizta', () => ({ diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index ab58b3e34..e216690df 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -1,6 +1,9 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Settings, DateTime} from 'luxon'; +import {AggregationParams} from '../../../common/types/manifest'; + +import {storeAggregateMetrics} from '../../../if-run/lib/aggregate'; import {TimeSync} from '../../../if-run/builtins/time-sync'; import {STRINGS} from '../../../if-run/config'; @@ -51,6 +54,20 @@ jest.mock('luxon', () => { }); describe('builtins/time-sync:', () => { + beforeAll(() => { + const metricStorage: AggregationParams = { + metrics: { + carbon: {method: 'sum'}, + 'cpu/utilization': {method: 'sum'}, + 'time-reserved': {method: 'avg'}, + 'resources-total': {method: 'none'}, + }, + type: 'horizontal', + }; + + storeAggregateMetrics(metricStorage); + }); + describe('time-sync: ', () => { const basicConfig = { 'start-time': '2023-12-12T00:01:00.000Z', diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index 76de6300c..56488eea2 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -1,8 +1,21 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import {aggregate} from '../../../if-run/lib/aggregate'; +import {AggregationParams} from '../../../common/types/manifest'; + +import {aggregate, storeAggregateMetrics} from '../../../if-run/lib/aggregate'; describe('lib/aggregate: ', () => { + beforeAll(() => { + const metricStorage: AggregationParams = { + metrics: { + carbon: {method: 'sum'}, + }, + type: 'horizontal', + }; + + storeAggregateMetrics(metricStorage); + }); + describe('aggregate(): ', () => { it('returns tree if aggregation is missing.', () => { const tree = {}; @@ -44,7 +57,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], + metrics: {carbon: {method: 'sum'}}, type: 'horizontal', }); const expectedAggregated = { @@ -92,7 +105,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], + metrics: {carbon: {method: 'sum'}}, type: 'vertical', }); const expectedOutputs = [ @@ -153,7 +166,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: ['carbon'], + metrics: {carbon: {method: 'sum'}}, type: 'both', }); diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index 78c8c4aeb..5f8bc3325 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -1,7 +1,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {PluginParams} from '@grnsft/if-core/types'; +import {AggregationParams} from '../../../common/types/manifest'; + import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; +import {AggregationMetric} from '../../../if-run/types/aggregation'; +import {storeAggregateMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -9,10 +13,23 @@ const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; describe('util/aggregation-helper: ', () => { + beforeAll(() => { + const metricStorage: AggregationParams = { + metrics: { + carbon: {method: 'sum'}, + 'cpu/number-cores': {method: 'none'}, + 'cpu/utilization': {method: 'sum'}, + }, + type: 'horizontal', + }; + + storeAggregateMetrics(metricStorage); + }); + describe('aggregateInputsIntoOne(): ', () => { it('throws error if aggregation method is none.', () => { const inputs: PluginParams[] = []; - const metrics: string[] = ['cpu/number-cores']; + const metrics: AggregationMetric = {'cpu/number-cores': {method: 'none'}}; const isTemporal = false; expect.assertions(2); @@ -23,14 +40,16 @@ describe('util/aggregation-helper: ', () => { expect(error).toBeInstanceOf(InvalidAggregationMethodError); if (error instanceof InvalidAggregationMethodError) { - expect(error.message).toEqual(INVALID_AGGREGATION_METHOD(metrics[0])); + expect(error.message).toEqual( + INVALID_AGGREGATION_METHOD('cpu/number-cores') + ); } } }); it('throws error if aggregation criteria is not found in input.', () => { const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; - const metrics: string[] = ['cpu/utilization']; + const metrics: AggregationMetric = {'cpu/utilization': {method: 'sum'}}; const isTemporal = false; expect.assertions(2); @@ -41,7 +60,7 @@ describe('util/aggregation-helper: ', () => { expect(error).toBeInstanceOf(MissingAggregationParamError); if (error instanceof MissingAggregationParamError) { - expect(error.message).toEqual(METRIC_MISSING(metrics[0], 0)); + expect(error.message).toEqual(METRIC_MISSING('cpu/utilization', 0)); } } }); @@ -51,7 +70,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: string[] = ['carbon']; + const metrics: AggregationMetric = {carbon: {method: 'sum'}}; const isTemporal = true; const expectedValue = { @@ -68,7 +87,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: string[] = ['carbon']; + const metrics: AggregationMetric = {carbon: {method: 'sum'}}; const isTemporal = false; const expectedValue = { @@ -79,11 +98,19 @@ describe('util/aggregation-helper: ', () => { }); it('calculates average of metrics.', () => { + const metricStorage: AggregationParams = { + metrics: { + 'cpu/utilization': {method: 'avg'}, + }, + type: 'horizontal', + }; + + storeAggregateMetrics(metricStorage); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, 'cpu/utilization': 10}, {timestamp: '', duration: 10, 'cpu/utilization': 90}, ]; - const metrics: string[] = ['cpu/utilization']; + const metrics: AggregationMetric = {'cpu/utilization': {method: 'avg'}}; const isTemporal = false; const expectedValue = { diff --git a/src/__tests__/if-run/util/args.test.ts b/src/__tests__/if-run/util/args.test.ts index 5ea3dd03b..c43d49eb9 100644 --- a/src/__tests__/if-run/util/args.test.ts +++ b/src/__tests__/if-run/util/args.test.ts @@ -21,11 +21,6 @@ jest.mock('ts-command-line-args', () => ({ manifest: 'manifest-mock.yml', output: 'output-mock.yml', }; - case 'override-params': - return { - manifest: 'manifest-mock.yml', - 'override-params': 'override-params-mock.yml', - }; case 'not-yaml': return { manifest: 'mock.notyaml', @@ -119,22 +114,6 @@ describe('if-run/util/args: ', () => { expect(result).toEqual(expectedResult); }); - it('returns manifest with `paramPath`.', () => { - expect.assertions(1); - - process.env.result = 'override-params'; - - const result = parseIfRunProcessArgs(); - const manifestPath = 'manifest-mock.yml'; - const expectedResult = { - inputPath: path.normalize(`${processRunningPath}/${manifestPath}`), - paramPath: 'override-params-mock.yml', - outputOptions: {}, - }; - - expect(result).toEqual(expectedResult); - }); - it('returns manifest and output path.', () => { expect.assertions(1); From a83cc42e04ae6fb700361bf235633d680dcb9ef7 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 18:32:00 +0400 Subject: [PATCH 383/863] fix(config): remove message --- src/if-run/config/strings.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 0a9c1a455..cdbc7c8c2 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -3,8 +3,6 @@ export const STRINGS = { MISSING_PATH: "Initalization param 'path' is missing.", UNSUPPORTED_PLUGIN: "Plugin interface doesn't implement 'execute' or 'metadata' methods.", - OVERRIDE_WARNING: - '\n**WARNING**: You are overriding the IF default parameters file. Please be extremely careful of unintended side-effects in your plugin pipeline!\n', NOT_NATIVE_PLUGIN: (path: string) => ` You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, From 608bd8ee43006e34132d6e1435903bc27ba75222 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 19:17:42 +0400 Subject: [PATCH 384/863] fix(lib): fix aggregation method check --- src/if-run/lib/aggregate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 7ca0d3f42..a3d2d2bad 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -143,7 +143,7 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); const aggregationMetricsStorage = storeAggregateMetrics(); - if (`${unitName}` in aggregationMetricsStorage) { + if (aggregationMetricsStorage && `${unitName}` in aggregationMetricsStorage) { return aggregationMetricsStorage[unitName].method; } From ff605134fff235b04ee26f6884ed438a27948a4b Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 19:23:33 +0400 Subject: [PATCH 385/863] docs(src): update documentations --- Refactor-migration-guide.md | 5 ++++- src/if-run/builtins/README.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 0e662110a..f8da3d8b8 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -201,6 +201,8 @@ This is a builtin feature of IF, meaning it does not have to be initialized as a - `metrics`: which metrics do you want to aggregate? Every metric you provide here must exist in the output array. + - `method`: the aggregation method for the specied metric + - `type`: the options are `horizontal`, `vertical` or both. Horizontal aggregation is the type that condenses each time series into a single summary value. Vertical aggregation is aggregated across components. Here's what the config block should look like: @@ -208,7 +210,8 @@ Here's what the config block should look like: ```yaml aggregation: metrics: - - 'carbon' + 'carbon': + method: 'sum' type: 'both' ``` diff --git a/src/if-run/builtins/README.md b/src/if-run/builtins/README.md index df743e93c..ccacf83e5 100644 --- a/src/if-run/builtins/README.md +++ b/src/if-run/builtins/README.md @@ -165,7 +165,7 @@ Note that when `error-on-padding` is `true` no padding is performed and the plug ##### Resampling rules -Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `intervalk` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `params.ts`. The returned array is the final, synchronized time series at the desired temporal resolution. +Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `interval` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `aggregation` section in the manifest file. The returned array is the final, synchronized time series at the desired temporal resolution. #### Assumptions and limitations From 4a5e15deff68d2d7ef5bc092a2b67c2ecbbb4578 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 19:24:32 +0400 Subject: [PATCH 386/863] test(mocks): update mocks --- src/__mocks__/builtins/export-yaml.ts | 2 +- src/__mocks__/fs/index.ts | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/__mocks__/builtins/export-yaml.ts b/src/__mocks__/builtins/export-yaml.ts index 399bbdb28..85f54e966 100644 --- a/src/__mocks__/builtins/export-yaml.ts +++ b/src/__mocks__/builtins/export-yaml.ts @@ -162,6 +162,6 @@ export const aggregated = { }; export const aggregation = { - metrics: ['carbon'], + metrics: {carbon: {method: 'sum'}}, type: 'both', }; diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 6d4f61b8b..0f37a4291 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -10,27 +10,7 @@ export const readFile = async (filePath: string) => { return fs.readFileSync(updatedPath, 'utf8'); } - /** mock for util/json */ - if (filePath.includes('json-reject')) { - return Promise.reject(new Error('rejected')); - } - if (filePath.includes('json')) { - if (filePath.includes('param')) { - return JSON.stringify({ - 'mock-carbon': { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - aggregation: 'sum', - }, - 'mock-cpu': { - description: 'number of cores available', - unit: 'cores', - aggregation: 'none', - }, - }); - } - return JSON.stringify(filePath); } From 6dd3984a7548b6318c82f3fea7a721cf50338e81 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 11 Jul 2024 19:29:53 +0400 Subject: [PATCH 387/863] fix(manifests): update aggregation section in the manifests --- manifests/examples/pipelines/nesting.yml | 4 ++-- .../examples/pipelines/pipeline-with-aggregate.yml | 11 ++++++----- manifests/examples/pipelines/pipeline-with-mocks.yml | 3 ++- .../outputs/bugs/aggregation-error-wrong-metric.yaml | 3 ++- .../features/aggregate-failure-invalid-metrics.yaml | 3 ++- .../aggregate-failure-missing-metric-in-inputs.yaml | 3 ++- manifests/outputs/features/aggregate-horizontal.yaml | 3 ++- manifests/outputs/features/aggregate-vertical.yaml | 3 ++- manifests/outputs/features/aggregate.yaml | 3 ++- 9 files changed, 22 insertions(+), 14 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index ac413d1c6..9f034092f 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -6,9 +6,9 @@ tags: category: on-premise aggregation: metrics: - - "carbon" + "carbon": + method: sum type: "both" -params: initialize: plugins: "interpolate": diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index 7b689f1d8..a833bcb9b 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -3,19 +3,20 @@ description: a full pipeline with the aggregate feature enabled tags: aggregation: metrics: - - "carbon" + "carbon": + method: sum type: "both" initialize: plugins: "interpolate": method: Interpolation - path: 'builtin' + 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: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" "cpu-factor-to-wattage": method: Multiply path: builtin @@ -182,4 +183,4 @@ tree: cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west - requests: 180 \ No newline at end of file + requests: 180 diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 2cd23920e..9e4292f51 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -3,7 +3,8 @@ description: a full pipeline seeded with data from mock-observations feature tags: aggregation: metrics: - - "carbon" + "carbon": + method: sum type: "both" initialize: plugins: diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index 2bbfba839..ebf55ad73 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -5,7 +5,8 @@ description: >- tags: null aggregation: metrics: - - dummy-param + "dummy-param": + method: sum type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index ad145646f..870be308a 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -2,7 +2,8 @@ name: Aggregation description: Fails with invalid metric. aggregation: metrics: - - test + "test": + method: sum type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 09b2e9338..4a3da85ae 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -2,7 +2,8 @@ name: Aggregation description: Fails with missing metric in inputs. aggregation: metrics: - - cpu/utilization + "cpu/utilization": + method: sum type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index 2241815d2..f870bb4d2 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -2,7 +2,8 @@ name: Aggregation description: Apply `horizontal` aggregation aggregation: metrics: - - cpu/utilization + "cpu/utilization": + method: sum type: horizontal initialize: plugins: diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 0c7b32b6a..0fd5b170a 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -2,7 +2,8 @@ name: Aggregation description: Apply `vertical` aggregation aggregation: metrics: - - cpu/utilization + "cpu/utilization": + method: sum type: vertical initialize: plugins: diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index b58ac9031..35ab21423 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -2,7 +2,8 @@ name: Aggregation description: Apply both `horizontal` and `vertical` aggregations aggregation: metrics: - - cpu/utilization + "cpu/utilization": + method: sum type: both initialize: plugins: From 03275e34b7af97774bac05e6445860aa87409383 Mon Sep 17 00:00:00 2001 From: mouhamadalmounayar Date: Wed, 10 Jul 2024 12:59:49 +0200 Subject: [PATCH 388/863] feat(builtins): handle multiple matches in extractMatching function - Update output parameter documentation - Added corresponding test case Signed-off-by: mouhamadalmounayar --- src/__tests__/if-run/builtins/regex.test.ts | 27 +++++++++++++++++++++ src/if-run/builtins/regex/README.md | 3 ++- src/if-run/builtins/regex/index.ts | 6 ++--- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index 6ac6bd4e9..ac0594cd6 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -49,6 +49,33 @@ describe('builtins/regex: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully applies regex strategy with multiple matches', async () => { + const globalConfig = { + parameter: 'cloud/instance-type', + match: '/(?<=_)[^_]+?(?=_|$)/g', + output: 'cloud/instance-type', + }; + const regex = Regex(globalConfig); + + const expectedResult = [ + { + timestamp: '2023-08-06T00:00', + duration: 3600, + 'cloud/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'; diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index a0fa5d624..e424efca0 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -22,7 +22,8 @@ Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-26 ## Returns -- `output`: the first match of `parameter` with the parameter name with `match` defined in global config. +- `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 diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 45c65d6f6..bb97e8358 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -80,13 +80,13 @@ export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { } const regex = eval(match); - const matchedItem = input[parameter].match(regex); + const matchedItems = input[parameter].match(regex); - if (!matchedItem || !matchedItem[0]) { + if (!matchedItems || matchedItems.length === 0) { throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); } - return matchedItem[0]; + return matchedItems.join(' '); }; return { From 548c02917c7228b8c047a72405c8ff06dc8fc0a3 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:31:21 +0400 Subject: [PATCH 389/863] feat(util): add `parameter-metadata` into manifest validation schema --- src/common/util/validations.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 76b785d6d..98d017c29 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -56,6 +56,30 @@ export const manifestSchema = z.object({ path: z.string(), method: z.string(), 'global-config': z.record(z.string(), z.any()).optional(), + 'parameter-metadata': z + .object({ + inputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + }) + ) + .optional() + .nullable(), + outputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + }) + ) + .optional() + .nullable(), + }) + .optional(), }) ), }), From 6a2584952bc331cc2dc54b88617e5cb15a94c59e Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:33:08 +0400 Subject: [PATCH 390/863] feat(lib): add `parameter-metadata` as a second parameter of the plugins --- src/if-run/lib/initialize.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 5833787ba..5adcc2b18 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -79,7 +79,12 @@ const handModule = (method: string, pluginPath: string) => { const initPlugin = async ( initPluginParams: PluginOptions ): Promise => { - const {method, path, 'global-config': globalConfig} = initPluginParams; + const { + method, + path, + 'global-config': globalConfig, + 'parameter-metadata': parameterMetadata, + } = initPluginParams; console.debug(INITIALIZING_PLUGIN(method)); @@ -93,7 +98,7 @@ const initPlugin = async ( const plugin = await handModule(method, path); - return plugin(globalConfig); + return plugin(globalConfig, parameterMetadata); }; /** From 16517ade3ee98d6d51b3ec31685fca6a1011854b Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:36:06 +0400 Subject: [PATCH 391/863] feat(src): update `Coefficient`, `Copy`, `Divide` and `Exponent` plugins code and docs --- src/if-run/builtins/coefficient/README.md | 25 +++++++++++++++- src/if-run/builtins/coefficient/index.ts | 18 +++++++++++- src/if-run/builtins/copy-param/README.md | 36 ++++++++++++++++------- src/if-run/builtins/copy-param/index.ts | 13 ++++++-- src/if-run/builtins/divide/README.md | 15 +++++++++- src/if-run/builtins/divide/index.ts | 14 +++++++-- src/if-run/builtins/exponent/README.md | 15 +++++++++- src/if-run/builtins/exponent/index.ts | 8 ++++- 8 files changed, 125 insertions(+), 19 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index fb42e32a1..f0e16cb4b 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -16,6 +16,20 @@ Three parameters are required in global config: `input-parameter`, `coefficient` - `coefficient`: the value to multiply `input-parameter` by. - `output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. +### Plugin parameter metadata + +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: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe parameters of the `output-parameter` of the global config. Each parameter has: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs All of `input-parameters` must be available in the input array. @@ -68,6 +82,15 @@ initialize: input-parameter: 'carbon' coefficient: 3 output-parameter: 'carbon-product' + parameter-metadata: + inputs: + carbon: + description: "an amount of carbon emitted into the atmosphere" + unit: "gCO2e" + outputs: + carbon-product: + description: "a product of cabon property and the coefficient" + unit: "gCO2e" tree: children: child: @@ -105,4 +128,4 @@ The required parameters are: You can fix this error by checking you are providing valid values for each parameter in the config. -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/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 4b80be633..b6c743170 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -3,6 +3,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import { CoefficientConfig, ExecutePlugin, + PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; @@ -13,9 +14,24 @@ import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Coefficient = (globalConfig: CoefficientConfig): ExecutePlugin => { +export const Coefficient = ( + globalConfig: CoefficientConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs || { + carbon: { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + }, + }, + outputs: parametersMetadata?.outputs || { + 'carbon-product': { + description: 'a product of cabon property and the coefficient', + unit: 'gCO2e', + }, + }, }; /** diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 78ab5f656..8e6ef563a 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -39,6 +39,19 @@ Three parameters are required in config: `from` and `to` and `keep-existing`. `to`: a string defining the name to use to add the result of summing the input parameters to the output array. `keep-existing`: toggles whether to keep or delete the copied parameter (defined in `to`) +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameter of the `from` of the global config. The parameter has the following attributes: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameters of the `to` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs As with all plugins, `timestamp` and `duration` are required. The key passed to `from` must exist in the `input` data. @@ -47,24 +60,28 @@ As with all plugins, `timestamp` and `duration` are required. The key passed to The plugin adds a new parameter with the name defined in `to` to the `input` data. - ## Implementation To run the plugin, you must first create an instance of `Copy`. Then, you can call `execute()`. ```typescript -import { Copy } from "."; +import {Copy} from '.'; -const plugin = Copy({ 'keep-existing': true, from: 'from-param', to: 'to-param' }); +const plugin = Copy({ + 'keep-existing': true, + from: 'from-param', + to: 'to-param', +}); -const result = plugin.execute([{ - timestamp: "2023-12-12T00:00:13.000Z", +const result = plugin.execute([ + { + timestamp: '2023-12-12T00:00:13.000Z', duration: 30, 'from-param': 'hello', -}]) - -console.log(result) + }, +]); +console.log(result); ``` ## Example manifest @@ -90,9 +107,8 @@ tree: pipeline: - copy-param inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' original: 'hello' - ``` You can run this example by saving it as `./manifests/examples/copy.yml` and executing the following command from the project root: diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index cf21cfb8e..7f10bf696 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,6 +1,10 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParametersMetadata, + PluginParams, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -12,9 +16,14 @@ const {GlobalConfigError} = ERRORS; // 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): ExecutePlugin => { +export const Copy = ( + globalConfig: Record, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 99f8a23ee..98e5c0314 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -12,6 +12,19 @@ You provide the names of the values you want to divide, and a name to use to add - `denominator` - a parameter by a specific configured number or the number by which `numerator` is divided - `output` - the number to a configured output parameter +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameter of the `numerator` of the global config. The parameter has the following attributes: + + - `description`: description of the parameter + - `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 + ### Inputs - `numerator` - as input parameter, must be available in the input array @@ -42,7 +55,7 @@ const globalConfig = { denominator: 2, output: 'cpu/number-cores', }; -const divide = Divide(globalConfig); +const divide = Divide(globalConfig, parametersMetadata); const input = [ { diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 328c4ccff..3d09c130c 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -1,6 +1,11 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -9,9 +14,14 @@ import {STRINGS} from '../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; -export const Divide = (globalConfig: ConfigParams): ExecutePlugin => { +export const Divide = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index fa36319b8..ed1c74b35 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -16,6 +16,19 @@ Three parameters are required in global config: `input-parameter`, `exponent` an `exponent`: a number defining the exponent. `output-parameter`: a string defining the name to use to add the result of the exponent to the output array. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes:: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs `input-parameter` and `exponent` must be available in the input array. @@ -111,4 +124,4 @@ Every element in the `inputs` array must contain: This error arises when an invalid value is passed to `Exponent`. 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/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 800b2295e..a821c3a14 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -3,13 +3,19 @@ import { ExecutePlugin, PluginParams, ExponentConfig, + PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -export const Exponent = (globalConfig: ExponentConfig): ExecutePlugin => { +export const Exponent = ( + globalConfig: ExponentConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** From 9b3890ec96cdae98b35f7a9c656ec2de6b5b02d0 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:38:28 +0400 Subject: [PATCH 392/863] feat(src): update `Interpolation`, `Multiply`, `Regex` and `Sum` plugins and their docs --- src/if-run/builtins/interpolation/README.md | 13 ++++++++++ src/if-run/builtins/interpolation/index.ts | 16 +++++++++--- src/if-run/builtins/multiply/README.md | 15 +++++++++++- src/if-run/builtins/multiply/index.ts | 8 +++++- src/if-run/builtins/regex/README.md | 13 ++++++++++ src/if-run/builtins/regex/index.ts | 14 +++++++++-- src/if-run/builtins/sum/README.md | 27 ++++++++++++++++++++- src/if-run/builtins/sum/index.ts | 14 +++++++++-- 8 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index 74c8498a3..dedcfe5e9 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -25,6 +25,19 @@ To employ the `Interpolation` plugin, adhere to these steps: `x` and `y` arrays must be equal lengths. +## Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameters of the `output-parameter` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ## Input Parameters The plugin expects the following input parameters: diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 03239a004..60fe90e5b 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -6,6 +6,7 @@ import { PluginParams, ConfigParams, Method, + PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -20,7 +21,16 @@ const { WITHIN_THE_RANGE, } = STRINGS; -export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { +export const Interpolation = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { + const metadata = { + kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, + }; + /** * Executes the energy consumption calculation for an array of input parameters. */ @@ -189,9 +199,7 @@ export const Interpolation = (globalConfig: ConfigParams): ExecutePlugin => { }; return { - metadata: { - kind: 'execute', - }, + metadata, execute, }; }; diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 0ce42c7c0..08ebe9526 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -15,6 +15,19 @@ Two parameters are required in global config: `input-parameters` and `output-par `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs All of `input-parameters` must be available in the input array. @@ -41,7 +54,7 @@ const config = { outputParameter: 'energy-product', }; -const mult = Multiply(config); +const mult = Multiply(config, parametersMetadata); const result = await mult.execute([ { duration: 3600, diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 706e190ec..b51c1a426 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -3,13 +3,19 @@ import { ExecutePlugin, PluginParams, MultiplyConfig, + PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -export const Multiply = (globalConfig: MultiplyConfig): ExecutePlugin => { +export const Multiply = ( + globalConfig: MultiplyConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index cba3b6fe4..99685a15b 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -16,6 +16,19 @@ Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-26 - `match` - a regex by which needs to match the `parameter` - `output` - output parameter name in the input +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameter of the `parameter` value of the global config. The parameter has the following attributes: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameters of the `output` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs - `parameter` - as input parameter, must be available in the input array diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 45c65d6f6..59c10154c 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -1,6 +1,11 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -9,9 +14,14 @@ import {STRINGS} from '../../config'; const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -export const Regex = (globalConfig: ConfigParams): ExecutePlugin => { +export const Regex = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 997a6e1cf..4d861f2c9 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -15,6 +15,19 @@ Two parameters are required in global config: `input-parameters` and `output-par `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the result of summing the input parameters to the output array. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs All of `input-parameters` must be available in the input array. @@ -39,7 +52,7 @@ const config = { outputParameter: 'energy', }; -const sum = Sum(config); +const sum = Sum(config, parametersMetadata); const result = sum.execute([ { timestamp: '2021-01-01T00:00:00Z', @@ -66,6 +79,18 @@ initialize: global-config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy' + parameter-metadata: + inputs: + cpu/energy: + description: energy consumed by the cpu + unit: kWh + network/energy: + description: energy consumed by data ingress and egress + unit: kWh + outputs: + energy: + description: sum of energy components + unit: kWh tree: children: child: diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 62ba479e6..da642dd13 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -1,6 +1,11 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, SumConfig} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParams, + SumConfig, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -9,9 +14,14 @@ import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; const {MISSING_GLOBAL_CONFIG} = STRINGS; -export const Sum = (globalConfig: SumConfig): ExecutePlugin => { +export const Sum = ( + globalConfig: SumConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** From 61b089d8793226b3af0ecd4f0cf35e04ab339e5f Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:51:24 +0400 Subject: [PATCH 393/863] feat(src): update `Sci`, `SciEmbodied` and `Subtract` plugins and their docs --- src/if-run/builtins/csv-lookup/README.md | 4 +-- src/if-run/builtins/sci-embodied/README.md | 13 +++++++ src/if-run/builtins/sci-embodied/index.ts | 42 ++++++++++++++++++++-- src/if-run/builtins/sci/README.md | 13 +++++++ src/if-run/builtins/sci/index.ts | 29 +++++++++++++-- src/if-run/builtins/subtract/README.md | 13 +++++++ src/if-run/builtins/subtract/index.ts | 8 ++++- 7 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 61af5b292..317f3c897 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -84,7 +84,7 @@ const globalConfig = { }, output: ['cpu-tdp', 'tdp'], }; -const divide = CSVLookup(globalConfig); +const csvLookup = CSVLookup(globalConfig); const input = [ { @@ -173,4 +173,4 @@ The required parameters are: You can fix this error by checking you are providing valid values for each parameter in the config. -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-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index b4d71304b..21266fba7 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -10,6 +10,19 @@ Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/ Not Needed +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe the parameters of the `inputs`. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the `carbon-embodied` parameter. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs - `device/emissions-embodied`: the sum of Life Cycle Assessment (LCA) emissions for the component diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 2fffc09ed..e2a60edd6 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; -import {ExecutePlugin, PluginParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParametersMetadata, + PluginParams, +} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; @@ -7,9 +11,43 @@ import {STRINGS} from '../../config'; const {SCI_EMBODIED_ERROR} = STRINGS; -export const SciEmbodied = (): ExecutePlugin => { +export const SciEmbodied = ( + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs || { + 'device/emissions-embodied': { + description: 'total embodied emissions of some component', + unit: 'gCO2e', + }, + 'device/expected-lifespan': { + description: 'Total Expected Lifespan of the Component in Seconds', + unit: 'seconds', + }, + 'resources-reserved': { + description: 'resources reserved for an application', + unit: 'count', + }, + 'resources-total': { + description: 'total resources available', + unit: 'count', + }, + 'vcpus-allocated': { + description: 'number of vcpus allocated to particular resource', + unit: 'count', + }, + 'vcpus-total': { + description: 'total number of vcpus available on a particular resource', + unit: 'count', + }, + }, + outputs: parametersMetadata?.outputs || { + 'carbon-embodied': { + description: 'embodied emissions of the component', + unit: 'gCO2e', + }, + }, }; const METRICS = [ diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index d40ca93ed..4d9544ad2 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -8,6 +8,19 @@ - `functional-unit`: the name of the functional unit in which to express the carbon impact (required) +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe parameters of the `inputs`. Each parameter has: + + - `description`: description of the parameter + - `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 + ### Inputs - `carbon`: total carbon in gCO2eq (required) diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index f11f6c2b8..90cf55fb7 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -1,6 +1,11 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import { + ExecutePlugin, + PluginParams, + ConfigParams, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; @@ -14,9 +19,29 @@ const { ZERO_DIVISION, } = STRINGS; -export const Sci = (globalConfig: ConfigParams): ExecutePlugin => { +export const Sci = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs || { + carbon: { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + }, + 'functional-unit': { + description: + 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', + unit: 'none', + }, + }, + outputs: parametersMetadata?.outputs || { + sci: { + description: 'carbon expressed in terms of the given functional unit', + unit: 'gCO2e', + }, + }, }; /** diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 726f982b2..9916404bc 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -15,6 +15,19 @@ Two parameters are required in global config: `input-parameters` and `output-par `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the result of the diff to the output array. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description` and `unit` of the parameters of the inputs and outputs + +- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has the following attributes: + + - `description`: description of the parameter + - `unit`: unit of the parameter + +- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + ### Inputs All of `input-parameters` must be available in the input array. diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index bd5af0603..2598ecb8a 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -1,15 +1,21 @@ import {z} from 'zod'; import { ExecutePlugin, + PluginParametersMetadata, PluginParams, SubtractConfig, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => { +export const Subtract = ( + globalConfig: SubtractConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** From 2574f4ff93fb65d8adbc2eeb978825f8edbde0d8 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 12 Jul 2024 18:54:29 +0400 Subject: [PATCH 394/863] test(builtins): add `parametersMetadata` into the tests --- .../if-run/builtins/coefficient.test.ts | 12 +++-- .../if-run/builtins/copy-param.test.ts | 12 +++-- src/__tests__/if-run/builtins/divide.test.ts | 16 +++--- .../if-run/builtins/exponent.test.ts | 8 ++- .../if-run/builtins/interpolation.test.ts | 20 +++++--- .../if-run/builtins/multiply.test.ts | 8 ++- src/__tests__/if-run/builtins/regex.test.ts | 12 +++-- .../if-run/builtins/sci-embodied.test.ts | 6 ++- src/__tests__/if-run/builtins/sci.test.ts | 51 +++++++++++++------ .../if-run/builtins/subtract.test.ts | 8 ++- src/__tests__/if-run/builtins/sum.test.ts | 10 ++-- 11 files changed, 111 insertions(+), 52 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 1660edffe..8d99c3e87 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -14,7 +14,11 @@ describe('builtins/coefficient: ', () => { coefficient: 3, 'output-parameter': 'carbon-product', }; - const coefficient = Coefficient(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const coefficient = Coefficient(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -51,7 +55,7 @@ describe('builtins/coefficient: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - const coefficient = Coefficient(config!); + const coefficient = Coefficient(config!, parametersMetadata); expect.assertions(1); @@ -76,7 +80,7 @@ describe('builtins/coefficient: ', () => { coefficient: 3, 'output-parameter': 'carbon-product', }; - const coefficient = Coefficient(invalidConfig); + const coefficient = Coefficient(invalidConfig, parametersMetadata); const expectedMessage = '"input-parameter" parameter is string must contain at least 1 character(s). Error code: too_small.'; @@ -103,7 +107,7 @@ describe('builtins/coefficient: ', () => { coefficient: 10, 'output-parameter': '', }; - const coefficient = Coefficient(invalidConfig); + 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 8ac621538..952546505 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -14,7 +14,11 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const copy = Copy(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const copy = Copy(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -49,7 +53,7 @@ describe('builtins/copy: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - const copy = Copy(config!); + const copy = Copy(config!, parametersMetadata); expect.assertions(1); @@ -74,7 +78,7 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const copy = Copy(globalConfig); + const copy = Copy(globalConfig, parametersMetadata); expect.assertions(1); try { @@ -99,7 +103,7 @@ describe('builtins/copy: ', () => { from: 'original', to: 'copy', }; - const copy = Copy(globalConfig); + const copy = Copy(globalConfig, parametersMetadata); const expectedResult = [ { diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index b9d1d9456..e0a472998 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -14,7 +14,11 @@ describe('builtins/divide: ', () => { denominator: 2, output: 'cpu/number-cores', }; - const divide = Divide(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const divide = Divide(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -54,7 +58,7 @@ describe('builtins/divide: ', () => { denominator: 'duration', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig); + const divide = Divide(globalConfig, parametersMetadata); const input = [ { @@ -86,7 +90,7 @@ describe('builtins/divide: ', () => { denominator: 3600, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig); + const divide = Divide(globalConfig, parametersMetadata); expect.assertions(1); @@ -107,7 +111,7 @@ describe('builtins/divide: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - const divide = Divide(config!); + const divide = Divide(config!, parametersMetadata); expect.assertions(1); @@ -131,7 +135,7 @@ describe('builtins/divide: ', () => { denominator: 0, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig); + const divide = Divide(globalConfig, parametersMetadata); expect.assertions(1); @@ -159,7 +163,7 @@ describe('builtins/divide: ', () => { denominator: '10', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig); + 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 3b88df0cb..2e0419686 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -11,7 +11,11 @@ describe('builtins/exponent: ', () => { exponent: 3, 'output-parameter': 'energy', }; - const exponent = Exponent(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const exponent = Exponent(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -91,7 +95,7 @@ describe('builtins/exponent: ', () => { exponent: 4, 'output-parameter': 'carbon', }; - const exponent = Exponent(newConfig); + 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 8dbd1295c..6634556dd 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -22,6 +22,10 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; const inputs = [ { timestamp: '2023-07-06T00:00', @@ -29,7 +33,7 @@ describe('builtins/interpolation: ', () => { 'cpu/utilization': 45, }, ]; - const plugin = Interpolation(globalConfig); + const plugin = Interpolation(globalConfig, parametersMetadata); describe('init Interpolation: ', () => { it('initalizes object with properties.', async () => { @@ -59,7 +63,7 @@ describe('builtins/interpolation: ', () => { 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const plugin = Interpolation(globalConfig); + const plugin = Interpolation(globalConfig, parametersMetadata); const outputs = [ { @@ -75,7 +79,7 @@ describe('builtins/interpolation: ', () => { it('returns result when the `method` is `spline`.', () => { const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config); + const plugin = Interpolation(config, parametersMetadata); const outputs = [ { @@ -93,7 +97,7 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { method: Method.POLYNOMIAL, }); - const plugin = Interpolation(config); + const plugin = Interpolation(config, parametersMetadata); const outputs = [ { @@ -111,7 +115,7 @@ describe('builtins/interpolation: ', () => { const config = Object.assign({}, globalConfig, { x: [0, 10, 100, 50], }); - const plugin = Interpolation(config); + const plugin = Interpolation(config, parametersMetadata); const outputs = [ { @@ -147,7 +151,7 @@ describe('builtins/interpolation: ', () => { it('throws an when the global config is not provided.', () => { const config = undefined; - const plugin = Interpolation(config!); + const plugin = Interpolation(config!, parametersMetadata); expect.assertions(2); try { @@ -163,7 +167,7 @@ describe('builtins/interpolation: ', () => { x: [0, 10, 100], }); - const plugin = Interpolation(config); + const plugin = Interpolation(config, parametersMetadata); expect.assertions(2); try { @@ -198,7 +202,7 @@ describe('builtins/interpolation: ', () => { 'output-parameter': 'interpolation-result', }; const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); - const plugin = Interpolation(config); + const plugin = Interpolation(config, parametersMetadata); const inputs = [ { timestamp: '2023-07-06T00:00', diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index 07dedf5ea..b3856dfd4 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -10,7 +10,11 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const multiply = Multiply(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const multiply = Multiply(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -72,7 +76,7 @@ describe('builtins/multiply: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-product', }; - const multiply = Multiply(newConfig); + 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 6ac6bd4e9..6d039363d 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -14,7 +14,11 @@ describe('builtins/regex: ', () => { match: '^[^,]+', output: 'cpu/name', }; - const regex = Regex(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const regex = Regex(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -59,7 +63,7 @@ describe('builtins/regex: ', () => { match: '[^,]+/', output: 'cpu/name', }; - const regex = Regex(globalConfig); + const regex = Regex(globalConfig, parametersMetadata); const expectedResult = [ { @@ -90,7 +94,7 @@ describe('builtins/regex: ', () => { match: '^(^:)+', output: 'cpu/name', }; - const regex = Regex(globalConfig); + const regex = Regex(globalConfig, parametersMetadata); expect.assertions(1); @@ -113,7 +117,7 @@ describe('builtins/regex: ', () => { it('throws an error on missing global config.', async () => { const config = undefined; - const regex = Regex(config!); + 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 0c1b504ac..0e2c234f7 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -9,7 +9,11 @@ const {SCI_EMBODIED_ERROR} = STRINGS; describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { - const sciEmbodied = SciEmbodied(); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const sciEmbodied = SciEmbodied(parametersMetadata); 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 2d75ea170..0360149a9 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -6,7 +6,11 @@ const {MissingInputDataError} = ERRORS; describe('builtins/sci:', () => { describe('Sci: ', () => { - const sci = Sci({'functional-unit': 'users'}); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const sci = Sci({'functional-unit': 'users'}, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -17,9 +21,12 @@ describe('builtins/sci:', () => { describe('execute():', () => { it('returns a result with valid inputs.', async () => { - const sci = Sci({ - 'functional-unit': 'users', - }); + const sci = Sci( + { + 'functional-unit': 'users', + }, + parametersMetadata + ); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -48,9 +55,12 @@ describe('builtins/sci:', () => { }); it('returns the same result regardless of input duration.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); + const sci = Sci( + { + 'functional-unit': 'requests', + }, + parametersMetadata + ); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -96,9 +106,12 @@ describe('builtins/sci:', () => { }); it('throws exception on invalid functional unit data.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); + const sci = Sci( + { + 'functional-unit': 'requests', + }, + parametersMetadata + ); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -118,9 +131,12 @@ describe('builtins/sci:', () => { }); it('throws exception if functional unit value is not positive integer.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); + const sci = Sci( + { + 'functional-unit': 'requests', + }, + parametersMetadata + ); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', @@ -142,9 +158,12 @@ describe('builtins/sci:', () => { }); it('fallbacks to carbon value, if functional unit is 0.', async () => { - const sci = Sci({ - 'functional-unit': 'requests', - }); + const sci = Sci( + { + 'functional-unit': 'requests', + }, + parametersMetadata + ); const inputs = [ { timestamp: '2021-01-01T00:00:00Z', diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index 33ba137ab..134cebfa7 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -10,7 +10,11 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', }; - const subtract = Subtract(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const subtract = Subtract(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -72,7 +76,7 @@ describe('builtins/subtract: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-diff', }; - const subtract = Subtract(newConfig); + 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 d7530827c..9ccc64378 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -13,7 +13,11 @@ describe('builtins/sum: ', () => { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const sum = Sum(globalConfig); + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const sum = Sum(globalConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -52,7 +56,7 @@ describe('builtins/sum: ', () => { it('throws an error when global config is not provided.', () => { const config = undefined; - const sum = Sum(config!); + const sum = Sum(config!, parametersMetadata); expect.assertions(1); @@ -98,7 +102,7 @@ describe('builtins/sum: ', () => { 'input-parameters': ['carbon', 'other-carbon'], 'output-parameter': 'carbon-sum', }; - const sum = Sum(newConfig); + const sum = Sum(newConfig, parametersMetadata); const data = [ { From 029978dca6ddc049d9d7dc2602109a2b37cb6a03 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:36:07 +0400 Subject: [PATCH 395/863] feat(util): add explain and explainer properties in the manifest validation --- src/common/util/validations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 98d017c29..5298d7d74 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -38,6 +38,8 @@ export const manifestSchema = z.object({ }) .optional() .nullable(), + explainer: z.boolean().optional(), + explain: z.record(z.string(), z.any()).optional(), aggregation: z .object({ metrics: z.record( From 9c7a7f008178da57f1b96e8df24f1108654d3e78 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:41:30 +0400 Subject: [PATCH 396/863] feat(types): add `ExplainParams` type --- src/if-run/types/explain.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/if-run/types/explain.ts diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts new file mode 100644 index 000000000..b1b684882 --- /dev/null +++ b/src/if-run/types/explain.ts @@ -0,0 +1,7 @@ +import {ParameterMetadata} from '@grnsft/if-core/types'; + +export type ExplainParams = { + pluginName: string; + pluginData: {method: string; path: string}; + metadata: {inputs?: ParameterMetadata; outputs?: ParameterMetadata}; +}; From 4ecc3d7feaee148d32b71ce12175aea2e2634132 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:43:07 +0400 Subject: [PATCH 397/863] feat(lib): add `explain` logic --- src/if-run/lib/explain.ts | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/if-run/lib/explain.ts diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts new file mode 100644 index 000000000..add1a02b6 --- /dev/null +++ b/src/if-run/lib/explain.ts @@ -0,0 +1,44 @@ +import {ExplainParams} from '../types/explain'; + +/** + * Retrieves stored explain data. + */ +export const explain = () => storeExplainData.plugins; + +/** + * Manages the storage of explain data. + */ +const storeExplainData = (() => { + let plugin = {}; + + const pluginManager = { + get plugins() { + return plugin; + }, + set plugins(value: object) { + plugin = value; + }, + }; + + return pluginManager; +})(); + +/** + * Adds new explain data to the stored explain data. + */ +export const addExplainData = (params: ExplainParams) => { + const {pluginName, pluginData, metadata} = params; + const plugin = { + [pluginName]: { + method: pluginData.method, + path: pluginData.path, + inputs: metadata?.inputs || 'undefined', + outputs: metadata?.outputs || 'undefined', + }, + }; + + storeExplainData.plugins = { + ...storeExplainData.plugins, + ...plugin, + }; +}; From 2e35df3a1400d465614001b4646108ad647c6564 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:44:56 +0400 Subject: [PATCH 398/863] test(lib): add tests for --- src/__tests__/if-run/lib/explain.test.ts | 86 ++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/__tests__/if-run/lib/explain.test.ts diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts new file mode 100644 index 000000000..509c3ba32 --- /dev/null +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -0,0 +1,86 @@ +import {explain, addExplainData} from '../../../if-run/lib/explain'; + +describe('lib/explain: ', () => { + it('successfully adds explain data if `inputs` and `outputs` of `metadata` are `undefined`.', () => { + const mockData = { + pluginName: 'divide', + metadata: {kind: 'execute', inputs: undefined, outputs: undefined}, + pluginData: { + path: 'builtin', + method: 'Divide', + }, + }; + const expectedResult = { + divide: { + method: 'Divide', + path: 'builtin', + inputs: 'undefined', + outputs: 'undefined', + }, + }; + + addExplainData(mockData); + const result = explain(); + expect.assertions(1); + expect(result).toEqual(expectedResult); + }); + + it('successfully adds explain data if `inputs` and `outputs` of `metadata` are valid data.', () => { + const mockData = { + pluginName: 'sum', + metadata: { + kind: 'execute', + inputs: { + 'cpu/energy': { + unit: 'kWh', + description: 'energy consumed by the cpu', + }, + 'network/energy': { + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + }, + }, + outputs: { + 'energy-sum': { + unit: 'kWh', + description: 'sum of energy components', + }, + }, + }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + const expectedResult = { + divide: { + method: 'Divide', + path: 'builtin', + inputs: 'undefined', + outputs: 'undefined', + }, + sum: { + method: 'Sum', + path: 'builtin', + inputs: { + 'cpu/energy': { + unit: 'kWh', + description: 'energy consumed by the cpu', + }, + 'network/energy': { + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + }, + }, + outputs: { + 'energy-sum': {unit: 'kWh', description: 'sum of energy components'}, + }, + }, + }; + + addExplainData(mockData); + const result = explain(); + expect.assertions(1); + expect(result).toEqual(expectedResult); + }); +}); From 3a9023a07b40fa269f568a17793c95a38c45a3d4 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:48:48 +0400 Subject: [PATCH 399/863] feat(lib): add logic in the compute.ts to add explain data in the storage --- src/if-run/lib/compute.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index dde49d3f7..02cc8e0e4 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -7,6 +7,7 @@ import {STRINGS} from '../config/strings'; import {isExecute, isGroupBy} from '../types/interface'; import {ComputeParams, Node, Params} from '../types/compute'; +import {addExplainData} from './explain'; const {MERGING_DEFAULTS_WITH_INPUT_DATA, COMPUTING_PIPELINE_FOR_NODE} = STRINGS; @@ -78,6 +79,15 @@ const computeNode = async (node: Node, params: Params): Promise => { if (isExecute(plugin)) { inputStorage = await plugin.execute(inputStorage, nodeConfig); + + if (params.context.explainer) { + addExplainData({ + pluginName, + metadata: plugin.metadata, + pluginData: params.context.initialize.plugins[pluginName], + }); + } + debugLogger.setExecutingPluginName(); node.outputs = inputStorage; From 41f9816767b81b5970dba7c6746594d85bdd91d5 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 10:50:34 +0400 Subject: [PATCH 400/863] feat(src): add logic to compose explain data when it's true --- src/if-run/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 5ffb62ded..ab4e7df01 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -14,6 +14,7 @@ import {debugLogger} from '../common/util/debug-logger'; import {STRINGS} from './config'; import {STRINGS as COMMON_STRINGS} from '../common/config'; +import {explain} from './lib/explain'; const {EXITING_IF, STARTING_IF} = STRINGS; const {DISCLAIMER_MESSAGE} = COMMON_STRINGS; @@ -39,6 +40,9 @@ const impactEngine = async () => { const pluginStorage = await initialize(context.initialize.plugins); const computedTree = await compute(tree, {context, pluginStorage}); const aggregatedTree = aggregate(computedTree, context.aggregation); + + envManifest.explainer && (context.explain = explain()); + await exhaust(aggregatedTree, context, outputOptions); } catch (error) { if (error instanceof Error) { From e609d0c194e402d60a10e606b91fa7c7e7230977 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 11:13:29 +0400 Subject: [PATCH 401/863] fix(src): improve manifestData check --- src/if-csv/index.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index 94ede0bb4..72c33379c 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -18,14 +18,11 @@ const IfCsv = async () => { const pipedManifest = await parseManifestFromStdin(); const {manifest, output, params} = await parseIfCsvArgs(); const resolvedManifest = manifest || pipedManifest; - let manifestData: Manifest; if (resolvedManifest) { - if (pipedManifest) { - manifestData = (await YAML.load(pipedManifest!)) as Manifest; - } else { - manifestData = await getManifestData(manifest!); - } + const manifestData = pipedManifest + ? ((await YAML.load(pipedManifest!)) as Manifest) + : await getManifestData(manifest!); const options: CsvOptions = { tree: manifestData.tree, From 669a422f5ea0adb839cf68712ac6bdb784a1f593 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 11:25:41 +0400 Subject: [PATCH 402/863] fix(src): rename the `executeCsv` function into `generateCsv` --- src/__tests__/if-csv/util/helpers.test.ts | 14 +++++++------- src/if-csv/index.ts | 4 ++-- src/if-csv/util/helpers.ts | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 1859f4850..1781f5fbc 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -3,7 +3,7 @@ import * as fs from 'fs/promises'; import {stringify} from 'csv-stringify/sync'; import {ERRORS} from '@grnsft/if-core/utils'; -import {executeCsv, getManifestData} from '../../../if-csv/util/helpers'; +import {generateCsv, getManifestData} from '../../../if-csv/util/helpers'; import {CsvOptions} from '../../../if-csv/types/csv'; const {ManifestValidationError} = ERRORS; @@ -26,7 +26,7 @@ jest.mock('fs/promises', () => { }); describe('if-csv/util/helpers: ', () => { - describe('executeCsv(): ', () => { + describe('generateCsv(): ', () => { it('generates CSV file with correct data.', async () => { const outputPath = 'output'; const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; @@ -65,7 +65,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect(fs.writeFile).toHaveBeenCalledWith( 'output.csv', @@ -112,7 +112,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); @@ -162,7 +162,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); expect(fs.writeFile).toHaveBeenCalledWith( @@ -190,7 +190,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - const result = await executeCsv(options); + const result = await generateCsv(options); expect.assertions(1); expect(result).toEqual(stringify(matrix, {columns})); @@ -221,7 +221,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); expect(fs.writeFile).toHaveBeenCalledWith( diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index 72c33379c..602aabe1e 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -7,7 +7,7 @@ import {debugLogger} from '../common/util/debug-logger'; import {Manifest} from '../common/types/manifest'; import {logger} from '../common/util/logger'; -import {executeCsv, getManifestData} from './util/helpers'; +import {generateCsv, getManifestData} from './util/helpers'; import {parseIfCsvArgs} from './util/args'; import {CsvOptions} from './types/csv'; @@ -30,7 +30,7 @@ const IfCsv = async () => { outputPath: output, params, }; - const result = await executeCsv(options); + const result = await generateCsv(options); if (!output && result) { console.log(result); diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index 397293dd8..655611ff3 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -26,9 +26,9 @@ export const getManifestData = async (manifest: string) => { }; /** - * Executes a CSV generation based on the provided tree structure, context, output path, and params. + * Generates a CSV file based on the provided tree structure, context, output path, and params. */ -export const executeCsv = async (options: CsvOptions) => { +export const generateCsv = async (options: CsvOptions) => { const {tree, context, outputPath, params} = options; const columns = ['Path']; const matrix = [columns]; From 64e686d11f57c66bd36c3fe6841ce0a1fc8cd9a8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 17:59:29 +0400 Subject: [PATCH 403/863] feat(util): add observe, regroup and compute flags --- src/if-run/util/args.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/if-run/util/args.ts b/src/if-run/util/args.ts index 632a17fd6..09446dada 100644 --- a/src/if-run/util/args.ts +++ b/src/if-run/util/args.ts @@ -13,16 +13,16 @@ import {IfRunArgs, ProcessArgsOutputs} from '../types/process-args'; const {ParseCliParamsError, CliSourceFileError} = ERRORS; -const {IF_RUN} = CONFIG; +const {ARGS, HELP} = CONFIG; const {NO_OUTPUT} = STRINGS; const {SOURCE_IS_NOT_YAML, MANIFEST_IS_MISSING} = COMMON_STRINGS; /** - * Validates `ie` process arguments. + * Validates `if-run` process arguments. */ const validateAndParseProcessArgs = () => { try { - return parse(IF_RUN.ARGS, IF_RUN.HELP); + return parse(ARGS, HELP); } catch (error) { if (error instanceof Error) { throw new ParseCliParamsError(error.message); @@ -33,9 +33,8 @@ const validateAndParseProcessArgs = () => { }; /** - * 1. Parses process arguments like `manifest`, `output`, `override-params`, `help` and `debug`. - * 2. Checks if `help` param is provided, then logs help message and exits. - * 3. If output params are missing, warns user about it. + * 1. Parses process arguments for `if-run`. + * 2. If output params are missing, warns user about it. * 3. Otherwise checks if `manifest` param is there, then processes with checking if it's a yaml file. * If it is, then returns object containing full path. * 4. If params are missing or invalid, then rejects with `ParseCliParamsError`. @@ -47,6 +46,9 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { 'override-params': overrideParams, 'no-output': noOutput, debug, + observe, + regroup, + compute, } = validateAndParseProcessArgs(); if (!output && noOutput) { @@ -63,6 +65,9 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { }, ...(overrideParams && {paramPath: overrideParams}), debug, + observe, + regroup, + compute, }; } From 43bbe2ceabdb1d2d0c81bf0651959c24aba5d334 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 18:00:01 +0400 Subject: [PATCH 404/863] feat(types): add observe, regroup and compute flags to process args --- src/if-run/types/process-args.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/if-run/types/process-args.ts b/src/if-run/types/process-args.ts index a336b0af0..1a0b2e2a8 100644 --- a/src/if-run/types/process-args.ts +++ b/src/if-run/types/process-args.ts @@ -4,6 +4,9 @@ export interface IfRunArgs { 'override-params'?: string; 'no-output'?: boolean; debug?: boolean; + observe?: boolean; + regroup?: boolean; + compute?: boolean; } export interface ProcessArgsOutputs { @@ -14,6 +17,9 @@ export interface ProcessArgsOutputs { }; paramPath?: string; debug?: boolean; + observe?: boolean; + regroup?: boolean; + compute?: boolean; } export interface Options { From 609d21202045d3e64b3dbe6ed474ea53dbced384 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 18:00:23 +0400 Subject: [PATCH 405/863] feat(types): add observe, regroup and compute flags to compute --- src/if-run/types/compute.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index bfe294241..6777bf553 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -7,24 +7,28 @@ export type NodeConfig = { [key: string]: Record; }; -export type Params = { +export type PhasedPipeline = { + observe?: string[]; + regroup?: string[]; + compute?: string[]; +}; + +export type ComputeParams = { pluginStorage: PluginStorageInterface; context: Context; - pipeline?: string[]; + pipeline?: PhasedPipeline; config?: NodeConfig; defaults?: PluginParams; + observe?: Boolean; + regroup?: Boolean; + compute?: Boolean; }; export type Node = { children?: any; - pipeline?: string[]; + pipeline?: PhasedPipeline; config?: NodeConfig; defaults?: PluginParams; inputs?: PluginParams[]; outputs?: PluginParams[]; }; - -export type ComputeParams = { - context: Context; - pluginStorage: PluginStorageInterface; -}; From 48746cbfd3df80962c8462cc1d9ef8d765146cf5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:20:46 +0400 Subject: [PATCH 406/863] feat(lib): init regroup --- src/if-run/lib/regroup.ts | 87 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/if-run/lib/regroup.ts diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts new file mode 100644 index 000000000..810da7c2d --- /dev/null +++ b/src/if-run/lib/regroup.ts @@ -0,0 +1,87 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {validate} from '../../common/util/validations'; + +import {STRINGS} from '../config'; + +const {InvalidGroupingError} = ERRORS; + +const {INVALID_GROUP_KEY, REGROUP_ERROR} = STRINGS; + +/** + * Grouping strategy. + */ +export const Regroup = (inputs: PluginParams[], groups: string[]) => { + /** + * Creates structure to insert inputs by groups. + */ + const appendGroup = ( + value: PluginParams, + object: any, + groups: string[] + ): any => { + if (groups.length > 0) { + const group = groups.shift() as string; + + object.children = object.children ?? {}; + object.children[group] = object.children[group] ?? {}; + + if (groups.length === 0) { + if ( + object.children[group].inputs && + object.children[group].inputs.length > 0 + ) { + object.children[group].inputs.push(value); + } else { + object.children[group].inputs = [value]; + } + } + + appendGroup(value, object.children[group], groups); + } + + return object; + }; + + /** + * Validates config parameter. + */ + const validateGroups = (groups: string[]) => { + const inputData = { + groups, + }; + + const validationSchema = z.record( + z.string(), + z.array(z.string()).min(1, REGROUP_ERROR) + ); + + validate(validationSchema, inputData); + + return groups; + }; + + /** + * Interates over inputs, grabs config-group types values for each one. + * Based on grouping types, initializes the structure grouped structure. + */ + return inputs.reduce((acc, input) => { + const validtedGroups = validateGroups(groups); + const groupsWithData = validtedGroups.map(groupType => { + if (!input[groupType]) { + throw new InvalidGroupingError(INVALID_GROUP_KEY(groupType)); + } + + return input[groupType]; + }); + + acc = { + ...acc, + ...appendGroup(input, acc, groupsWithData), + }; + + return acc; + }, {} as any).children; +}; From f3af54fe03319e5e0ac6512821da412c0a1406f1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:34:41 +0400 Subject: [PATCH 407/863] feat(lib): tune compute to suport phased execution --- src/if-run/lib/compute.ts | 93 +++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index dde49d3f7..69ee0b5ff 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -1,19 +1,21 @@ -import {PluginParams, GroupByConfig} from '@grnsft/if-core/types'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {Regroup} from './regroup'; import {mergeObjects} from '../util/helpers'; import {debugLogger} from '../../common/util/debug-logger'; import {STRINGS} from '../config/strings'; -import {isExecute, isGroupBy} from '../types/interface'; -import {ComputeParams, Node, Params} from '../types/compute'; +import {isExecute} from '../types/interface'; +import {ComputeParams, Node, PhasedPipeline} from '../types/compute'; -const {MERGING_DEFAULTS_WITH_INPUT_DATA, COMPUTING_PIPELINE_FOR_NODE} = STRINGS; +const {MERGING_DEFAULTS_WITH_INPUT_DATA} = STRINGS; /** * Traverses all child nodes based on children grouping. */ -const traverse = async (children: any, params: Params) => { +const traverse = async (children: any, params: ComputeParams) => { for (const child in children) { await computeNode(children[child], params); } @@ -48,12 +50,13 @@ const mergeDefaults = ( * 4. Goes through the pipeline plugins, by checking if it's `execute` plugin. If so sets outputs. * If is a `groupby` plugin, it will return child components rather than outputs. * 5. Since after `groupby`, there are new child components, then computes them. - * Note: `pipeline` now equals the remaining plu.gins to apply to each child + * Note: `pipeline` now equals the remaining plugins to apply to each child */ -const computeNode = async (node: Node, params: Params): Promise => { - const pipeline = (node.pipeline || params.pipeline) as string[]; +const computeNode = async (node: Node, params: ComputeParams): Promise => { + const pipeline = node.pipeline || (params.pipeline as PhasedPipeline); const config = node.config || params.config; const defaults = node.defaults || params.defaults; + const noFlags = !params.observe && !params.regroup && !params.compute; if (node.children) { return traverse(node.children, { @@ -68,39 +71,55 @@ const computeNode = async (node: Node, params: Params): Promise => { inputStorage = mergeDefaults(inputStorage, defaults); const pipelineCopy = structuredClone(pipeline); - while (pipelineCopy.length !== 0) { - const pluginName = pipelineCopy.shift() as string; - const plugin = params.pluginStorage.get(pluginName); - const nodeConfig = config && config[pluginName]; - - console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); - debugLogger.setExecutingPluginName(pluginName); - - if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); - debugLogger.setExecutingPluginName(); - - node.outputs = inputStorage; + /** + * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. + */ + if ((noFlags || params.observe) && pipelineCopy.observe) { + while (pipelineCopy.observe.length !== 0) { + const pluginName = pipelineCopy.observe.shift() as string; + const plugin = params.pluginStorage.get(pluginName); + const nodeConfig = config && config[pluginName]; + + if (isExecute(plugin)) { + inputStorage = await plugin.execute(inputStorage, nodeConfig); + node.inputs = inputStorage; + } } + } - if (isGroupBy(plugin)) { - node.children = await plugin.execute( - inputStorage, - nodeConfig as GroupByConfig - ); - delete node.inputs; - delete node.outputs; - - await traverse(node.children, { - ...params, - pipeline: pipelineCopy, - defaults, - config, - }); + /** + * If regroup is requested, execute regroup strategy, delete child's inputs, outputs and empty regroup array. + */ + if ((noFlags || params.regroup) && pipeline.regroup) { + node.children = Regroup(inputStorage, pipeline.regroup); + delete node.inputs; + delete node.outputs; - debugLogger.setExecutingPluginName(); + return traverse(node.children, { + ...params, + pipeline: { + ...pipelineCopy, + regroup: undefined, + }, + defaults, + config, + }); + } - break; + /** + * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. + */ + if ((noFlags || params.compute) && pipelineCopy.compute) { + while (pipelineCopy.compute.length !== 0) { + const pluginName = pipelineCopy.compute.shift() as string; + const plugin = params.pluginStorage.get(pluginName); + const nodeConfig = config && config[pluginName]; + + if (isExecute(plugin)) { + inputStorage = await plugin.execute(inputStorage, nodeConfig); + node.outputs = inputStorage; + debugLogger.setExecutingPluginName(); + } } } }; From bfd58ead65b0092925b3920e987960fc6b027967 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:35:10 +0400 Subject: [PATCH 408/863] feat(config): add regroup error --- src/if-run/config/strings.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 5f5387c1f..942ae851f 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -27,7 +27,9 @@ export const STRINGS = { `Aggregation is not possible for given ${metric} since method is 'none'.`, METRIC_MISSING: (metric: string, index: number) => `Aggregation metric ${metric} is not found in inputs[${index}].`, - INVALID_GROUP_BY: (type: string) => `Invalid group ${type}.`, + INVALID_GROUP_KEY: (key: string) => `Invalid group ${key}.`, + REGROUP_ERROR: + 'Regroup phase is not an array or should contain at least one key.', REJECTING_OVERRIDE: (param: ManifestParameter) => `Rejecting overriding of canonical parameter: ${param.name}.`, INVALID_EXHAUST_PLUGIN: (pluginName: string) => From 5cbc710d03a8ee73037ef8cb16b5ec1344042152 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:36:49 +0400 Subject: [PATCH 409/863] feat(config): add phased flags to if-run --- src/if-run/config/config.ts | 111 ++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index 99ca34193..9bd39d89f 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -7,55 +7,68 @@ import {IfRunArgs} from '../types/process-args'; const {DISCLAIMER_MESSAGE} = STRINGS; export const CONFIG = { - IF_RUN: { - ARGS: { - manifest: { - type: String, - optional: true, - alias: 'm', - description: '[path to the input file]', - }, - output: { - type: String, - optional: true, - alias: 'o', - description: '[path to the output file]', - }, - 'override-params': { - type: String, - optional: true, - alias: 'p', - description: '[path to a parameter file that overrides our defaults]', - }, - 'no-output': { - type: Boolean, - optional: true, - alias: 'n', - description: '[prevent output to the console]', - }, - help: { - type: Boolean, - optional: true, - alias: 'h', - description: '[prints out the above help instruction]', - }, - debug: { - type: Boolean, - optional: true, - alias: 'd', - description: '[prints out debug logs to the console]', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - }, + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the input file]', + }, + output: { + type: String, + optional: true, + alias: 'o', + description: '[path to the output file]', + }, + 'override-params': { + type: String, + optional: true, + alias: 'p', + description: '[path to a parameter file that overrides our defaults]', + }, + 'no-output': { + type: Boolean, + optional: true, + alias: 'n', + description: '[prevent output to the console]', + }, + help: { + type: Boolean, + optional: true, + alias: 'h', + description: '[prints out the above help instruction]', + }, + debug: { + type: Boolean, + optional: true, + alias: 'd', + description: '[prints out debug logs to the console]', + }, + observe: { + type: Boolean, + optional: true, + description: '[executes only observe pipeline of the manifest]', + }, + regroup: { + type: Boolean, + optional: true, + description: '[executes only regroup pipeline of the manifest]', + }, + compute: { + type: Boolean, + optional: true, + description: '[executes only compute pipeline of the manifest]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], From f0df9f2249808d8b1d5370e7c60a04eb00cf66a7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:41:47 +0400 Subject: [PATCH 410/863] revert(builtins): remove groupby --- src/if-run/builtins/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts index d22491aca..a8ccc76fd 100644 --- a/src/if-run/builtins/index.ts +++ b/src/if-run/builtins/index.ts @@ -1,4 +1,3 @@ -export {GroupBy} from './group-by'; export {TimeSync} from './time-sync'; export {Interpolation} from './interpolation'; export {MockObservations} from './mock-observations'; From 7137fc641b7fe0522e017af603ad1c79e8c6b842 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:43:11 +0400 Subject: [PATCH 411/863] revert(builtins): drop groop-by plugin --- src/if-run/builtins/group-by.ts | 95 --------------------------------- 1 file changed, 95 deletions(-) delete mode 100644 src/if-run/builtins/group-by.ts diff --git a/src/if-run/builtins/group-by.ts b/src/if-run/builtins/group-by.ts deleted file mode 100644 index c8694d4cc..000000000 --- a/src/if-run/builtins/group-by.ts +++ /dev/null @@ -1,95 +0,0 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - GroupByPlugin, - PluginParams, - GroupByConfig, -} from '@grnsft/if-core/types'; - -import {STRINGS} from '../config'; - -import {validate} from '../../common/util/validations'; - -const {InvalidGroupingError, GlobalConfigError} = ERRORS; - -const {INVALID_GROUP_BY, MISSING_GLOBAL_CONFIG} = STRINGS; - -/** - * Plugin for inputs grouping. - */ -export const GroupBy = (): GroupByPlugin => { - const metadata = { - kind: 'groupby', - }; - - /** - * Creates structure to insert inputs by groups. - */ - const appendGroup = ( - value: PluginParams, - object: any, - groups: string[] - ): any => { - if (groups.length > 0) { - const group = groups.shift() as string; - - object.children = object.children ?? {}; - object.children[group] = object.children[group] ?? {}; - - if (groups.length === 0) { - if ( - object.children[group].inputs && - object.children[group].inputs.length > 0 - ) { - object.children[group].inputs.push(value); - } else { - object.children[group].inputs = [value]; - } - } - - appendGroup(value, object.children[group], groups); - } - - return object; - }; - - /** - * Interates over inputs, grabs config-group types values for each one. - * Based on grouping types, initializes the structure grouped structure. - */ - const execute = (inputs: PluginParams[], config: GroupByConfig) => - inputs.reduce((acc, input) => { - const validatedConfig = validateConfig(config); - const groups = validatedConfig.group.map(groupType => { - if (!input[groupType]) { - throw new InvalidGroupingError(INVALID_GROUP_BY(groupType)); - } - - return input[groupType]; - }); - - acc = { - ...acc, - ...appendGroup(input, acc, groups), - }; - - return acc; - }, {} as any).children; - - /** - * Validates config parameter. - */ - const validateConfig = (config: GroupByConfig) => { - if (!config) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); - } - - const schema = z.object({ - group: z.array(z.string()).min(1), - }); - - return validate>(schema, config); - }; - - return {metadata, execute}; -}; From 7a08226455b3451af25a8edece46f5373e2184b0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:45:55 +0400 Subject: [PATCH 412/863] feat(src): in if-run introduce phased execution flags --- src/if-run/index.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index fa5d17fa2..f7e3553a6 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -21,7 +21,15 @@ const {DISCLAIMER_MESSAGE} = COMMON_STRINGS; const impactEngine = async () => { const options = parseIfRunProcessArgs(); - const {inputPath, paramPath, outputOptions, debug} = options; + const { + inputPath, + paramPath, + outputOptions, + debug, + observe, + regroup, + compute: computeFlag, + } = options; debugLogger.overrideConsoleMethods(!!debug); @@ -35,7 +43,13 @@ const impactEngine = async () => { const {tree, ...context} = validateManifest(envManifest); parameterize.combine(context.params, parameters); const pluginStorage = await initialize(context.initialize.plugins); - const computedTree = await compute(tree, {context, pluginStorage}); + const computedTree = await compute(tree, { + context, + pluginStorage, + observe, + regroup, + compute: computeFlag, + }); const aggregatedTree = aggregate(computedTree, context.aggregation); await exhaust(aggregatedTree, context, outputOptions); } catch (error) { From 0fcd99109db89dad97cb347f6c264b92057be9ff Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:53:35 +0400 Subject: [PATCH 413/863] fix(util): in if-env args use args and help directly --- src/if-env/util/args.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-env/util/args.ts b/src/if-env/util/args.ts index 940fa7b7a..525ae14f6 100644 --- a/src/if-env/util/args.ts +++ b/src/if-env/util/args.ts @@ -12,7 +12,7 @@ import {STRINGS as COMMON_STRINGS} from '../../common/config'; import {IFEnvArgs} from '../types/process-args'; const {ParseCliParamsError, CliSourceFileError} = ERRORS; -const {IF_ENV} = CONFIG; +const {ARGS, HELP} = CONFIG; const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; /** @@ -20,7 +20,7 @@ const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; */ const validateAndParseIfEnvArgs = () => { try { - return parse(IF_ENV.ARGS, IF_ENV.HELP); + return parse(ARGS, HELP); } catch (error) { if (error instanceof Error) { throw new ParseCliParamsError(error.message); From 27cc830bfca8b53d23e9ac752b825db025c23704 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:54:24 +0400 Subject: [PATCH 414/863] refactor(config): remove if-env from config to make access to args easier --- src/if-env/config/config.ts | 62 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/if-env/config/config.ts b/src/if-env/config/config.ts index cc603d6de..f3f21b0c8 100644 --- a/src/if-env/config/config.ts +++ b/src/if-env/config/config.ts @@ -7,36 +7,34 @@ import {STRINGS} from '../../common/config'; const {DISCLAIMER_MESSAGE} = STRINGS; export const CONFIG = { - IF_ENV: { - ARGS: { - manifest: { - type: String, - optional: true, - alias: 'm', - description: '[path to the manifest file]', - }, - install: { - type: Boolean, - optional: true, - alias: 'i', - description: '[command to install package.json]', - }, - cwd: { - type: Boolean, - optional: true, - alias: 'c', - description: - '[command to generate the package.json in the command working directory]', - }, - } as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - }, + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + install: { + type: Boolean, + optional: true, + alias: 'i', + description: '[command to install package.json]', + }, + cwd: { + type: Boolean, + optional: true, + alias: 'c', + description: + '[command to generate the package.json in the command working directory]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Env Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, }; From 5a91cdec79442da3bdc03838864754c00b02c5aa Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:56:48 +0400 Subject: [PATCH 415/863] test(lib): init regroup instead of group-by --- .../if-run/builtins/group-by.test.ts | 177 ------------------ src/__tests__/if-run/lib/regroup.test.ts | 161 ++++++++++++++++ 2 files changed, 161 insertions(+), 177 deletions(-) delete mode 100644 src/__tests__/if-run/builtins/group-by.test.ts create mode 100644 src/__tests__/if-run/lib/regroup.test.ts diff --git a/src/__tests__/if-run/builtins/group-by.test.ts b/src/__tests__/if-run/builtins/group-by.test.ts deleted file mode 100644 index b59da6836..000000000 --- a/src/__tests__/if-run/builtins/group-by.test.ts +++ /dev/null @@ -1,177 +0,0 @@ -import {ERRORS} from '@grnsft/if-core/utils'; - -import {GroupBy} from '../../../if-run/builtins/group-by'; - -import {STRINGS} from '../../../if-run/config'; - -const {InvalidGroupingError, InputValidationError, GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, INVALID_GROUP_BY} = STRINGS; - -describe('builtins/group-by: ', () => { - describe('GroupBy: ', () => { - const plugin = GroupBy(); - - describe('init GroupBy: ', () => { - it('initalizes object with properties.', async () => { - expect(plugin).toHaveProperty('metadata'); - expect(plugin).toHaveProperty('execute'); - }); - }); - - describe('execute(): ', () => { - it('groups inputs correctly.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - const config = { - group: ['region', 'cloud/instance-type'], - }; - - const expectedOutput = { - 'uk-west': { - children: { - A1: { - inputs: [ - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T00:00', - }, - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T05:00', - }, - { - 'cloud/instance-type': 'A1', - region: 'uk-west', - timestamp: '2023-07-06T10:00', - }, - ], - }, - }, - }, - }; - - const result = plugin.execute(inputs, config); - expect(result).toEqual(expectedOutput); - }); - - it('throws an error when config is not provided.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - - const config = undefined; - - expect.assertions(2); - try { - plugin.execute(inputs, config!); - } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); - } - }); - - it('throws an error if `group` is an empty array.', () => { - const inputs = [ - { - timestamp: '2023-07-06T00:00', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T05:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - { - timestamp: '2023-07-06T10:00', - region: 'uk-west', - 'cloud/instance-type': 'A1', - }, - ]; - const config = { - group: ['region', 'cloud/instance-type'], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InvalidGroupingError); - expect(error).toEqual( - new InvalidGroupingError('Invalid group region.') - ); - } - }); - - it('throws an error if group type is missing from the input.', () => { - const inputs = [ - {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, - ]; - const config = { - group: [], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toEqual( - new InputValidationError( - '"group" parameter is array must contain at least 1 element(s). Error code: too_small.' - ) - ); - } - }); - - it('throws an error if input does not have required group type.', () => { - const inputs = [ - {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, - ]; - const config = { - group: ['region', 'cloud/instance-type', 'unknown'], - }; - - expect.assertions(2); - try { - plugin.execute(inputs, config); - } catch (error) { - expect(error).toBeInstanceOf(InvalidGroupingError); - expect(error).toEqual( - new InvalidGroupingError(INVALID_GROUP_BY(config.group[2])) - ); - } - }); - }); - }); -}); diff --git a/src/__tests__/if-run/lib/regroup.test.ts b/src/__tests__/if-run/lib/regroup.test.ts new file mode 100644 index 000000000..9f0b373ff --- /dev/null +++ b/src/__tests__/if-run/lib/regroup.test.ts @@ -0,0 +1,161 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../../if-run/config'; +import {Regroup} from '../../../if-run/lib/regroup'; + +const {InvalidGroupingError, InputValidationError} = ERRORS; +const {INVALID_GROUP_KEY} = STRINGS; + +describe('lib/regroup: ', () => { + describe('Regroup: ', () => { + it('groups inputs correctly.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + const groups = ['region', 'cloud/instance-type']; + + const expectedOutput = { + 'uk-west': { + children: { + A1: { + inputs: [ + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T00:00', + }, + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T05:00', + }, + { + 'cloud/instance-type': 'A1', + region: 'uk-west', + timestamp: '2023-07-06T10:00', + }, + ], + }, + }, + }, + }; + + const result = Regroup(inputs, groups); + expect(result).toEqual(expectedOutput); + }); + + it('throws an error when groups is not provided.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + + const groups = undefined; + + expect.assertions(2); + try { + Regroup(inputs, groups!); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"groups" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('throws an error if `group` is an empty array.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-west', + 'cloud/instance-type': 'A1', + }, + ]; + const groups = ['region', 'cloud/instance-type']; + + expect.assertions(2); + try { + Regroup(inputs, groups); + } catch (error) { + expect(error).toBeInstanceOf(InvalidGroupingError); + expect(error).toEqual( + new InvalidGroupingError('Invalid group region.') + ); + } + }); + + it('throws an error if group type is missing from the input.', () => { + const inputs = [ + {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, + ]; + const groups: any[] = []; + + expect.assertions(2); + try { + Regroup(inputs, groups); + } catch (error) { + expect(error).toBeInstanceOf(InputValidationError); + expect(error).toEqual( + new InputValidationError( + '"groups" parameter is regroup phase is not an array or should contain at least one key.. Error code: too_small.' + ) + ); + } + }); + + it('throws an error if input does not have required group type.', () => { + const inputs = [ + {timestamp: 1, region: 'uk-west', 'cloud/instance-type': 'A1'}, + ]; + const groups = ['region', 'cloud/instance-type', 'unknown']; + + expect.assertions(2); + try { + Regroup(inputs, groups); + } catch (error) { + expect(error).toBeInstanceOf(InvalidGroupingError); + expect(error).toEqual( + new InvalidGroupingError(INVALID_GROUP_KEY(groups[2])) + ); + } + }); + }); +}); From d00e842152590fd65d3bdaea1f73d800fe65d116 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 21:57:28 +0400 Subject: [PATCH 416/863] test(lib): fix test after introducing phased execution --- src/__tests__/if-run/lib/compute.test.ts | 57 +++++++++--------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index 4ed48b5a5..b019d4c67 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -19,12 +19,6 @@ describe('lib/compute: ', () => { kind: 'execute', }, }); - const mockGroupByPlugin = () => ({ - execute: (inputs: any) => ({children: inputs}), - metadata: { - kind: 'groupby', - }, - }); /** * Compute params. */ @@ -43,28 +37,13 @@ describe('lib/compute: ', () => { }, pluginStorage: pluginStorage().set('mock', mockExecutePlugin()), }; - const params: ComputeParams = { - // @ts-ignore - context: { - name: 'mock-name', - initialize: { - plugins: { - mock: { - path: 'mockavizta', - method: 'Mockavizta', - }, - }, - }, - }, - pluginStorage: pluginStorage().set('mock', mockGroupByPlugin()), - }; describe('compute(): ', () => { it('computes simple tree with execute plugin.', async () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, inputs: [ {timestamp: 'mock-timestamp-1', duration: 10}, {timestamp: 'mock-timestamp-2', duration: 10}, @@ -85,7 +64,7 @@ describe('lib/compute: ', () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: {regroup: ['duration']}, inputs: [ {timestamp: 'mock-timestamp-1', duration: 10}, {timestamp: 'mock-timestamp-2', duration: 10}, @@ -93,19 +72,24 @@ describe('lib/compute: ', () => { }, }, }; - const response = await compute(tree, params); - const expectedResult = mockGroupByPlugin().execute( - tree.children.mockChild.inputs - ); + const response = await compute(tree, paramsExecute); + const expectedResponse = { + '10': { + inputs: [ + {duration: 10, timestamp: 'mock-timestamp-1'}, + {duration: 10, timestamp: 'mock-timestamp-2'}, + ], + }, + }; - expect(response.children.mockChild.children).toEqual(expectedResult); + expect(response.children.mockChild.children).toEqual(expectedResponse); }); it('computes simple tree with defaults and execute plugin.', async () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, defaults: { 'cpu/name': 'Intel CPU', }, @@ -132,7 +116,7 @@ describe('lib/compute: ', () => { const tree = { children: { mockChild1: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, defaults: { 'cpu/name': 'Intel CPU', }, @@ -144,7 +128,7 @@ describe('lib/compute: ', () => { mockChild2: { children: { mockChild21: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, defaults: { 'cpu/name': 'Intel CPU', }, @@ -188,16 +172,17 @@ describe('lib/compute: ', () => { }, }; const response = await compute(tree, paramsExecute); - const expectedResult: any[] = []; - expect(response.children.mockChild.outputs).toEqual(expectedResult); + expect(response.children.mockChild.outputs).toBeUndefined(); }); it('computes simple tree with defaults and no inputs with execue plugin.', async () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: { + compute: ['mock'], + }, defaults: { carbon: 10, }, @@ -215,7 +200,9 @@ describe('lib/compute: ', () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: { + compute: ['mock'], + }, config: { 'cpu/name': 'Intel CPU', }, From 3a00c90d45d5c6637ef508b72448e28aeb265cc4 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 22:18:32 +0400 Subject: [PATCH 417/863] feat(manifests): remove newline in cloud metadata devide --- manifests/outputs/pipelines/cloud-metadata-divide.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml index f85725c5c..befa2d0cb 100644 --- a/manifests/outputs/pipelines/cloud-metadata-divide.yaml +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -39,7 +39,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" From 7bb370be53e20bb91d16da7a19012458e4bbf47d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 22:19:05 +0400 Subject: [PATCH 418/863] feat(manifests): init scenarios for phased execution --- manifests/examples/pipelines/scenario-1.yml | 35 +++++++++ manifests/examples/pipelines/scenario-2.yml | 52 +++++++++++++ manifests/examples/pipelines/scenario-3.yml | 86 +++++++++++++++++++++ manifests/examples/pipelines/scenario-4.yml | 46 +++++++++++ manifests/examples/pipelines/scenario-5.yml | 46 +++++++++++ 5 files changed, 265 insertions(+) create mode 100644 manifests/examples/pipelines/scenario-1.yml create mode 100644 manifests/examples/pipelines/scenario-2.yml create mode 100644 manifests/examples/pipelines/scenario-3.yml create mode 100644 manifests/examples/pipelines/scenario-4.yml create mode 100644 manifests/examples/pipelines/scenario-5.yml diff --git a/manifests/examples/pipelines/scenario-1.yml b/manifests/examples/pipelines/scenario-1.yml new file mode 100644 index 000000000..3882e8d02 --- /dev/null +++ b/manifests/examples/pipelines/scenario-1.yml @@ -0,0 +1,35 @@ +name: demo +description: demo for observe feat +tags: +initialize: + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: "builtin" + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:01 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 +tree: + children: + child: + pipeline: + observe: + - mock-observations + inputs: null + \ No newline at end of file diff --git a/manifests/examples/pipelines/scenario-2.yml b/manifests/examples/pipelines/scenario-2.yml new file mode 100644 index 000000000..569cbcb05 --- /dev/null +++ b/manifests/examples/pipelines/scenario-2.yml @@ -0,0 +1,52 @@ +name: regroup demo +description: +initialize: + plugins: + interpolate: + 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: "cpu-factor" +tree: + children: + child: + pipeline: + observe: + regroup: + - cloud/region + - cloud/instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/examples/pipelines/scenario-3.yml b/manifests/examples/pipelines/scenario-3.yml new file mode 100644 index 000000000..f5710b553 --- /dev/null +++ b/manifests/examples/pipelines/scenario-3.yml @@ -0,0 +1,86 @@ +name: groupby +description: successful path +initialize: + plugins: + "sum": + path: "builtin" + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy +tree: + children: + my-app: + pipeline: + observe: + regroup: + - cloud/instance-type + - cloud/region + compute: + children: + uk-west: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 + uk-east: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 9 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 1 diff --git a/manifests/examples/pipelines/scenario-4.yml b/manifests/examples/pipelines/scenario-4.yml new file mode 100644 index 000000000..151db09be --- /dev/null +++ b/manifests/examples/pipelines/scenario-4.yml @@ -0,0 +1,46 @@ +name: demo +description: +tags: +initialize: + plugins: + "sum": + path: "builtin" + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-sum + "coefficient": + path: "builtin" + method: Coefficient + global-config: + input-parameter: energy + coefficient: 2 + output-parameter: energy-doubled + "multiply": + path: "builtin" + method: Multiply + global-config: + input-parameters: ["cpu/utilization", "duration"] + output-parameter: "cpu-times-duration" +tree: + children: + child-1: + pipeline: + observe: + compute: + - sum + - coefficient + - multiply + defaults: + cpu/thermal-design-power: 100 + inputs: + - timestamp: "2023-12-12T00:00:00.000Z" + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + cpu/energy: 20 + network/energy: 10 + energy: 5 diff --git a/manifests/examples/pipelines/scenario-5.yml b/manifests/examples/pipelines/scenario-5.yml new file mode 100644 index 000000000..6990c33e3 --- /dev/null +++ b/manifests/examples/pipelines/scenario-5.yml @@ -0,0 +1,46 @@ +name: demo +description: +tags: +initialize: + plugins: + mock-observations: + kind: plugin + method: MockObservations + path: "builtin" + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:01 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 + sum: + path: "builtin" + method: Sum + global-config: + input-parameters: + - cpu/utilization + - memory/utilization + output-parameter: util-sum +tree: + children: + child: + pipeline: + observe: + - mock-observations + regroup: + - cloud/instance-type + compute: + - sum + inputs: null From 8ef9edd17b800637984f1e314dbcbcff73bb5258 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 17 Jul 2024 22:29:42 +0400 Subject: [PATCH 419/863] fix(manifests): newline at the end of scenario 1 --- manifests/examples/pipelines/scenario-1.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/manifests/examples/pipelines/scenario-1.yml b/manifests/examples/pipelines/scenario-1.yml index 3882e8d02..9ab2d20f4 100644 --- a/manifests/examples/pipelines/scenario-1.yml +++ b/manifests/examples/pipelines/scenario-1.yml @@ -32,4 +32,3 @@ tree: observe: - mock-observations inputs: null - \ No newline at end of file From d2d2c210447e6d61a78e7f03c00fe2e5771bcc75 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 17 Jul 2024 23:03:43 +0400 Subject: [PATCH 420/863] chore(manifests): updated some manifests for phased execution --- manifests/examples/pipelines/nesting.yml | 92 +++++++------- .../pipelines/pipeline-with-mocks.yml | 117 +++++------------- 2 files changed, 82 insertions(+), 127 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index 9f034092f..29023983e 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -95,17 +95,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -145,17 +146,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -197,17 +199,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 @@ -247,17 +250,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 9e4292f51..4a2651e1f 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -98,29 +98,27 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - "group-by": - path: builtin - method: GroupBy tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - instance-type + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -130,48 +128,25 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 30 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 40 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 50 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -181,27 +156,3 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 40 - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 50 - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 60 From b20c3bd093c1b103eb014a842e386e1989b6f28f Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 18 Jul 2024 18:04:50 +0400 Subject: [PATCH 421/863] fix(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f01b0fb13..57230e0e6 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.10", + "@grnsft/if-core": "^0.0.12", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1185,9 +1185,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.10.tgz", - "integrity": "sha512-WHCdr7H/dFO9gT5fbjrthjOU+4RoLZ5P1F84pbGwJiKLmcU7dvYRuNQKDVIQQ7YJfZl76KSaS7sYgqA+QG8Wpw==", + "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==", "dependencies": { "typescript": "^5.1.6" }, diff --git a/package.json b/package.json index 7c80610c5..3a0f5af32 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.10", + "@grnsft/if-core": "^0.0.12", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 5a7847687601c86358f646b3e5706ad1655a2c70 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 18 Jul 2024 18:05:52 +0400 Subject: [PATCH 422/863] test(builtins): update rege test --- src/__tests__/if-run/builtins/regex.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index 795bbd36d..ea45c49d1 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -59,7 +59,7 @@ describe('builtins/regex: ', () => { match: '/(?<=_)[^_]+?(?=_|$)/g', output: 'cloud/instance-type', }; - const regex = Regex(globalConfig); + const regex = Regex(globalConfig, parametersMetadata); const expectedResult = [ { From ae7ad734f6b2f6ad145e7c24295ef540c48af081 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 18 Jul 2024 18:16:38 +0400 Subject: [PATCH 423/863] fix(src): rename `MissingPluginDependenciesError` custom error --- src/if-env/util/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-env/util/helpers.ts b/src/if-env/util/helpers.ts index 17827f58a..e8ff24914 100644 --- a/src/if-env/util/helpers.ts +++ b/src/if-env/util/helpers.ts @@ -16,7 +16,7 @@ import {STRINGS} from '../config'; import {EnvironmentOptions} from '../types/if-env'; -const {MissingPluginDependenciesError} = ERRORS; +const {MissingManifestDependenciesError} = ERRORS; const { FAILURE_MESSAGE_DEPENDENCIES, FAILURE_MESSAGE, @@ -38,7 +38,7 @@ export const getOptionsFromArgs = async (commandArgs: { const dependencies = rawManifest?.execution?.environment.dependencies || []; if (!dependencies.length) { - throw new MissingPluginDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); + throw new MissingManifestDependenciesError(FAILURE_MESSAGE_DEPENDENCIES); } const pathsWithVersion = extractPathsWithVersion(plugins, dependencies); From 26fc92dd91500e510d434f29e87833c76cf6d24c Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 19 Jul 2024 10:55:26 +0400 Subject: [PATCH 424/863] revert(manifests): drop not builtin divide --- manifests/outputs/divide.yaml | 91 ----------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 manifests/outputs/divide.yaml diff --git a/manifests/outputs/divide.yaml b/manifests/outputs/divide.yaml deleted file mode 100644 index 85c681d1f..000000000 --- a/manifests/outputs/divide.yaml +++ /dev/null @@ -1,91 +0,0 @@ -name: divide -description: success path -tags: null -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - global-config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: - - cpu-cores-utilized - - vcpus-allocated - divide: - path: builtin - method: Divide - global-config: - numerator: vcpus-allocated - denominator: 2 - output: cpu/number-cores -execution: - command: >- - /home/joe/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /home/joe/Code/if/src/index.ts -m ./manifests/plugins/divide/success.yml -o - ./manifests/outputs/divide - environment: - if-version: 0.4.0 - os: linux - os-version: 5.15.0-113-generic - node-version: 21.4.0 - date-time: 2024-07-03T14:02:26.789Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child: - pipeline: - - cloud-metadata - - divide - config: - divide: null - defaults: - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 - outputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - vcpus-allocated: 2 - cpu/number-cores: 1 From 145814b62bd07bfeb7698d7e7bf95fcf858a0e62 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 19 Jul 2024 10:56:04 +0400 Subject: [PATCH 425/863] feat(manifests): add outputs to pipelines --- manifests/outputs/pipelines/generics.yaml | 239 +++ .../outputs/pipelines/instance-metadata.yaml | 97 + manifests/outputs/pipelines/nesting.yaml | 1691 +++++++++++++++++ .../outputs/pipelines/pipeline-teads-sci.yaml | 283 +++ .../pipelines/pipeline-with-aggregate.yaml | 890 +++++++++ .../pipelines/pipeline-with-mocks.yaml | 910 +++++++++ manifests/outputs/pipelines/sci.yaml | 297 +++ manifests/outputs/pipelines/teads-curve.yaml | 187 ++ manifests/outputs/pipelines/zeros.yaml | 199 ++ 9 files changed, 4793 insertions(+) create mode 100644 manifests/outputs/pipelines/generics.yaml create mode 100644 manifests/outputs/pipelines/instance-metadata.yaml create mode 100644 manifests/outputs/pipelines/nesting.yaml create mode 100644 manifests/outputs/pipelines/pipeline-teads-sci.yaml create mode 100644 manifests/outputs/pipelines/pipeline-with-aggregate.yaml create mode 100644 manifests/outputs/pipelines/pipeline-with-mocks.yaml create mode 100644 manifests/outputs/pipelines/sci.yaml create mode 100644 manifests/outputs/pipelines/teads-curve.yaml create mode 100644 manifests/outputs/pipelines/zeros.yaml diff --git a/manifests/outputs/pipelines/generics.yaml b/manifests/outputs/pipelines/generics.yaml new file mode 100644 index 000000000..4f724754e --- /dev/null +++ b/manifests/outputs/pipelines/generics.yaml @@ -0,0 +1,239 @@ +name: generics +description: >- + a pipeline that does arbitrary calculations using our generic arithmetic + builtins +tags: null +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + coefficient: + path: builtin + method: Coefficient + global-config: + input-parameter: cpu-energy-kwh + coefficient: 2 + output-parameter: energy-doubled + multiply: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu/utilization + - duration + output-parameter: cpu-times-duration +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/generics.yml -o + manifests/outputs/pipelines/generics + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-17T20:30:54.004Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - coefficient + - multiply + config: null + defaults: + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 10 + energy: 5 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.75 + cpu-wattage: 75 + cpu-wattage-times-duration: 75 + cpu-energy-raw: 0.000020833333333333333 + vcpu-ratio: 8 + cpu-energy-kwh: 0.0000026041666666666666 + energy-doubled: 0.000005208333333333333 + cpu-times-duration: 50 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4275 + cpu-wattage: 42.75 + cpu-wattage-times-duration: 213.75 + cpu-energy-raw: 0.000059375 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000007421875 + energy-doubled: 0.00001484375 + cpu-times-duration: 100 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 261.625 + cpu-energy-raw: 0.00007267361111111111 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009084201388888889 + energy-doubled: 0.000018168402777777778 + cpu-times-duration: 105 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 1121.25 + cpu-energy-raw: 0.00031145833333333335 + vcpu-ratio: 8 + cpu-energy-kwh: 0.00003893229166666667 + energy-doubled: 0.00007786458333333334 + cpu-times-duration: 450 diff --git a/manifests/outputs/pipelines/instance-metadata.yaml b/manifests/outputs/pipelines/instance-metadata.yaml new file mode 100644 index 000000000..fbff57e45 --- /dev/null +++ b/manifests/outputs/pipelines/instance-metadata.yaml @@ -0,0 +1,97 @@ +name: csv-demo +description: null +tags: null +initialize: + plugins: + cloud-instance-metadata: + path: builtin + method: CSVLookup + global-config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: '*' + extract-processor-name: + path: builtin + method: Regex + global-config: + parameter: cpu-model-name + match: /^([^,])+/g + output: cpu/name +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/instance-metadata.yml -o + manifests/outputs/pipelines/instance-metadata + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:31:27.411Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - cloud-instance-metadata + - extract-processor-name + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + cpu/energy: 0.001 + cloud/provider: gcp + cloud/region: asia-east + cloud/instance-type: Standard_A1_v2 + cpu-cores-available: 52 + cpu-cores-utilized: 1 + cpu-manufacturer: Intel + cpu-model-name: >- + 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 + cpu-tdp: 205 + gpu-count: nan + gpu-model-name: nan + gpu-tdp: nan + memory-available: 2 + cpu/name: Intel® Xeon® Platinum 8272CL diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml new file mode 100644 index 000000000..a29ceada2 --- /dev/null +++ b/manifests/outputs/pipelines/nesting.yaml @@ -0,0 +1,1691 @@ +name: nesting +description: a manifest that includes nested child components +tags: + kind: web + complexity: moderate + category: on-premise +aggregation: + metrics: + carbon: + method: sum + type: both +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/nesting.yml -o + manifests/outputs/pipelines/nesting + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:32:05.687Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-0: + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + requests: 50 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 60 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 70 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + requests: 55 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 66 + network/energy: 0.0000018 + requests: 98 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-allocated: 1.7999999999999998 + vcpus-total: 14.399999999999999 + cpu-factor: 1.0919999999999999 + cpu-wattage: 109.19999999999999 + cpu-wattage-times-duration: 246 + cpu-energy-raw: 0.00006833333333333335 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008541666666666668 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.006833333333333334 + carbon: 0.0068434614408929475 + sci: 0.00006983123919278518 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 7.714285714285713e-7 + requests: 52 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-allocated: 0.7714285714285714 + vcpus-total: 6.171428571428571 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.0001028924208718729 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 4.952380952380952e-7 + requests: 33.666666666666664 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-allocated: 0.4952380952380952 + vcpus-total: 3.9619047619047616 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.0001544881286073813 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 9.166666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0005673927632489277 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 9.166666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0005673927632489277 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 9.166666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0005673927632489277 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 9.166666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0005673927632489277 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 9.166666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0005673927632489277 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + network/energy: 1.e-7 + requests: 5.5 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-allocated: 0.1 + vcpus-total: 0.8 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0005673927632489276 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04652112950279046 + child-1: + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + requests: 10 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 90 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 30 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + requests: 22 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 66 + network/energy: 0.0000018 + requests: 82 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-allocated: 1.7999999999999998 + vcpus-total: 14.399999999999999 + cpu-factor: 1.0919999999999999 + cpu-wattage: 109.19999999999999 + cpu-wattage-times-duration: 246 + cpu-energy-raw: 0.00006833333333333335 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008541666666666668 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.006833333333333334 + carbon: 0.0068434614408929475 + sci: 0.0000834568468401579 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 7.714285714285713e-7 + requests: 35.14285714285714 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-allocated: 0.7714285714285714 + vcpus-total: 6.171428571428571 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.00015224732194049487 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 4.952380952380952e-7 + requests: 14.323809523809523 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-allocated: 0.4952380952380952 + vcpus-total: 3.9619047619047616 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.000363108733129716 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 3.6666666666666665 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 3.6666666666666665 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 3.6666666666666665 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 3.6666666666666665 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 3.6666666666666665 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + network/energy: 1.e-7 + requests: 2.1999999999999997 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-allocated: 0.1 + vcpus-total: 0.8 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0014184819081223194 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04652112950279046 + child-2: + children: + child-2-0: + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + requests: 50 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 65 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 80 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + requests: 40 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 66 + network/energy: 0.0000018 + requests: 102 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-allocated: 1.7999999999999998 + vcpus-total: 14.399999999999999 + cpu-factor: 1.0919999999999999 + cpu-wattage: 109.19999999999999 + cpu-wattage-times-duration: 246 + cpu-energy-raw: 0.00006833333333333335 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008541666666666668 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.006833333333333334 + carbon: 0.0068434614408929475 + sci: 0.00006709275922444067 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 7.714285714285713e-7 + requests: 58.71428571428572 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-allocated: 0.7714285714285714 + vcpus-total: 6.171428571428571 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.0000911261343001502 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 4.952380952380952e-7 + requests: 36.952380952380956 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-allocated: 0.4952380952380952 + vcpus-total: 3.9619047619047616 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.00014075142645028166 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + network/energy: 1.e-7 + requests: 4 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-allocated: 0.1 + vcpus-total: 0.8 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0007801650494672755 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04652112950279046 + child-2-1: + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-allocated: 1 + vcpus-total: 8 + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + requests: 50 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 50 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + requests: 60 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + requests: 40 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 66 + network/energy: 0.0000018 + requests: 90 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-allocated: 1.7999999999999998 + vcpus-total: 14.399999999999999 + cpu-factor: 1.0919999999999999 + cpu-wattage: 109.19999999999999 + cpu-wattage-times-duration: 246 + cpu-energy-raw: 0.00006833333333333335 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008541666666666668 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.006833333333333334 + carbon: 0.0068434614408929475 + sci: 0.00007603846045436609 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 7.714285714285713e-7 + requests: 44.28571428571428 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-allocated: 0.7714285714285714 + vcpus-total: 6.171428571428571 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.00012081561676568304 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + network/energy: 4.952380952380952e-7 + requests: 28.38095238095238 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-allocated: 0.4952380952380952 + vcpus-total: 3.9619047619047616 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.0001832602465191587 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + network/energy: 1.6666666666666668e-7 + requests: 6.666666666666666 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-allocated: 0.16666666666666666 + vcpus-total: 1.3333333333333333 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0007801650494672756 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + network/energy: 1.e-7 + requests: 4 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-allocated: 0.1 + vcpus-total: 0.8 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0007801650494672755 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + network/energy: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-allocated: 0 + vcpus-total: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04652112950279046 + outputs: + - carbon: 0.013686922881785895 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.010700811770674782 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.010402200659563673 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.010402200659563675 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.010402200659563675 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.010402200659563675 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.010402200659563675 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.010402200659563675 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.006241320395738204 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.09304225900558093 + outputs: + - carbon: 0.02737384576357179 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.021401623541349564 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.020804401319127346 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.02080440131912735 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.02080440131912735 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.02080440131912735 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.02080440131912735 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.02080440131912735 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.012482640791476408 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.18608451801116185 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml new file mode 100644 index 000000000..fc8e6d0f8 --- /dev/null +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -0,0 +1,283 @@ +name: pipeline-teads-sci +description: >- + a full pipeline seeded with some hardcoded input data and yielding an SCI + score +tags: null +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + sci: + path: builtin + method: Sci + global-config: + functional-unit: component + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-teads-sci.yml -o + manifests/outputs/pipelines/pipeline-teads-sci + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:32:50.994Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - sci + config: null + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + component: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + component: 1 + cpu-factor: 0.75 + cpu-wattage: 75 + cpu-wattage-times-duration: 75 + cpu-energy-raw: 0.000020833333333333333 + vcpu-ratio: 8 + cpu-energy-kwh: 0.0000026041666666666666 + carbon-embodied: 0.0000020256215119228817 + carbon-operational: 0.0020833333333333333 + carbon: 0.002085358954845256 + sci: 0.002085358954845256 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + component: 1 + cpu-factor: 0.4275 + cpu-wattage: 42.75 + cpu-wattage-times-duration: 213.75 + cpu-energy-raw: 0.000059375 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000007421875 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.0059375 + carbon: 0.005947628107559615 + sci: 0.005947628107559615 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + component: 1 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 261.625 + cpu-energy-raw: 0.00007267361111111111 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009084201388888889 + carbon-embodied: 0.00001417935058346017 + carbon-operational: 0.007267361111111111 + carbon: 0.007281540461694571 + sci: 0.007281540461694571 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + component: 1 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 1121.25 + cpu-energy-raw: 0.00031145833333333335 + vcpu-ratio: 8 + cpu-energy-kwh: 0.00003893229166666667 + carbon-embodied: 0.00006076864535768645 + carbon-operational: 0.031145833333333334 + carbon: 0.03120660197869102 + sci: 0.03120660197869102 diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml new file mode 100644 index 000000000..82e9a6280 --- /dev/null +++ b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml @@ -0,0 +1,890 @@ +name: pipeline-with-aggregate +description: a full pipeline with the aggregate feature enabled +tags: null +aggregation: + metrics: + carbon: + method: sum + type: both +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-aggregate.yml -o + manifests/outputs/pipelines/pipeline-with-aggregate + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:33:37.703Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 10 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 5 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 15 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 30 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 26 + requests: 14 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-total: 14.399999999999999 + vcpus-allocated: 1.7999999999999998 + cpu-factor: 0.662 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000007048611111111113 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.0056388888888888895 + carbon: 0.005649016996448503 + sci: 0.000403501214032036 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + requests: 9.571428571428571 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 6.171428571428571 + vcpus-allocated: 0.7714285714285714 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.0005589976298113692 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + requests: 8.428571428571429 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 3.9619047619047616 + vcpus-allocated: 0.4952380952380952 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.0006170797001436077 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 5 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 5 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 5 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 5 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 5 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + requests: 3 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-total: 0.8 + vcpus-allocated: 0.1 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04532668505834602 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 150 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 110 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 180 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 52.400000000000006 + cloud/instance-type: .nan + cloud/region: .nan + requests: 220 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-total: 14.399999999999999 + vcpus-allocated: 1.7999999999999998 + cpu-factor: 0.9458 + cpu-wattage: 94.57999999999998 + cpu-wattage-times-duration: 258.9 + cpu-energy-raw: 0.00007191666666666668 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008989583333333334 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007191666666666666 + carbon: 0.007201794774226282 + sci: 0.00003273543079193765 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 28.45714285714286 + cloud/instance-type: .nan + cloud/region: .nan + requests: 92.85714285714285 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 6.171428571428571 + vcpus-allocated: 0.7714285714285714 + cpu-factor: 0.469842857142857 + cpu-wattage: 46.98428571428572 + cpu-wattage-times-duration: 308.35 + cpu-energy-raw: 0.00008565277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000010706597222222223 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008565277777777778 + carbon: 0.008575405885337391 + sci: 0.00009235052491901808 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 19.342857142857145 + cloud/instance-type: .nan + cloud/region: .nan + requests: 59.14285714285714 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 3.9619047619047616 + vcpus-allocated: 0.4952380952380952 + cpu-factor: 0.3131738095238096 + cpu-wattage: 31.31738095238095 + cpu-wattage-times-duration: 306.2 + cpu-energy-raw: 0.00008505555555555556 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.000010631944444444445 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008505555555555556 + carbon: 0.00851568366311517 + sci: 0.0001439849894729618 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 30 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 30 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 30 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 30 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 30 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 3.3000000000000003 + cloud/instance-type: .nan + cloud/region: .nan + requests: 18 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-total: 0.8 + vcpus-allocated: 0.1 + cpu-factor: 0.05672500000000001 + cpu-wattage: 5.6725 + cpu-wattage-times-duration: 170.175 + cpu-energy-raw: 0.00004727083333333333 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000005908854166666666 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.004727083333333333 + carbon: 0.0047331601978691015 + sci: 0.00026295334432606117 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.06846904616945712 + outputs: + - carbon: 0.012850811770674785 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.013925811770674782 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.013716783992897007 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.007853820395738204 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.11379573122780316 diff --git a/manifests/outputs/pipelines/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/pipeline-with-mocks.yaml new file mode 100644 index 000000000..f09bc3401 --- /dev/null +++ b/manifests/outputs/pipelines/pipeline-with-mocks.yaml @@ -0,0 +1,910 @@ +name: pipeline-with-mocks +description: a full pipeline seeded with data from mock-observations feature +tags: null +aggregation: + metrics: + carbon: + method: sum + type: both +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + group-by: + path: builtin + method: GroupBy +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-mocks.yml -o + manifests/outputs/pipelines/pipeline-with-mocks + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:34:10.878Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 30 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 40 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 50 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: .nan + cloud/region: .nan + duration: 5 + cpu/utilization: 26 + requests: 62 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-total: 14.399999999999999 + vcpus-allocated: 1.7999999999999998 + cpu-factor: 0.662 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000007048611111111113 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.0056388888888888895 + carbon: 0.005649016996448503 + sci: 0.00009111317736207264 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 12.57142857142857 + cloud/instance-type: .nan + cloud/region: .nan + requests: 25.14285714285714 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 6.171428571428571 + vcpus-allocated: 0.7714285714285714 + cpu-factor: 0.29907142857142854 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.000212800234075919 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 7.428571428571429 + cloud/instance-type: .nan + cloud/region: .nan + requests: 16.19047619047619 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 3.9619047619047616 + vcpus-allocated: 0.4952380952380952 + cpu-factor: 0.1850952380952381 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.00032124443213358406 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 8.333333333333334 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 8.333333333333334 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 8.333333333333334 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 8.333333333333334 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 2.5 + requests: 8.333333333333334 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.06229166666666667 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: .nan + cloud/region: .nan + cpu/utilization: 1.5 + requests: 5 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-total: 0.8 + vcpus-allocated: 0.1 + cpu-factor: 0.037375 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0006241320395738205 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: 0 + cloud/region: 0 + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04532668505834602 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 40 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 50 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 60 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 52.400000000000006 + cloud/instance-type: .nan + cloud/region: .nan + requests: 62 + cpu/thermal-design-power: 180 + grid/carbon-intensity: 1440 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 6480 + device/expected-lifespan: 170294400 + vcpus-total: 14.399999999999999 + vcpus-allocated: 1.7999999999999998 + cpu-factor: 0.9458 + cpu-wattage: 94.57999999999998 + cpu-wattage-times-duration: 258.9 + cpu-energy-raw: 0.00007191666666666668 + vcpu-ratio: 14.399999999999999 + cpu-energy-kwh: 0.000008989583333333334 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007191666666666666 + carbon: 0.007201794774226282 + sci: 0.00011615798022945616 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 28.45714285714286 + cloud/instance-type: .nan + cloud/region: .nan + requests: 36.57142857142857 + cpu/thermal-design-power: 77.14285714285714 + grid/carbon-intensity: 617.1428571428571 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2777.142857142857 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 6.171428571428571 + vcpus-allocated: 0.7714285714285714 + cpu-factor: 0.469842857142857 + cpu-wattage: 46.98428571428572 + cpu-wattage-times-duration: 308.35 + cpu-energy-raw: 0.00008565277777777778 + vcpu-ratio: 6.171428571428571 + cpu-energy-kwh: 0.000010706597222222223 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008565277777777778 + carbon: 0.008575405885337391 + sci: 0.0002344837546771943 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 19.342857142857145 + cloud/instance-type: .nan + cloud/region: .nan + requests: 25.42857142857143 + cpu/thermal-design-power: 49.52380952380953 + grid/carbon-intensity: 396.19047619047626 + device/emissions-embodied: 759.2594285714285 + time-reserved: 1782.8571428571431 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 3.9619047619047616 + vcpus-allocated: 0.4952380952380952 + cpu-factor: 0.3131738095238096 + cpu-wattage: 31.31738095238095 + cpu-wattage-times-duration: 306.2 + cpu-energy-raw: 0.00008505555555555556 + vcpu-ratio: 3.9619047619047616 + cpu-energy-kwh: 0.000010631944444444445 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008505555555555556 + carbon: 0.00851568366311517 + sci: 0.0003348864361899224 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 10 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 10 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 10 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 10 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 5.5 + cloud/instance-type: .nan + cloud/region: .nan + requests: 10 + cpu/thermal-design-power: 16.666666666666668 + grid/carbon-intensity: 133.33333333333334 + device/emissions-embodied: 255.51999999999998 + time-reserved: 600 + device/expected-lifespan: 15768000 + vcpus-total: 1.3333333333333333 + vcpus-allocated: 0.16666666666666666 + cpu-factor: 0.09454166666666668 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 1.3333333333333333 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 3.3000000000000003 + cloud/instance-type: .nan + cloud/region: .nan + requests: 6 + cpu/thermal-design-power: 10 + grid/carbon-intensity: 80 + device/emissions-embodied: 153.312 + time-reserved: 362 + device/expected-lifespan: 9460800 + vcpus-total: 0.8 + vcpus-allocated: 0.1 + cpu-factor: 0.05672500000000001 + cpu-wattage: 5.6725 + cpu-wattage-times-duration: 170.175 + cpu-energy-raw: 0.00004727083333333333 + vcpu-ratio: 0.8 + cpu-energy-kwh: 0.000005908854166666666 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.004727083333333333 + carbon: 0.0047331601978691015 + sci: 0.0007888600329781836 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 5 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cpu/utilization: 0 + cloud/instance-type: 0 + cloud/region: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 0 + vcpus-allocated: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 0 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.06846904616945712 + outputs: + - carbon: 0.012850811770674785 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.013925811770674782 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.013716783992897007 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.007853820395738204 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.11379573122780316 diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml new file mode 100644 index 000000000..5c5f0d822 --- /dev/null +++ b/manifests/outputs/pipelines/sci.yaml @@ -0,0 +1,297 @@ +name: pipeline-teads-sci +description: >- + a full pipeline seeded with some hardcoded input data and yielding an SCI + score +tags: null +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu/energy + sum-energy-components: + path: builtin + method: Sum + global-config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy + embodied-carbon: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - energy + - grid/carbon-intensity + output-parameter: carbon-operational + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + sci: + path: builtin + method: Sci + global-config: + functional-unit: component +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/sci.yml -o manifests/outputs/pipelines/sci + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:34:45.027Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sum-energy-components + - embodied-carbon + - operational-carbon + - sum-carbon + - sci + config: null + defaults: + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: vcpus-allocated + resources-total: vcpus-total + component: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + network/energy: 0.000001 + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: vcpus-allocated + resources-total: vcpus-total + component: 1 + cpu-factor: 0.75 + cpu-wattage: 75 + cpu-wattage-times-duration: 75 + cpu-energy-raw: 0.000020833333333333333 + vcpu-ratio: 4 + cpu/energy: 0.000005208333333333333 + energy: 0.000006208333333333333 + carbon-embodied: 0.000004051243023845763 + carbon-operational: 0.004966666666666666 + carbon: 0.004970717909690512 + sci: 0.004970717909690512 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: vcpus-allocated + resources-total: vcpus-total + component: 1 + cpu-factor: 0.4275 + cpu-wattage: 42.75 + cpu-wattage-times-duration: 213.75 + cpu-energy-raw: 0.000059375 + vcpu-ratio: 4 + cpu/energy: 0.00001484375 + energy: 0.00001584375 + carbon-embodied: 0.000020256215119228814 + carbon-operational: 0.012674999999999999 + carbon: 0.012695256215119228 + sci: 0.012695256215119228 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + network/energy: 0.000001 + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: vcpus-allocated + resources-total: vcpus-total + component: 1 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 261.625 + cpu-energy-raw: 0.00007267361111111111 + vcpu-ratio: 4 + cpu/energy: 0.000018168402777777778 + energy: 0.000019168402777777778 + carbon-embodied: 0.00002835870116692034 + carbon-operational: 0.015334722222222222 + carbon: 0.015363080923389142 + sci: 0.015363080923389142 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + network/energy: 0.000001 + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + resources-reserved: vcpus-allocated + resources-total: vcpus-total + component: 1 + cpu-factor: 0.37375 + cpu-wattage: 37.375 + cpu-wattage-times-duration: 1121.25 + cpu-energy-raw: 0.00031145833333333335 + vcpu-ratio: 4 + cpu/energy: 0.00007786458333333334 + energy: 0.00007886458333333333 + carbon-embodied: 0.0001215372907153729 + carbon-operational: 0.06309166666666667 + carbon: 0.06321320395738204 + sci: 0.06321320395738204 diff --git a/manifests/outputs/pipelines/teads-curve.yaml b/manifests/outputs/pipelines/teads-curve.yaml new file mode 100644 index 000000000..3f5d2d323 --- /dev/null +++ b/manifests/outputs/pipelines/teads-curve.yaml @@ -0,0 +1,187 @@ +name: carbon-intensity plugin demo +description: null +tags: null +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - thermal-design-power + output-parameter: cpu-wattage + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/teads-curve.yml -o + manifests/outputs/pipelines/teads-curve + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:35:33.728Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + defaults: + thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 360 + cpu/utilization: 1 + carbon: 30 + - timestamp: 2023-09-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 10 + - timestamp: 2023-10-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 50 + - timestamp: 2023-10-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 100 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 360 + cpu/utilization: 1 + carbon: 30 + thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + cpu-factor: 0.13999999999999999 + cpu-wattage: 13.999999999999998 + cpu-wattage-times-duration: 5039.999999999999 + cpu-energy-raw: 0.0013999999999999998 + vcpu-ratio: 4 + cpu-energy-kwh: 0.00034999999999999994 + - timestamp: 2023-09-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 10 + thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + cpu-factor: 0.32 + cpu-wattage: 32 + cpu-wattage-times-duration: 11520 + cpu-energy-raw: 0.0032 + vcpu-ratio: 4 + cpu-energy-kwh: 0.0008 + - timestamp: 2023-10-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 50 + thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + cpu-factor: 0.75 + cpu-wattage: 75 + cpu-wattage-times-duration: 27000 + cpu-energy-raw: 0.0075 + vcpu-ratio: 4 + cpu-energy-kwh: 0.001875 + - timestamp: 2023-10-06T00:00 + duration: 360 + carbon: 30 + cpu/utilization: 100 + thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 2 + cpu-factor: 1.02 + cpu-wattage: 102 + cpu-wattage-times-duration: 36720 + cpu-energy-raw: 0.0102 + vcpu-ratio: 4 + cpu-energy-kwh: 0.00255 diff --git a/manifests/outputs/pipelines/zeros.yaml b/manifests/outputs/pipelines/zeros.yaml new file mode 100644 index 000000000..523728097 --- /dev/null +++ b/manifests/outputs/pipelines/zeros.yaml @@ -0,0 +1,199 @@ +name: generics +description: >- + a pipeline that does arbitrary calculations using our generic arithmetic + builtins +tags: null +initialize: + plugins: + sum-zero-and-one: + path: builtin + method: Sum + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-plus-zero + sum-zero-and-zero: + path: builtin + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-plus-zero + subtract-one-and-zero: + path: builtin + method: Subtract + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-minus-zero + subtract-zero-and-zero: + path: builtin + method: Sum + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-minus-zero + subtract-zero-and-one: + path: builtin + method: Subtract + global-config: + input-parameters: + - zero-value + - some-value + output-parameter: zero-minus-one + coefficient-one-times-zero: + path: builtin + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 1 + output-parameter: zero-times-one-coefficient + coefficient-zero-times-one: + path: builtin + method: Coefficient + global-config: + input-parameter: some-value + coefficient: 0 + output-parameter: one-times-zero-coefficient + coefficient-zero-times-zero: + path: builtin + method: Coefficient + global-config: + input-parameter: zero-value + coefficient: 0 + output-parameter: zero-times-zero-coefficient + multiply-one-times-zero: + path: builtin + method: Multiply + global-config: + input-parameters: + - some-value + - zero-value + output-parameter: one-times-zero + multiply-zero-times-one: + path: builtin + method: Multiply + global-config: + input-parameters: + - zero-value + - zero-value + output-parameter: zero-times-one + exponent-one-to-zero: + path: builtin + method: Exponent + global-config: + input-parameter: some-value + exponent: 0 + output-parameter: one-raised-to-zero-power + exponent-zero-to-zero: + path: builtin + method: Exponent + global-config: + input-parameter: zero-value + exponent: 0 + output-parameter: zero-raised-to-zero-power + exponent-zero-to-one: + path: builtin + method: Exponent + global-config: + input-parameter: zero-value + exponent: 1 + output-parameter: zero-raised-to-first-power + sci: + path: builtin + method: Sci + global-config: + functional-unit: zero-value +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/zeros.yml -o manifests/outputs/pipelines/zeros + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-19T06:36:00.790Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.10' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + status: success +tree: + children: + child-1: + pipeline: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci + config: null + defaults: null + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + some-value: 1 + zero-value: 0 + carbon: 10 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + some-value: 1 + zero-value: 0 + carbon: 10 + one-plus-zero: 1 + zero-plus-zero: 0 + one-minus-zero: 1 + zero-minus-zero: 0 + zero-minus-one: -1 + zero-times-one-coefficient: 0 + one-times-zero-coefficient: 0 + zero-times-zero-coefficient: 0 + one-times-zero: 0 + zero-times-one: 0 + one-raised-to-zero-power: 1 + zero-raised-to-first-power: 0 + zero-raised-to-zero-power: 1 + sci: 10 From ed6bb383d2b7d5d9ba7e4e45fe2312e8de4bd1fc Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 19 Jul 2024 10:56:50 +0400 Subject: [PATCH 426/863] fix(manifests): rename plugins to builtins --- .../coefficient/failure-invalid-config-input-param.yaml | 0 .../coefficient/failure-output-param-is-null.yaml | 0 manifests/outputs/{plugins => builtins}/coefficient/success.yaml | 0 .../csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml | 0 .../csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml | 0 .../{plugins => builtins}/csv-lookup/cloud-metadata/success.yaml | 0 .../csv-lookup/region-metadata/failure-missing-column.yaml | 0 .../csv-lookup/region-metadata/failure-missing-output.yaml | 0 .../csv-lookup/region-metadata/success-renaming.yaml | 0 .../{plugins => builtins}/csv-lookup/region-metadata/success.yaml | 0 .../csv-lookup/tdp-finder/failure-missing-input-param.yaml | 0 .../tdp-finder/failure-unsupported-physical-processor.yaml | 0 .../{plugins => builtins}/csv-lookup/tdp-finder/success.yaml | 0 .../divide/failure-invalid-config-denominator.yaml | 0 .../{plugins => builtins}/divide/failure-missing-numerator.yaml | 0 .../divide/success-denominator-equal-zero.yaml | 0 manifests/outputs/{plugins => builtins}/divide/success.yaml | 0 manifests/outputs/{plugins => builtins}/exponent/success.yaml | 0 .../groupby/failure-invalid-config-group.yaml | 0 .../groupby/failure-missing-cloud-instance-type.yaml | 0 .../{plugins => builtins}/interpolation/interpolation.yaml | 0 .../outputs/{plugins => builtins}/interpolation/success.yaml | 0 .../mock-observations/failure-invalid-config-cpu-range.yaml | 0 .../failure-invalid-memory-utilization-range.yaml | 0 .../mock-observations/failure-missing-timestamp-from-param.yaml | 0 .../outputs/{plugins => builtins}/mock-observations/success.yaml | 0 .../multiply/failure-input-parameter-is-missing.yaml | 0 .../multiply/success-with-multiple-inputs.yaml | 0 manifests/outputs/{plugins => builtins}/multiply/success.yaml | 0 .../{plugins => builtins}/regex/failure-missing-input-param.yaml | 0 .../regex/failure-not-matching-with-regex.yaml | 0 manifests/outputs/{plugins => builtins}/regex/success.yaml | 0 .../sci-embodied/failure-invalid-default-emission-value.yaml | 0 .../sci-embodied/failure-missing-expected-lifespan.yaml | 0 manifests/outputs/{plugins => builtins}/sci-embodied/success.yaml | 0 .../{plugins => builtins}/sci/failure-invalid-config-value.yaml | 0 .../{plugins => builtins}/sci/failure-missing-input-param.yaml | 0 manifests/outputs/{plugins => builtins}/sci/success.yml.yaml | 0 .../{plugins => builtins}/shell/failure-invalid-command.yaml | 0 manifests/outputs/{plugins => builtins}/shell/success.yaml | 0 manifests/outputs/{plugins => builtins}/subtract/success.yaml | 0 .../{plugins => builtins}/sum/failure-missing-input-param.yaml | 0 .../{plugins => builtins}/sum/failure-missing-output-param.yaml | 0 manifests/outputs/{plugins => builtins}/sum/success.yaml | 0 .../time-sync/failure-config-start-later-end.yaml | 0 manifests/outputs/{plugins => builtins}/time-sync/success.yaml | 0 46 files changed, 0 insertions(+), 0 deletions(-) rename manifests/outputs/{plugins => builtins}/coefficient/failure-invalid-config-input-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/coefficient/failure-output-param-is-null.yaml (100%) rename manifests/outputs/{plugins => builtins}/coefficient/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/cloud-metadata/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/region-metadata/failure-missing-column.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/region-metadata/failure-missing-output.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/region-metadata/success-renaming.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/region-metadata/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/tdp-finder/failure-missing-input-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml (100%) rename manifests/outputs/{plugins => builtins}/csv-lookup/tdp-finder/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/divide/failure-invalid-config-denominator.yaml (100%) rename manifests/outputs/{plugins => builtins}/divide/failure-missing-numerator.yaml (100%) rename manifests/outputs/{plugins => builtins}/divide/success-denominator-equal-zero.yaml (100%) rename manifests/outputs/{plugins => builtins}/divide/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/exponent/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/groupby/failure-invalid-config-group.yaml (100%) rename manifests/outputs/{plugins => builtins}/groupby/failure-missing-cloud-instance-type.yaml (100%) rename manifests/outputs/{plugins => builtins}/interpolation/interpolation.yaml (100%) rename manifests/outputs/{plugins => builtins}/interpolation/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/mock-observations/failure-invalid-config-cpu-range.yaml (100%) rename manifests/outputs/{plugins => builtins}/mock-observations/failure-invalid-memory-utilization-range.yaml (100%) rename manifests/outputs/{plugins => builtins}/mock-observations/failure-missing-timestamp-from-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/mock-observations/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/multiply/failure-input-parameter-is-missing.yaml (100%) rename manifests/outputs/{plugins => builtins}/multiply/success-with-multiple-inputs.yaml (100%) rename manifests/outputs/{plugins => builtins}/multiply/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/regex/failure-missing-input-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/regex/failure-not-matching-with-regex.yaml (100%) rename manifests/outputs/{plugins => builtins}/regex/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci-embodied/failure-invalid-default-emission-value.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci-embodied/failure-missing-expected-lifespan.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci-embodied/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci/failure-invalid-config-value.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci/failure-missing-input-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/sci/success.yml.yaml (100%) rename manifests/outputs/{plugins => builtins}/shell/failure-invalid-command.yaml (100%) rename manifests/outputs/{plugins => builtins}/shell/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/subtract/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/sum/failure-missing-input-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/sum/failure-missing-output-param.yaml (100%) rename manifests/outputs/{plugins => builtins}/sum/success.yaml (100%) rename manifests/outputs/{plugins => builtins}/time-sync/failure-config-start-later-end.yaml (100%) rename manifests/outputs/{plugins => builtins}/time-sync/success.yaml (100%) diff --git a/manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml similarity index 100% rename from manifests/outputs/plugins/coefficient/failure-invalid-config-input-param.yaml rename to manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml diff --git a/manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml similarity index 100% rename from manifests/outputs/plugins/coefficient/failure-output-param-is-null.yaml rename to manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml diff --git a/manifests/outputs/plugins/coefficient/success.yaml b/manifests/outputs/builtins/coefficient/success.yaml similarity index 100% rename from manifests/outputs/plugins/coefficient/success.yaml rename to manifests/outputs/builtins/coefficient/success.yaml diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml rename to manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml rename to manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml diff --git a/manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/cloud-metadata/success.yaml rename to manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-column.yaml rename to manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yaml rename to manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/region-metadata/success-renaming.yaml rename to manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml diff --git a/manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/region-metadata/success.yaml rename to manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/tdp-finder/failure-missing-input-param.yaml rename to manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml rename to manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml diff --git a/manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml similarity index 100% rename from manifests/outputs/plugins/csv-lookup/tdp-finder/success.yaml rename to manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml diff --git a/manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml similarity index 100% rename from manifests/outputs/plugins/divide/failure-invalid-config-denominator.yaml rename to manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml diff --git a/manifests/outputs/plugins/divide/failure-missing-numerator.yaml b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml similarity index 100% rename from manifests/outputs/plugins/divide/failure-missing-numerator.yaml rename to manifests/outputs/builtins/divide/failure-missing-numerator.yaml diff --git a/manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml similarity index 100% rename from manifests/outputs/plugins/divide/success-denominator-equal-zero.yaml rename to manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml diff --git a/manifests/outputs/plugins/divide/success.yaml b/manifests/outputs/builtins/divide/success.yaml similarity index 100% rename from manifests/outputs/plugins/divide/success.yaml rename to manifests/outputs/builtins/divide/success.yaml diff --git a/manifests/outputs/plugins/exponent/success.yaml b/manifests/outputs/builtins/exponent/success.yaml similarity index 100% rename from manifests/outputs/plugins/exponent/success.yaml rename to manifests/outputs/builtins/exponent/success.yaml diff --git a/manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml similarity index 100% rename from manifests/outputs/plugins/groupby/failure-invalid-config-group.yaml rename to manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml diff --git a/manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml similarity index 100% rename from manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yaml rename to manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml diff --git a/manifests/outputs/plugins/interpolation/interpolation.yaml b/manifests/outputs/builtins/interpolation/interpolation.yaml similarity index 100% rename from manifests/outputs/plugins/interpolation/interpolation.yaml rename to manifests/outputs/builtins/interpolation/interpolation.yaml diff --git a/manifests/outputs/plugins/interpolation/success.yaml b/manifests/outputs/builtins/interpolation/success.yaml similarity index 100% rename from manifests/outputs/plugins/interpolation/success.yaml rename to manifests/outputs/builtins/interpolation/success.yaml diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml similarity index 100% rename from manifests/outputs/plugins/mock-observations/failure-invalid-config-cpu-range.yaml rename to manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml diff --git a/manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml similarity index 100% rename from manifests/outputs/plugins/mock-observations/failure-invalid-memory-utilization-range.yaml rename to manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml diff --git a/manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml similarity index 100% rename from manifests/outputs/plugins/mock-observations/failure-missing-timestamp-from-param.yaml rename to manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml diff --git a/manifests/outputs/plugins/mock-observations/success.yaml b/manifests/outputs/builtins/mock-observations/success.yaml similarity index 100% rename from manifests/outputs/plugins/mock-observations/success.yaml rename to manifests/outputs/builtins/mock-observations/success.yaml diff --git a/manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml similarity index 100% rename from manifests/outputs/plugins/multiply/failure-input-parameter-is-missing.yaml rename to manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml diff --git a/manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml similarity index 100% rename from manifests/outputs/plugins/multiply/success-with-multiple-inputs.yaml rename to manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml diff --git a/manifests/outputs/plugins/multiply/success.yaml b/manifests/outputs/builtins/multiply/success.yaml similarity index 100% rename from manifests/outputs/plugins/multiply/success.yaml rename to manifests/outputs/builtins/multiply/success.yaml diff --git a/manifests/outputs/plugins/regex/failure-missing-input-param.yaml b/manifests/outputs/builtins/regex/failure-missing-input-param.yaml similarity index 100% rename from manifests/outputs/plugins/regex/failure-missing-input-param.yaml rename to manifests/outputs/builtins/regex/failure-missing-input-param.yaml diff --git a/manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml similarity index 100% rename from manifests/outputs/plugins/regex/failure-not-matching-with-regex.yaml rename to manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml diff --git a/manifests/outputs/plugins/regex/success.yaml b/manifests/outputs/builtins/regex/success.yaml similarity index 100% rename from manifests/outputs/plugins/regex/success.yaml rename to manifests/outputs/builtins/regex/success.yaml diff --git a/manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml similarity index 100% rename from manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yaml rename to manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml diff --git a/manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml similarity index 100% rename from manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yaml rename to manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml diff --git a/manifests/outputs/plugins/sci-embodied/success.yaml b/manifests/outputs/builtins/sci-embodied/success.yaml similarity index 100% rename from manifests/outputs/plugins/sci-embodied/success.yaml rename to manifests/outputs/builtins/sci-embodied/success.yaml diff --git a/manifests/outputs/plugins/sci/failure-invalid-config-value.yaml b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml similarity index 100% rename from manifests/outputs/plugins/sci/failure-invalid-config-value.yaml rename to manifests/outputs/builtins/sci/failure-invalid-config-value.yaml diff --git a/manifests/outputs/plugins/sci/failure-missing-input-param.yaml b/manifests/outputs/builtins/sci/failure-missing-input-param.yaml similarity index 100% rename from manifests/outputs/plugins/sci/failure-missing-input-param.yaml rename to manifests/outputs/builtins/sci/failure-missing-input-param.yaml diff --git a/manifests/outputs/plugins/sci/success.yml.yaml b/manifests/outputs/builtins/sci/success.yml.yaml similarity index 100% rename from manifests/outputs/plugins/sci/success.yml.yaml rename to manifests/outputs/builtins/sci/success.yml.yaml diff --git a/manifests/outputs/plugins/shell/failure-invalid-command.yaml b/manifests/outputs/builtins/shell/failure-invalid-command.yaml similarity index 100% rename from manifests/outputs/plugins/shell/failure-invalid-command.yaml rename to manifests/outputs/builtins/shell/failure-invalid-command.yaml diff --git a/manifests/outputs/plugins/shell/success.yaml b/manifests/outputs/builtins/shell/success.yaml similarity index 100% rename from manifests/outputs/plugins/shell/success.yaml rename to manifests/outputs/builtins/shell/success.yaml diff --git a/manifests/outputs/plugins/subtract/success.yaml b/manifests/outputs/builtins/subtract/success.yaml similarity index 100% rename from manifests/outputs/plugins/subtract/success.yaml rename to manifests/outputs/builtins/subtract/success.yaml diff --git a/manifests/outputs/plugins/sum/failure-missing-input-param.yaml b/manifests/outputs/builtins/sum/failure-missing-input-param.yaml similarity index 100% rename from manifests/outputs/plugins/sum/failure-missing-input-param.yaml rename to manifests/outputs/builtins/sum/failure-missing-input-param.yaml diff --git a/manifests/outputs/plugins/sum/failure-missing-output-param.yaml b/manifests/outputs/builtins/sum/failure-missing-output-param.yaml similarity index 100% rename from manifests/outputs/plugins/sum/failure-missing-output-param.yaml rename to manifests/outputs/builtins/sum/failure-missing-output-param.yaml diff --git a/manifests/outputs/plugins/sum/success.yaml b/manifests/outputs/builtins/sum/success.yaml similarity index 100% rename from manifests/outputs/plugins/sum/success.yaml rename to manifests/outputs/builtins/sum/success.yaml diff --git a/manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml similarity index 100% rename from manifests/outputs/plugins/time-sync/failure-config-start-later-end.yaml rename to manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml diff --git a/manifests/outputs/plugins/time-sync/success.yaml b/manifests/outputs/builtins/time-sync/success.yaml similarity index 100% rename from manifests/outputs/plugins/time-sync/success.yaml rename to manifests/outputs/builtins/time-sync/success.yaml From 85ae2f5fe3fa8abfb638c9733926a74b75c1c6dd Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 19 Jul 2024 16:06:15 +0400 Subject: [PATCH 427/863] feat(lib): update compute documentation --- src/if-run/lib/compute.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 69ee0b5ff..8a44b8ef1 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -47,10 +47,15 @@ const mergeDefaults = ( * 2. If it's a grouping node, then first of all computes all it's children. * This is doing a depth first traversal. * 3. Otherwise merges the defaults into the inputs. - * 4. Goes through the pipeline plugins, by checking if it's `execute` plugin. If so sets outputs. - * If is a `groupby` plugin, it will return child components rather than outputs. - * 5. Since after `groupby`, there are new child components, then computes them. - * Note: `pipeline` now equals the remaining plugins to apply to each child + * 4. Iterates over pipeline phases (observe, regroup, compute). + * 5. Observe plugins are used to insert input values + * (isolated execution can be achived by passing `--observe` flag to CLI command). + * 6. Regroup plugin is used to group existing inputs by criteria + * (isolated execution can be achived by passing `--regroup` flag to CLI command). + * Since it creates new children for node, existing inputs and outputs are dropped and recursive traversal is called + * for newbord child component. + * 7. Compute plugins are used to do desired computations and appending the result to outputs + * (isolated execution can be achived by passing `--compute` flag to CLI command). */ const computeNode = async (node: Node, params: ComputeParams): Promise => { const pipeline = node.pipeline || (params.pipeline as PhasedPipeline); From d379036e1f2d692a9ed3e0093c046a4872eb8486 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 19 Jul 2024 16:07:11 +0400 Subject: [PATCH 428/863] fix(lib): tune regroup docs, types --- src/if-run/lib/regroup.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index 810da7c2d..eba87a4d0 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -17,11 +17,7 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { /** * Creates structure to insert inputs by groups. */ - const appendGroup = ( - value: PluginParams, - object: any, - groups: string[] - ): any => { + const appendGroup = (value: PluginParams, object: any, groups: string[]) => { if (groups.length > 0) { const group = groups.shift() as string; @@ -46,26 +42,22 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { }; /** - * Validates config parameter. + * Validates groups array. */ const validateGroups = (groups: string[]) => { - const inputData = { - groups, - }; - + const inputData = {groups}; const validationSchema = z.record( z.string(), z.array(z.string()).min(1, REGROUP_ERROR) ); - validate(validationSchema, inputData); return groups; }; /** - * Interates over inputs, grabs config-group types values for each one. - * Based on grouping types, initializes the structure grouped structure. + * Interates over inputs, grabs group values for each one. + * Based on grouping, initializes the structure. */ return inputs.reduce((acc, input) => { const validtedGroups = validateGroups(groups); From 55bbc586374b75509d6f7c44779925329fbf1dde Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Sat, 20 Jul 2024 23:08:08 +0400 Subject: [PATCH 429/863] fix(manifests): tune mock observation settings to match time sync --- manifests/examples/pipelines/pipeline-with-mocks.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 4a2651e1f..c53aa04b9 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -13,9 +13,9 @@ initialize: method: MockObservations path: "builtin" global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 - duration: 60 + timestamp-from: "2023-12-12T00:00:00.000Z" + timestamp-to: "2023-12-12T00:00:13.000Z" + duration: 30 components: - cloud/instance-type: A1 generators: From 2b5a591a43d520f5a58fff1caa8333c0ec7712d3 Mon Sep 17 00:00:00 2001 From: Manushak Keramyan Date: Mon, 22 Jul 2024 13:13:01 +0400 Subject: [PATCH 430/863] Update src/if-run/builtins/multiply/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Manushak Keramyan --- src/if-run/builtins/multiply/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 08ebe9526..0514ce0fd 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -54,7 +54,7 @@ const config = { outputParameter: 'energy-product', }; -const mult = Multiply(config, parametersMetadata); +const multiply = Multiply(config, parametersMetadata); const result = await mult.execute([ { duration: 3600, From 9ed8e1aad5916d5cf6a37c3a9eefd7e146c600e8 Mon Sep 17 00:00:00 2001 From: Manushak Keramyan Date: Mon, 22 Jul 2024 13:13:18 +0400 Subject: [PATCH 431/863] Update src/if-run/builtins/multiply/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Manushak Keramyan --- src/if-run/builtins/multiply/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 0514ce0fd..6acbb847a 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -55,7 +55,7 @@ const config = { }; const multiply = Multiply(config, parametersMetadata); -const result = await mult.execute([ +const result = await multiply.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', From 2bf8e47775c918634072e26efe7af0b23c4fac7e Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:13:07 +0400 Subject: [PATCH 432/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57230e0e6..78e1a23a3 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.13", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1185,9 +1185,9 @@ } }, "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.13", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.13.tgz", + "integrity": "sha512-FSNzs0jL7sFaT8ZaaTS4yRl0IRBorVOgMQ7mVcQKZc9+uONosrudvWLPoDTZfxEQ5ZyFsJe6yEt2O1E53XagqQ==", "dependencies": { "typescript": "^5.1.6" }, diff --git a/package.json b/package.json index 3a0f5af32..ec8f48aed 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.13", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From fdced82dcd02c3c90272b6544d18edc0ebeb1aee Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:14:45 +0400 Subject: [PATCH 433/863] feat(util): add `aggregationMethod` into manifest schema --- src/common/util/validations.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 98d017c29..39de2de1c 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -64,6 +64,7 @@ export const manifestSchema = z.object({ z.object({ unit: z.string(), description: z.string(), + aggregationMethod: z.string(), }) ) .optional() @@ -74,6 +75,7 @@ export const manifestSchema = z.object({ z.object({ unit: z.string(), description: z.string(), + aggregationMethod: z.string(), }) ) .optional() From dfcd5ea3c16a3ccc4b9813d1c5fad398e049e618 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:16:54 +0400 Subject: [PATCH 434/863] feat(builtins): add `aggregationMethod` into plugins --- src/if-run/builtins/coefficient/index.ts | 2 ++ src/if-run/builtins/csv-lookup/index.ts | 13 +++++++++++-- .../builtins/mock-observations/index.ts | 8 +++++++- src/if-run/builtins/sci-embodied/index.ts | 6 ++++++ src/if-run/builtins/sci/index.ts | 3 +++ src/if-run/builtins/shell/index.ts | 14 ++++++++++++-- src/if-run/builtins/time-sync.ts | 19 ++++++++++++++++++- 7 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index b6c743170..f04a2ab74 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -24,12 +24,14 @@ export const Coefficient = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', + aggregationMethod: 'sum', }, }, outputs: parametersMetadata?.outputs || { 'carbon-product': { description: 'a product of cabon property and the coefficient', unit: 'gCO2e', + aggregationMethod: 'sum', }, }, }; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 91e1739b3..e227eaadf 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -5,7 +5,11 @@ 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, + PluginParametersMetadata, + PluginParams, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -28,9 +32,14 @@ const { CSVParseError, } = ERRORS; -export const CSVLookup = (globalConfig: any): ExecutePlugin => { +export const CSVLookup = ( + globalConfig: any, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index ab090d7c8..facc78353 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -5,6 +5,7 @@ import { PluginParams, ConfigParams, ObservationParams, + PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -14,9 +15,14 @@ import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; -export const MockObservations = (globalConfig: ConfigParams): ExecutePlugin => { +export const MockObservations = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index e2a60edd6..6bd7fd1b8 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -20,14 +20,17 @@ export const SciEmbodied = ( 'device/emissions-embodied': { description: 'total embodied emissions of some component', unit: 'gCO2e', + aggregationMethod: 'sum', }, 'device/expected-lifespan': { description: 'Total Expected Lifespan of the Component in Seconds', unit: 'seconds', + aggregationMethod: 'sum', }, 'resources-reserved': { description: 'resources reserved for an application', unit: 'count', + aggregationMethod: 'none', }, 'resources-total': { description: 'total resources available', @@ -36,16 +39,19 @@ export const SciEmbodied = ( 'vcpus-allocated': { description: 'number of vcpus allocated to particular resource', unit: 'count', + aggregationMethod: 'none', }, 'vcpus-total': { description: 'total number of vcpus available on a particular resource', unit: 'count', + aggregationMethod: 'none', }, }, outputs: parametersMetadata?.outputs || { 'carbon-embodied': { description: 'embodied emissions of the component', unit: 'gCO2e', + aggregationMethod: 'sum', }, }, }; diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 90cf55fb7..ac566fdb9 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -29,17 +29,20 @@ export const Sci = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', + aggregationMethod: 'sum', }, 'functional-unit': { description: 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', unit: 'none', + aggregationMethod: 'sum', }, }, outputs: parametersMetadata?.outputs || { sci: { description: 'carbon expressed in terms of the given functional unit', unit: 'gCO2e', + aggregationMethod: 'sum', }, }, }; diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 5fbea5f28..9abe8363c 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -3,15 +3,25 @@ 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, + PluginParametersMetadata, +} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; const {ProcessExecutionError} = ERRORS; -export const Shell = (globalConfig: ConfigParams): ExecutePlugin => { +export const Shell = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index 9c14b63a4..ae5a91a87 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -9,6 +9,7 @@ import { PaddingReceipt, TimeNormalizerConfig, TimeParams, + PluginParametersMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../common/util/validations'; @@ -35,9 +36,25 @@ const { INVALID_DATETIME, } = STRINGS; -export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { +export const TimeSync = ( + globalConfig: TimeNormalizerConfig, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { const metadata = { kind: 'execute', + inputs: parametersMetadata?.inputs || { + timestamp: { + description: 'refers to the time of occurrence of the input', + unit: 'RFC3339', + aggregationMethod: 'none', + }, + duration: { + description: 'refers to the duration of the input', + unit: 'seconds', + aggregationMethod: 'sum', + }, + }, + outputs: parametersMetadata?.outputs, }; /** From 90f861faf03d4857ade586b098602c6123ba7238 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:18:35 +0400 Subject: [PATCH 435/863] test(builtins): update test according to changes --- .../if-run/builtins/csv-lookup.test.ts | 32 ++-- .../if-run/builtins/mock-observations.test.ts | 137 ++++++++++-------- src/__tests__/if-run/builtins/shell.test.ts | 16 +- .../if-run/builtins/time-sync.test.ts | 57 +++++--- src/__tests__/if-run/lib/aggregate.test.ts | 7 +- .../if-run/util/aggregation-helper.test.ts | 6 +- 6 files changed, 150 insertions(+), 105 deletions(-) diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index b89c7572e..49e4d45bb 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -19,6 +19,10 @@ const { const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; const mock = new AxiosMockAdapter(axios); describe('CSVLookup: ', () => { @@ -35,7 +39,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); expect(csvLookup).toHaveProperty('metadata'); expect(csvLookup).toHaveProperty('execute'); }); @@ -54,7 +58,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + 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 @@ -93,7 +97,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -126,7 +130,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -155,7 +159,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -187,7 +191,7 @@ describe('builtins/CSVLookup: ', () => { }; mock.onGet(globalConfig.filepath).reply(404); - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -217,7 +221,7 @@ describe('builtins/CSVLookup: ', () => { }, output: '*', }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -265,7 +269,7 @@ describe('builtins/CSVLookup: ', () => { ['gpu-model-name', 'gpumodel'], ], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -300,7 +304,7 @@ describe('builtins/CSVLookup: ', () => { }, output: 'gpu-count', }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -335,7 +339,7 @@ describe('builtins/CSVLookup: ', () => { output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -392,7 +396,7 @@ describe('builtins/CSVLookup: ', () => { }, output: 'mock', }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -425,7 +429,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['gpu-count'], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -459,7 +463,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); const result = await csvLookup.execute([ { @@ -495,7 +499,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig); + const csvLookup = CSVLookup(globalConfig, parametersMetadata); try { await csvLookup.execute([ diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index 6b0fb22bd..0569b4c93 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -8,24 +8,32 @@ const {InputValidationError, GlobalConfigError} = ERRORS; const {INVALID_MIN_MAX} = STRINGS; describe('builtins/mock-observations: ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + describe('init: ', () => { it('successfully initalized.', () => { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, + const mockObservations = MockObservations( + { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, }, }, - }); + parametersMetadata + ); expect(mockObservations).toHaveProperty('metadata'); expect(mockObservations).toHaveProperty('execute'); @@ -49,7 +57,7 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); const result = await mockObservations.execute([]); expect.assertions(1); @@ -109,7 +117,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); try { await mockObservations.execute([]); } catch (error) { @@ -131,7 +139,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -165,7 +173,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -177,21 +185,24 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - 'timestamp-to': '2023-07-06T00:01', - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, + const mockObservations = MockObservations( + { + 'timestamp-from': '2023-07-06T00:00', + 'timestamp-to': '2023-07-06T00:01', + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, }, }, - }); + parametersMetadata + ); await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -207,21 +218,25 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ - 'timestamp-from': '2023-07-06T00:00', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, + const mockObservations = MockObservations( + { + 'timestamp-from': '2023-07-06T00:00', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, }, }, - }); + parametersMetadata + ); + await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -237,21 +252,25 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const mockObservations = MockObservations({ - 'timestamp-to': '2023-07-06T00:01', - duration: 5, - components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], - generators: { - common: { - region: 'uk-west', - 'common-key': 'common-val', - }, - randint: { - 'cpu/utilization': {min: 10, max: 95}, - 'memory/utilization': {min: 10, max: 85}, + const mockObservations = MockObservations( + { + 'timestamp-to': '2023-07-06T00:01', + duration: 5, + components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], + generators: { + common: { + region: 'uk-west', + 'common-key': 'common-val', + }, + randint: { + 'cpu/utilization': {min: 10, max: 95}, + 'memory/utilization': {min: 10, max: 85}, + }, }, }, - }); + parametersMetadata + ); + await mockObservations.execute([]); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); @@ -277,7 +296,7 @@ describe('builtins/mock-observations: ', () => { randint: null, }, }; - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); expect.assertions(2); @@ -307,7 +326,7 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const mockObservations = MockObservations(config); + const mockObservations = MockObservations(config, parametersMetadata); expect.assertions(2); diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts index 379863052..20b6a7e1c 100644 --- a/src/__tests__/if-run/builtins/shell.test.ts +++ b/src/__tests__/if-run/builtins/shell.test.ts @@ -10,8 +10,12 @@ jest.mock('child_process'); jest.mock('js-yaml'); describe('builtins/shell', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; describe('Shell', () => { - const shell = Shell({}); + const shell = Shell({}, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -22,7 +26,10 @@ 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( + {command: 'python3 /path/to/script.py'}, + parametersMetadata + ); const mockSpawnSync = spawnSync as jest.MockedFunction< typeof spawnSync >; @@ -70,7 +77,10 @@ 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( + {command: 'python3 /path/to/script.py'}, + parametersMetadata + ); (spawnSync as jest.Mock).mockImplementation(() => { throw new InputValidationError('Could not run the command'); }); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index e216690df..322971711 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -3,7 +3,7 @@ import {Settings, DateTime} from 'luxon'; import {AggregationParams} from '../../../common/types/manifest'; -import {storeAggregateMetrics} from '../../../if-run/lib/aggregate'; +import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {TimeSync} from '../../../if-run/builtins/time-sync'; import {STRINGS} from '../../../if-run/config'; @@ -65,10 +65,14 @@ describe('builtins/time-sync:', () => { type: 'horizontal', }; - storeAggregateMetrics(metricStorage); + storeAggregationMetrics(metricStorage); }); describe('time-sync: ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; const basicConfig = { 'start-time': '2023-12-12T00:01:00.000Z', 'end-time': '2023-12-12T00:01:00.000Z', @@ -76,7 +80,7 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - const timeSync = TimeSync(basicConfig); + const timeSync = TimeSync(basicConfig, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -88,6 +92,11 @@ describe('builtins/time-sync:', () => { }); describe('execute(): ', () => { + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + it('throws error if `start-time` is missing.', async () => { const invalidStartTimeConfig = { 'start-time': '', @@ -96,7 +105,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(invalidStartTimeConfig); + const timeModel = TimeSync(invalidStartTimeConfig, parametersMetadata); expect.assertions(1); @@ -131,7 +140,7 @@ describe('execute(): ', () => { interval: 5, 'allow-padding': true, }; - const timeModel = TimeSync(invalidEndTimeConfig); + const timeModel = TimeSync(invalidEndTimeConfig, parametersMetadata); expect.assertions(1); @@ -160,7 +169,7 @@ describe('execute(): ', () => { interval: 5, 'allow-padding': true, }; - const timeModel = TimeSync(invalidStartTimeConfig); + const timeModel = TimeSync(invalidStartTimeConfig, parametersMetadata); expect.assertions(1); try { await timeModel.execute([ @@ -186,7 +195,7 @@ describe('execute(): ', () => { interval: 5, 'allow-padding': true, }; - const timeModel = TimeSync(invalidEndTimeConfig); + const timeModel = TimeSync(invalidEndTimeConfig, parametersMetadata); expect.assertions(1); try { @@ -208,7 +217,7 @@ describe('execute(): ', () => { it('throws error on missing global config.', async () => { const config = undefined; - const timeModel = TimeSync(config!); + const timeModel = TimeSync(config!, parametersMetadata); expect.assertions(1); @@ -240,7 +249,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(invalidIntervalConfig); + const timeModel = TimeSync(invalidIntervalConfig, parametersMetadata); expect.assertions(1); @@ -272,7 +281,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -302,7 +311,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -334,7 +343,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -374,7 +383,7 @@ describe('execute(): ', () => { }, ]; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); expect.assertions(2); try { @@ -395,7 +404,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -425,7 +434,7 @@ describe('execute(): ', () => { 'allow-padding': false, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { @@ -464,7 +473,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { @@ -538,7 +547,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { @@ -578,7 +587,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { @@ -622,7 +631,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -651,7 +660,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { @@ -690,7 +699,7 @@ describe('execute(): ', () => { 'allow-padding': false, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -720,7 +729,7 @@ describe('execute(): ', () => { 'allow-padding': false, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -750,7 +759,7 @@ describe('execute(): ', () => { 'allow-padding': false, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); try { await timeModel.execute([ @@ -781,7 +790,7 @@ describe('execute(): ', () => { 'allow-padding': true, }; - const timeModel = TimeSync(basicConfig); + const timeModel = TimeSync(basicConfig, parametersMetadata); const result = await timeModel.execute([ { timestamp: '2023-12-12T00:00:00.000Z', diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index 56488eea2..36bbc0d1f 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -2,7 +2,10 @@ import {AggregationParams} from '../../../common/types/manifest'; -import {aggregate, storeAggregateMetrics} from '../../../if-run/lib/aggregate'; +import { + aggregate, + storeAggregationMetrics, +} from '../../../if-run/lib/aggregate'; describe('lib/aggregate: ', () => { beforeAll(() => { @@ -13,7 +16,7 @@ describe('lib/aggregate: ', () => { type: 'horizontal', }; - storeAggregateMetrics(metricStorage); + storeAggregationMetrics(metricStorage); }); describe('aggregate(): ', () => { diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index 5f8bc3325..df8a74d9b 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -5,7 +5,7 @@ import {AggregationParams} from '../../../common/types/manifest'; import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; import {AggregationMetric} from '../../../if-run/types/aggregation'; -import {storeAggregateMetrics} from '../../../if-run/lib/aggregate'; +import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -23,7 +23,7 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; - storeAggregateMetrics(metricStorage); + storeAggregationMetrics(metricStorage); }); describe('aggregateInputsIntoOne(): ', () => { @@ -105,7 +105,7 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; - storeAggregateMetrics(metricStorage); + storeAggregationMetrics(metricStorage); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, 'cpu/utilization': 10}, {timestamp: '', duration: 10, 'cpu/utilization': 90}, From 192f261628c1c035e7704b2a099617064af29ed0 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:20:59 +0400 Subject: [PATCH 436/863] feat(src): add `AggregationParamsWithoutType` type and update `storeAggregationMetrics` function --- src/common/types/manifest.ts | 5 +++++ src/if-run/lib/aggregate.ts | 13 ++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 1b003be2c..c28fe7194 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -9,6 +9,11 @@ export type GlobalPlugins = Manifest['initialize']['plugins']; export type PluginOptions = GlobalPlugins[string]; export type AggregationParams = Manifest['aggregation']; +export type AggregationParamsWithoutType = Omit< + Exclude, + 'type' +>; + export type AggregationParamsSure = Extract; export type Context = Omit; diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index a3d2d2bad..508117bb3 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -5,6 +5,7 @@ import {logger} from '../../common/util/logger'; import { AggregationParams, AggregationParamsSure, + AggregationParamsWithoutType, } from '../../common/types/manifest'; import {aggregateInputsIntoOne} from '../util/aggregation-helper'; @@ -105,13 +106,15 @@ export const aggregate = (tree: any, aggregationParams: AggregationParams) => { /** * Gets or stores aggregation metrics. - * @todo Remove these functions after resolving timeSync to be a builtin functionality. */ -export const storeAggregateMetrics = ( - aggregationParams?: AggregationParams +export const storeAggregationMetrics = ( + aggregationParams?: AggregationParamsWithoutType ) => { if (aggregationParams?.metrics) { - metricManager.metrics = aggregationParams?.metrics; + metricManager.metrics = { + ...metricManager.metrics, + ...aggregationParams?.metrics, + }; } return metricManager.metrics; @@ -141,7 +144,7 @@ const metricManager = (() => { export const getAggregationMethod = (unitName: string) => { debugLogger.setExecutingPluginName(); memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); - const aggregationMetricsStorage = storeAggregateMetrics(); + const aggregationMetricsStorage = storeAggregationMetrics(); if (aggregationMetricsStorage && `${unitName}` in aggregationMetricsStorage) { return aggregationMetricsStorage[unitName].method; From d16ba4e9e340b48df4fcc9027ee42429feb6d61c Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:22:13 +0400 Subject: [PATCH 437/863] feat(util): add `storeAggregationMethods` functionality --- src/if-run/util/helpers.ts | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts index 978ef128f..5870181e9 100644 --- a/src/if-run/util/helpers.ts +++ b/src/if-run/util/helpers.ts @@ -1,8 +1,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; -import {STRINGS} from '../config'; - import {logger} from '../../common/util/logger'; +import {GlobalPlugins} from '../../common/types/manifest'; +import {PluginStorageInterface} from '../types/plugin-storage'; +import {storeAggregationMetrics} from '../lib/aggregate'; + +import {STRINGS} from '../config'; const {UNSUPPORTED_ERROR} = STRINGS; @@ -39,3 +42,33 @@ export const mergeObjects = (defaults: any, input: any) => { return merged; }; + +/** + * Stores `aggregationMethod` of the plugins in the pipeline. + */ +export const storeAggregationMethods = ( + plugins: GlobalPlugins, + pluginStorage: PluginStorageInterface +) => { + Object.keys(plugins).forEach(pluginName => { + const plugin = pluginStorage.get(pluginName); + + if ('inputs' in plugin.metadata || 'outputs' in plugin.metadata) { + const pluginParameters = + {...plugin.metadata.inputs, ...plugin.metadata.outputs} || {}; + + Object.entries(pluginParameters).forEach( + ([parameterName, parameterMetadata]) => { + const {aggregationMethod} = parameterMetadata; + + if (aggregationMethod) { + const metrics = { + [parameterName]: {method: aggregationMethod}, + }; + storeAggregationMetrics({metrics}); + } + } + ); + } + }); +}; From 3836eb9f2e273e84fa94be3e8912386c143a6b6c Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:25:01 +0400 Subject: [PATCH 438/863] test(util): add tests for `storeAggregationMethods` function --- src/__tests__/if-run/util/helpers.test.ts | 111 +++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts index 35b60a01b..742990486 100644 --- a/src/__tests__/if-run/util/helpers.test.ts +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -3,7 +3,15 @@ const mockError = jest.fn(); import {ERRORS} from '@grnsft/if-core/utils'; -import {andHandle, mergeObjects} from '../../../if-run/util/helpers'; +import {GlobalPlugins} from '../../../common/types/manifest'; + +import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; + +import { + andHandle, + mergeObjects, + storeAggregationMethods, +} from '../../../if-run/util/helpers'; const {WriteFileError} = ERRORS; @@ -14,6 +22,10 @@ jest.mock('../../../common/util/logger', () => ({ }, })); +jest.mock('../../../if-run/lib/aggregate', () => ({ + storeAggregationMetrics: jest.fn(), +})); + describe('if-run/util/helpers: ', () => { describe('andHandle(): ', () => { afterEach(() => { @@ -166,4 +178,101 @@ describe('if-run/util/helpers: ', () => { expect(result).toEqual(expectedResult); }); }); + + describe('storeAggregationMethods(): ', () => { + const mockPluginStorage = { + get: jest.fn(), + set: jest.fn((_name, _plugin) => {}), + }; + + const mockPlugins: GlobalPlugins = { + multiply: { + path: 'builtin', + method: 'Multiply', + }, + sci: { + path: 'builtin', + method: 'Sci', + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('succefully executes with correct metrics.', () => { + const mockPlugin1 = { + execute: () => [{}], + metadata: { + kind: 'execute', + inputs: { + carbon: { + description: 'mock description', + unit: 'none', + aggregationMethod: 'sum', + }, + }, + outputs: { + cpu: { + description: 'mock description', + unit: 'none', + aggregationMethod: 'avg', + }, + }, + }, + }; + + const mockPlugin2 = { + metadata: { + inputs: {}, + outputs: { + carbon: {aggregationMethod: 'none'}, + }, + }, + }; + + mockPluginStorage.get + .mockReturnValueOnce(mockPlugin1) + .mockReturnValueOnce(mockPlugin2); + + // @ts-ignore + storeAggregationMethods(mockPlugins, mockPluginStorage); + + expect(storeAggregationMetrics).toHaveBeenCalledTimes(3); + expect(storeAggregationMetrics).toHaveBeenNthCalledWith(1, { + metrics: { + carbon: {method: 'sum'}, + }, + }); + expect(storeAggregationMetrics).toHaveBeenNthCalledWith(2, { + metrics: { + cpu: {method: 'avg'}, + }, + }); + expect(storeAggregationMetrics).toHaveBeenNthCalledWith(3, { + metrics: { + carbon: {method: 'none'}, + }, + }); + }); + + it('does not execute if there are no inputs or outputs.', () => { + mockPluginStorage.get.mockReturnValueOnce({ + execute: () => [{}], + metadata: {}, + }); + + const mockPlugin = { + execute: () => [{}], + metadata: { + kind: 'execute', + }, + }; + + mockPluginStorage.get.mockReturnValueOnce(mockPlugin); + // @ts-ignore + storeAggregationMethods(mockPlugins, mockPluginStorage); + expect(storeAggregationMetrics).not.toHaveBeenCalled(); + }); + }); }); From 4b20ff05bc19bd7d62414cb12217f1accbaacd09 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:30:39 +0400 Subject: [PATCH 439/863] feat(src): call `storeAggregationMethods` function from impactEngine --- src/if-run/index.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 5ffb62ded..eb0daeb24 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -1,19 +1,20 @@ #!/usr/bin/env node -import {aggregate, storeAggregateMetrics} from './lib/aggregate'; -import {compute} from './lib/compute'; +import {STRINGS as COMMON_STRINGS} from '../common/config'; +import {validateManifest} from '../common/util/validations'; +import {debugLogger} from '../common/util/debug-logger'; +import {logger} from '../common/util/logger'; +import {load} from '../common/lib/load'; + +import {aggregate, storeAggregationMetrics} from './lib/aggregate'; import {injectEnvironment} from './lib/environment'; -import {exhaust} from './lib/exhaust'; import {initialize} from './lib/initialize'; -import {load} from '../common/lib/load'; +import {compute} from './lib/compute'; +import {exhaust} from './lib/exhaust'; import {parseIfRunProcessArgs} from './util/args'; -import {andHandle} from './util/helpers'; -import {logger} from '../common/util/logger'; -import {validateManifest} from '../common/util/validations'; -import {debugLogger} from '../common/util/debug-logger'; +import {andHandle, storeAggregationMethods} from './util/helpers'; import {STRINGS} from './config'; -import {STRINGS as COMMON_STRINGS} from '../common/config'; const {EXITING_IF, STARTING_IF} = STRINGS; const {DISCLAIMER_MESSAGE} = COMMON_STRINGS; @@ -32,11 +33,14 @@ const impactEngine = async () => { try { const {tree, ...context} = validateManifest(envManifest); + const pluginStorage = await initialize(context.initialize.plugins); + + if (context.aggregation) { + storeAggregationMetrics({metrics: context.aggregation?.metrics}); + } - // TODO: remove this after resolving timeSync to be a builtin functionality. - storeAggregateMetrics(context.aggregation); + storeAggregationMethods(context.initialize.plugins, pluginStorage); - const pluginStorage = await initialize(context.initialize.plugins); const computedTree = await compute(tree, {context, pluginStorage}); const aggregatedTree = aggregate(computedTree, context.aggregation); await exhaust(aggregatedTree, context, outputOptions); From 24d6474ad723f4970b1b578041d28c4251d1f772 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 23 Jul 2024 20:32:39 +0400 Subject: [PATCH 440/863] fix(manifests): update manifests with time-sync and mock-observations --- .../pipelines/pipeline-with-mocks.yml | 75 ++++++++++++++++++- .../outputs/pipelines/mock-obs-time-sync.yaml | 47 +++++++++++- 2 files changed, 115 insertions(+), 7 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 9e4292f51..fa681a918 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -13,19 +13,36 @@ initialize: method: MockObservations path: "builtin" global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 + timestamp-from: 2023-12-12T00:00 + timestamp-to: 2023-12-12T00:10 duration: 60 components: - cloud/instance-type: A1 generators: common: cloud/region: uk-west - common-key: common-val randint: cpu/utilization: min: 1 max: 99 + parameter-metadata: + inputs: + timestamp: + description: refers to the time of occurrence of the input + unit: RFC3339 + aggregationMethod: none + duration: + description: refers to the duration of the input + unit: seconds + aggregationMethod: sum + cloud/instance-type: + description: type of Cloud Instance name used in the cloud provider APIs + unit: none + aggregationMethod: none + cloud/region: + description: region cloud instance + unit: none + aggregationMethod: none "interpolate": method: Interpolation path: "builtin" @@ -35,12 +52,34 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: "cpu/utilization" output-parameter: "cpu-factor" + parameter-metadata: + inputs: + cpu/utilization: + description: refers to CPU utilization. + unit: percentage + aggregationMethod: avg + outputs: + cpu-factor: + description: result of interpolate + unit: kWh + aggregationMethod: avg "cpu-factor-to-wattage": method: Multiply path: builtin global-config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" + parameter-metadata: + inputs: + cpu/thermal-design-power: + description: thermal design power for a processor + unit: kwh + aggregationMethod: avg + outputs: + cpu-wattage: + description: the energy used by the CPU + unit: kwh + aggregationMethod: sum "wattage-times-duration": method: Multiply path: builtin @@ -61,6 +100,16 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + description: total number of vcpus available on a particular resource + unit: count + aggregationMethod: none + vcpus-allocated: + description: number of vcpus allocated to particular resource + unit: count + aggregationMethod: none "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -77,6 +126,12 @@ initialize: global-config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" + parameter-metadata: + inputs: + grid/carbon-intensity: + description: Carbon intensity for the grid + unit: gCO2eq/kWh + aggregationMethod: avg "sum-carbon": path: "builtin" method: Sum @@ -90,6 +145,12 @@ initialize: method: Sci global-config: functional-unit: "requests" + parameter-metadata: + inputs: + requests: + description: expressed the final SCI value + unit: none + aggregationMethod: sum "time-sync": method: TimeSync path: "builtin" @@ -98,6 +159,12 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true + parameter-metadata: + inputs: + time-reserved: + description: time reserved for a component + unit: seconds + aggregationMethod: avg "group-by": path: builtin method: GroupBy @@ -105,6 +172,7 @@ tree: children: child-1: pipeline: + - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration @@ -156,6 +224,7 @@ tree: requests: 50 child-2: pipeline: + - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index c22a14c3e..11d8b6c34 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -7,19 +7,36 @@ initialize: path: builtin method: MockObservations global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 + timestamp-from: 2023-12-12T00:00 + timestamp-to: 2023-12-12T00:10 duration: 60 components: - cloud/instance-type: A1 generators: common: cloud/region: uk-west - common-key: common-val randint: cpu/utilization: min: 1 max: 99 + parameter-metadata: + inputs: + timestamp: + description: refers to the time of occurrence of the input + unit: RFC3339 + aggregationMethod: none + duration: + description: refers to the duration of the input + unit: seconds + aggregationMethod: sum + cloud/instance-type: + description: type of Cloud Instance name used in the cloud provider APIs + unit: none + aggregationMethod: none + cloud/region: + description: region cloud instance + unit: none + aggregationMethod: none interpolate: path: builtin method: Interpolation @@ -37,6 +54,12 @@ initialize: - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + description: refers to CPU utilization. + unit: percentage + aggregationMethod: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -45,6 +68,12 @@ initialize: - cpu-factor - cpu/thermal-design-power output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu/thermal-design-power: + description: thermal design power for a processor + unit: kwh + aggregationMethod: avg wattage-times-duration: path: builtin method: Multiply @@ -67,6 +96,16 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + description: total number of vcpus available on a particular resource + unit: count + aggregationMethod: none + vcpus-allocated: + description: number of vcpus allocated to particular resource + unit: count + aggregationMethod: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -100,7 +139,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -131,6 +169,7 @@ tree: children: child-1: pipeline: + - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration From 6e612f0fe4a874f4b9985964abc7a00c8154f9f9 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 13:40:04 +0400 Subject: [PATCH 441/863] 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 78e1a23a3..0ebf1239a 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.13", + "@grnsft/if-core": "^0.0.15", "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.13", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.13.tgz", - "integrity": "sha512-FSNzs0jL7sFaT8ZaaTS4yRl0IRBorVOgMQ7mVcQKZc9+uONosrudvWLPoDTZfxEQ5ZyFsJe6yEt2O1E53XagqQ==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.15.tgz", + "integrity": "sha512-2x38VgvoQNRXPQscIHi8s+OkgsbV38ZcU65IwgNEHEEptpo+7xlYblMUDwnZJX5alI2JFn/uVX3W1IDjxoqTfQ==", "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 ec8f48aed..9a9457f81 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.13", + "@grnsft/if-core": "^0.0.15", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 72db420085ca7a904bc264ff3bcfb54d6a35b4c8 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 13:41:25 +0400 Subject: [PATCH 442/863] test(builtins): fix time-sync tests error messages --- src/__tests__/if-run/builtins/time-sync.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 322971711..314ed06d4 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -362,7 +362,7 @@ describe('execute(): ', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toStrictEqual( new InputValidationError( - '"timestamp" parameter is required in input[0]. Error code: invalid_union.' + '"timestamp" parameter is invalid datetime in input[0]. Error code: invalid_string.' ) ); } @@ -645,7 +645,7 @@ describe('execute(): ', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toStrictEqual( new InputValidationError( - '"timestamp" parameter is invalid datetime in input[1]. Error code: invalid_string.' + '"start-time" parameter is invalid datetime. Error code: invalid_string.' ) ); } From 44c74ecbb66e8c977dc68bf44a0bb614f8bde310 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 16:42:06 +0400 Subject: [PATCH 443/863] fix(manifests): rename 'aggregationMethod' to 'aggregation-method' --- .../pipelines/pipeline-with-mocks.yml | 26 +++++++++---------- .../outputs/pipelines/mock-obs-time-sync.yaml | 16 ++++++------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index fa681a918..0ef54f32c 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -30,19 +30,19 @@ initialize: timestamp: description: refers to the time of occurrence of the input unit: RFC3339 - aggregationMethod: none + aggregation-method: none duration: description: refers to the duration of the input unit: seconds - aggregationMethod: sum + aggregation-method: sum cloud/instance-type: description: type of Cloud Instance name used in the cloud provider APIs unit: none - aggregationMethod: none + aggregation-method: none cloud/region: description: region cloud instance unit: none - aggregationMethod: none + aggregation-method: none "interpolate": method: Interpolation path: "builtin" @@ -57,12 +57,12 @@ initialize: cpu/utilization: description: refers to CPU utilization. unit: percentage - aggregationMethod: avg + aggregation-method: avg outputs: cpu-factor: description: result of interpolate unit: kWh - aggregationMethod: avg + aggregation-method: avg "cpu-factor-to-wattage": method: Multiply path: builtin @@ -74,12 +74,12 @@ initialize: cpu/thermal-design-power: description: thermal design power for a processor unit: kwh - aggregationMethod: avg + aggregation-method: avg outputs: cpu-wattage: description: the energy used by the CPU unit: kwh - aggregationMethod: sum + aggregation-method: sum "wattage-times-duration": method: Multiply path: builtin @@ -105,11 +105,11 @@ initialize: vcpus-total: description: total number of vcpus available on a particular resource unit: count - aggregationMethod: none + aggregation-method: none vcpus-allocated: description: number of vcpus allocated to particular resource unit: count - aggregationMethod: none + aggregation-method: none "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -131,7 +131,7 @@ initialize: grid/carbon-intensity: description: Carbon intensity for the grid unit: gCO2eq/kWh - aggregationMethod: avg + aggregation-method: avg "sum-carbon": path: "builtin" method: Sum @@ -150,7 +150,7 @@ initialize: requests: description: expressed the final SCI value unit: none - aggregationMethod: sum + aggregation-method: sum "time-sync": method: TimeSync path: "builtin" @@ -164,7 +164,7 @@ initialize: time-reserved: description: time reserved for a component unit: seconds - aggregationMethod: avg + aggregation-method: avg "group-by": path: builtin method: GroupBy diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index 11d8b6c34..623305f0b 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -24,19 +24,19 @@ initialize: timestamp: description: refers to the time of occurrence of the input unit: RFC3339 - aggregationMethod: none + aggregation-method: none duration: description: refers to the duration of the input unit: seconds - aggregationMethod: sum + aggregation-method: sum cloud/instance-type: description: type of Cloud Instance name used in the cloud provider APIs unit: none - aggregationMethod: none + aggregation-method: none cloud/region: description: region cloud instance unit: none - aggregationMethod: none + aggregation-method: none interpolate: path: builtin method: Interpolation @@ -59,7 +59,7 @@ initialize: cpu/utilization: description: refers to CPU utilization. unit: percentage - aggregationMethod: avg + aggregation-method: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -73,7 +73,7 @@ initialize: cpu/thermal-design-power: description: thermal design power for a processor unit: kwh - aggregationMethod: avg + aggregation-method: avg wattage-times-duration: path: builtin method: Multiply @@ -101,11 +101,11 @@ initialize: vcpus-total: description: total number of vcpus available on a particular resource unit: count - aggregationMethod: none + aggregation-method: none vcpus-allocated: description: number of vcpus allocated to particular resource unit: count - aggregationMethod: none + aggregation-method: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide From cf7f3ba99a1bd212d47f8e7d530446f41f8fcb98 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 16:44:43 +0400 Subject: [PATCH 444/863] fix(util): rename 'aggregationMethod' to 'aggregation-method' --- src/common/util/validations.ts | 4 ++-- src/if-run/util/helpers.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 39de2de1c..8599274bf 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -64,7 +64,7 @@ export const manifestSchema = z.object({ z.object({ unit: z.string(), description: z.string(), - aggregationMethod: z.string(), + 'aggregation-method': z.string(), }) ) .optional() @@ -75,7 +75,7 @@ export const manifestSchema = z.object({ z.object({ unit: z.string(), description: z.string(), - aggregationMethod: z.string(), + 'aggregation-method': z.string(), }) ) .optional() diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts index 5870181e9..da50f22f4 100644 --- a/src/if-run/util/helpers.ts +++ b/src/if-run/util/helpers.ts @@ -44,7 +44,7 @@ export const mergeObjects = (defaults: any, input: any) => { }; /** - * Stores `aggregationMethod` of the plugins in the pipeline. + * Stores `'aggregation-method'` of the plugins in the pipeline. */ export const storeAggregationMethods = ( plugins: GlobalPlugins, @@ -59,7 +59,7 @@ export const storeAggregationMethods = ( Object.entries(pluginParameters).forEach( ([parameterName, parameterMetadata]) => { - const {aggregationMethod} = parameterMetadata; + const {'aggregation-method': aggregationMethod} = parameterMetadata; if (aggregationMethod) { const metrics = { From 8dbd79d7d3259fbfb18a2fe29257137110229e35 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 16:46:19 +0400 Subject: [PATCH 445/863] fix(builtins): rename 'aggregationMethod' to 'aggregation-method' --- src/if-run/builtins/coefficient/index.ts | 4 ++-- src/if-run/builtins/sci-embodied/index.ts | 12 ++++++------ src/if-run/builtins/sci/index.ts | 6 +++--- src/if-run/builtins/time-sync.ts | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index f04a2ab74..13764bf0c 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -24,14 +24,14 @@ export const Coefficient = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, outputs: parametersMetadata?.outputs || { 'carbon-product': { description: 'a product of cabon property and the coefficient', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, }; diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 6bd7fd1b8..35e012b72 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -20,17 +20,17 @@ export const SciEmbodied = ( 'device/emissions-embodied': { description: 'total embodied emissions of some component', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, 'device/expected-lifespan': { description: 'Total Expected Lifespan of the Component in Seconds', unit: 'seconds', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, 'resources-reserved': { description: 'resources reserved for an application', unit: 'count', - aggregationMethod: 'none', + 'aggregation-method': 'none', }, 'resources-total': { description: 'total resources available', @@ -39,19 +39,19 @@ export const SciEmbodied = ( 'vcpus-allocated': { description: 'number of vcpus allocated to particular resource', unit: 'count', - aggregationMethod: 'none', + 'aggregation-method': 'none', }, 'vcpus-total': { description: 'total number of vcpus available on a particular resource', unit: 'count', - aggregationMethod: 'none', + 'aggregation-method': 'none', }, }, outputs: parametersMetadata?.outputs || { 'carbon-embodied': { description: 'embodied emissions of the component', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, }; diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index ac566fdb9..70608fe84 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -29,20 +29,20 @@ export const Sci = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, 'functional-unit': { description: 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', unit: 'none', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, outputs: parametersMetadata?.outputs || { sci: { description: 'carbon expressed in terms of the given functional unit', unit: 'gCO2e', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, }; diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index ae5a91a87..9d589c491 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -46,12 +46,12 @@ export const TimeSync = ( timestamp: { description: 'refers to the time of occurrence of the input', unit: 'RFC3339', - aggregationMethod: 'none', + 'aggregation-method': 'none', }, duration: { description: 'refers to the duration of the input', unit: 'seconds', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, outputs: parametersMetadata?.outputs, From 8537a3e54c3c540872e3f48094fc66f3abb30761 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 24 Jul 2024 16:48:49 +0400 Subject: [PATCH 446/863] test(util): rename 'aggregationMethod' to 'aggregation-method' --- src/__tests__/if-run/util/helpers.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts index 742990486..cd60b10a7 100644 --- a/src/__tests__/if-run/util/helpers.test.ts +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -209,14 +209,14 @@ describe('if-run/util/helpers: ', () => { carbon: { description: 'mock description', unit: 'none', - aggregationMethod: 'sum', + 'aggregation-method': 'sum', }, }, outputs: { cpu: { description: 'mock description', unit: 'none', - aggregationMethod: 'avg', + 'aggregation-method': 'avg', }, }, }, @@ -226,7 +226,7 @@ describe('if-run/util/helpers: ', () => { metadata: { inputs: {}, outputs: { - carbon: {aggregationMethod: 'none'}, + carbon: {'aggregation-method': 'none'}, }, }, }; From 30243818c556f18e282545de441ed3a24d51d35f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:18:54 +0400 Subject: [PATCH 447/863] feat(types): add time sync to compute --- src/if-run/types/compute.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index 6777bf553..da31b2635 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -13,6 +13,13 @@ export type PhasedPipeline = { compute?: string[]; }; +type TimeSyncConfig = { + 'start-time': string; + 'end-time': string; + interval: number; + 'allow-padding': boolean; +}; + export type ComputeParams = { pluginStorage: PluginStorageInterface; context: Context; @@ -22,6 +29,7 @@ export type ComputeParams = { observe?: Boolean; regroup?: Boolean; compute?: Boolean; + timeSync?: TimeSyncConfig | undefined | null; }; export type Node = { From 77cc1f2f77e14f5b28d869d93e95a5a94ad809b2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:19:28 +0400 Subject: [PATCH 448/863] feat(lib): add time sync --- src/if-run/lib/time-sync.ts | 475 ++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 src/if-run/lib/time-sync.ts diff --git a/src/if-run/lib/time-sync.ts b/src/if-run/lib/time-sync.ts new file mode 100644 index 000000000..d0d92e41d --- /dev/null +++ b/src/if-run/lib/time-sync.ts @@ -0,0 +1,475 @@ +import {isDate} from 'node:util/types'; + +import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + PaddingReceipt, + TimeNormalizerConfig, + TimeParams, +} from '@grnsft/if-core/types'; + +import {validate} from '../../common/util/validations'; + +import {STRINGS} from '../config'; +import {getAggregationMethod} from '../lib/aggregate'; + +Settings.defaultZone = 'utc'; + +const { + GlobalConfigError, + InvalidDateInInputError, + InvalidPaddingError, + InvalidInputError, +} = ERRORS; + +const { + INVALID_TIME_NORMALIZATION, + INVALID_OBSERVATION_OVERLAP, + AVOIDING_PADDING_BY_EDGES, + INVALID_DATE_TYPE, + START_LOWER_END, + TIMESTAMP_REQUIRED, + INVALID_DATETIME, +} = STRINGS; + +/** + * Time synchronization plugin converted into framework integrated tool. + * It can't be requested in `initialize.plugins` section anymore. Instead describe configuration in context. + * @example + * ```yaml + * name: time-sync + * description: sample in time sync lib + * tags: sample, time, sync + * time-sync: + * start-time: '2023-12-12T00:00:00.000Z' + * end-time: '2023-12-12T00:01:00.000Z' + * interval: 5 + * allow-padding: true + * ``` + */ +export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { + const metadata = { + kind: 'execute', + }; + + /** + * Take input array and return time-synchronized input array. + */ + const execute = (inputs: PluginParams[]): PluginParams[] => { + const validatedConfig = validateGlobalConfig(); + const timeParams = { + startTime: DateTime.fromISO(validatedConfig['start-time']), + endTime: DateTime.fromISO(validatedConfig['end-time']), + interval: validatedConfig.interval, + allowPadding: validatedConfig['allow-padding'], + }; + + const pad = checkForPadding(inputs, timeParams); + validatePadding(pad, timeParams); + + const paddedInputs = padInputs(inputs, pad, timeParams); + + const flattenInputs = paddedInputs.reduce( + (acc: PluginParams[], input, index) => { + const safeInput = Object.assign({}, input, validateInput(input, index)); + const currentMoment = parseDate(safeInput.timestamp); + + /** Checks if not the first input, then check consistency with previous ones. */ + if (index > 0) { + const previousInput = paddedInputs[index - 1]; + const previousInputTimestamp = parseDate(previousInput.timestamp); + + /** Checks for timestamps overlap. */ + if ( + parseDate(previousInput.timestamp).plus({ + seconds: previousInput.duration, + }) > currentMoment + ) { + throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); + } + + const compareableTime = previousInputTimestamp.plus({ + seconds: previousInput.duration, + }); + + const timelineGapSize = currentMoment + .diff(compareableTime) + .as('seconds'); + + /** Checks if there is gap in timeline. */ + if (timelineGapSize > 1) { + acc.push( + ...getZeroishInputPerSecondBetweenRange( + compareableTime, + currentMoment, + safeInput + ) + ); + } + } + /** Break down current observation. */ + for (let i = 0; i < safeInput.duration; i++) { + const normalizedInput = breakDownInput(safeInput, i); + + acc.push(normalizedInput); + } + + return trimInputsByGlobalTimeline(acc, timeParams); + }, + [] as PluginParams[] + ); + + const sortedInputs = flattenInputs.sort((a, b) => + parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') + ); + + return resampleInputs(sortedInputs, timeParams) as PluginParams[]; + }; + + /** + * Dates are passed to `time-sync` both in ISO 8601 format + * and as a Date object (from the deserialization of a YAML file). + * If the YAML parser fails to identify as a date, it passes as a string. + */ + const parseDate = (date: Date | string) => { + if (!date) { + return DateTime.invalid('Invalid date'); + } + + if (isDate(date)) { + return DateTime.fromJSDate(date); + } + + if (typeof date === 'string') { + return DateTime.fromISO(date); + } + + throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); + }; + + /** + * Validates input parameters. + */ + const validateInput = (input: PluginParams, index: number) => { + const schema = z.object({ + timestamp: z + .string({ + required_error: TIMESTAMP_REQUIRED(index), + }) + .datetime({ + message: INVALID_DATETIME(index), + }) + .or(z.date()), + duration: z.number(), + }); + + return validate>(schema, input); + }; + + /** + * Validates global config parameters. + */ + const validateGlobalConfig = () => { + if (globalConfig === undefined) { + throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); + } + + const schema = z + .object({ + 'start-time': z.string().datetime(), + 'end-time': z.string().datetime(), + interval: z.number(), + 'allow-padding': z.boolean(), + }) + .refine(data => data['start-time'] < data['end-time'], { + message: START_LOWER_END, + }); + + return validate>(schema, globalConfig); + }; + + /** + * Calculates minimal factor. + */ + const convertPerInterval = (value: number, duration: number) => + value / duration; + + /** + * Normalize time per given second. + */ + const normalizeTimePerSecond = ( + currentRoundMoment: Date | string, + i: number + ) => { + const thisMoment = parseDate(currentRoundMoment).startOf('second'); + + return thisMoment.plus({seconds: i}); + }; + + /** + * Breaks down input per minimal time unit. + */ + const breakDownInput = (input: PluginParams, i: number) => { + const inputKeys = Object.keys(input); + + return inputKeys.reduce((acc, key) => { + const method = getAggregationMethod(key); + + if (key === 'timestamp') { + const perSecond = normalizeTimePerSecond(input.timestamp, i); + acc[key] = perSecond.toUTC().toISO() ?? ''; + + return acc; + } + + /** @todo use user defined resolution later */ + if (key === 'duration') { + acc[key] = 1; + + return acc; + } + + acc[key] = + method === 'sum' + ? convertPerInterval(input[key], input['duration']) + : input[key]; + + return acc; + }, {} as PluginParams); + }; + + /** + * Populates object to fill the gaps in observational timeline using zeroish values. + */ + const fillWithZeroishInput = ( + input: PluginParams, + missingTimestamp: DateTimeMaybeValid + ) => { + const metrics = Object.keys(input); + + return metrics.reduce((acc, metric) => { + if (metric === 'timestamp') { + acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; + + return acc; + } + + /** @todo later will be changed to user defined interval */ + if (metric === 'duration') { + acc[metric] = 1; + + return acc; + } + + if (metric === 'time-reserved') { + acc[metric] = acc['duration']; + + return acc; + } + + const method = getAggregationMethod(metric); + + if (method === 'avg' || method === 'sum') { + acc[metric] = 0; + + return acc; + } + + acc[metric] = input[metric]; + + return acc; + }, {} as PluginParams); + }; + + /** + * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. + */ + const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { + const {start, end} = pad; + const isPaddingNeeded = start || end; + + if (!params.allowPadding && isPaddingNeeded) { + throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); + } + }; + + /** + * Checks if padding is needed either at start of the timeline or the end and returns status. + */ + const checkForPadding = ( + inputs: PluginParams[], + params: TimeParams + ): PaddingReceipt => { + const startDiffInSeconds = parseDate(inputs[0].timestamp) + .diff(params.startTime) + .as('seconds'); + + const lastInput = inputs[inputs.length - 1]; + + const endDiffInSeconds = parseDate(lastInput.timestamp) + .plus({second: lastInput.duration}) + .diff(params.endTime) + .as('seconds'); + + return { + start: startDiffInSeconds > 0, + end: endDiffInSeconds < 0, + }; + }; + + /** + * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. + * For methods is `avg` and `none` calculating average of the frame. + */ + const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => + inputsInTimeslot.reduce((acc, input, index, inputs) => { + const metrics = Object.keys(input); + + metrics.forEach(metric => { + const method = getAggregationMethod(metric); + acc[metric] = acc[metric] ?? 0; + + if (metric === 'timestamp') { + acc[metric] = inputs[0][metric]; + + return; + } + + if (method === 'sum') { + acc[metric] += input[metric]; + + return; + } + + if (method === 'none') { + acc[metric] = input[metric]; + + return; + } + + /** + * If timeslot contains records more than one, then divide each metric by the timeslot length, + * so that their sum yields the timeslot average. + */ + if ( + inputsInTimeslot.length > 1 && + index === inputsInTimeslot.length - 1 + ) { + acc[metric] /= inputsInTimeslot.length; + + return; + } + + acc[metric] += input[metric]; + }); + + return acc; + }, {} as PluginParams); + + /** + * Takes each array frame with interval length, then aggregating them together as from units.yaml file. + */ + const resampleInputs = (inputs: PluginParams[], params: TimeParams) => + inputs.reduce((acc: PluginParams[], _input, index, inputs) => { + const frameStart = index * params.interval; + const frameEnd = (index + 1) * params.interval; + const inputsFrame = inputs.slice(frameStart, frameEnd); + + const resampledInput = resampleInputFrame(inputsFrame); + + /** Checks if resampled input is not empty, then includes in result. */ + if (Object.keys(resampledInput).length > 0) { + acc.push(resampledInput); + } + + return acc; + }, [] as PluginParams[]); + + /** + * Pads zeroish inputs from the beginning or at the end of the inputs if needed. + */ + const padInputs = ( + inputs: PluginParams[], + pad: PaddingReceipt, + params: TimeParams + ): PluginParams[] => { + const {start, end} = pad; + const paddedFromBeginning = []; + + if (start) { + paddedFromBeginning.push( + ...getZeroishInputPerSecondBetweenRange( + params.startTime, + parseDate(inputs[0].timestamp), + inputs[0] + ) + ); + } + + const paddedArray = paddedFromBeginning.concat(inputs); + + if (end) { + const lastInput = inputs[inputs.length - 1]; + const lastInputEnd = parseDate(lastInput.timestamp).plus({ + seconds: lastInput.duration, + }); + paddedArray.push( + ...getZeroishInputPerSecondBetweenRange( + lastInputEnd, + params.endTime.plus({seconds: 1}), + lastInput + ) + ); + } + + return paddedArray; + }; + + const getZeroishInputPerSecondBetweenRange = ( + startDate: DateTimeMaybeValid, + endDate: DateTimeMaybeValid, + templateInput: PluginParams + ) => { + const array: PluginParams[] = []; + const dateRange = Interval.fromDateTimes(startDate, endDate); + + for (const interval of dateRange.splitBy({second: 1})) { + array.push( + fillWithZeroishInput( + templateInput, + // as far as I can tell, start will never be null + // because if we pass an invalid start/endDate to + // Interval, we get a zero length array as the range + interval.start || DateTime.invalid('not expected - start is null') + ) + ); + } + + return array; + }; + + /* + * Checks if input's timestamp is included in global specified period then leaves it, otherwise. + */ + const trimInputsByGlobalTimeline = ( + inputs: PluginParams[], + params: TimeParams + ): PluginParams[] => + inputs.reduce((acc: PluginParams[], item) => { + const {timestamp} = item; + + if ( + parseDate(timestamp) >= params.startTime && + parseDate(timestamp) <= params.endTime + ) { + acc.push(item); + } + + return acc; + }, [] as PluginParams[]); + + return {metadata, execute}; +}; From 5c7ef1da168bbc3b7db7ef794abf817c761244ad Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:21:06 +0400 Subject: [PATCH 449/863] feat(lib): add time sync logic yo initialize --- src/if-run/lib/initialize.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 5833787ba..dc115fac4 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -9,7 +9,7 @@ import {pluginStorage} from '../util/plugin-storage'; import {CONFIG, STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; -import {GlobalPlugins, PluginOptions} from '../../common/types/manifest'; +import {Context, PluginOptions} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; const { @@ -27,6 +27,7 @@ const { LOADING_PLUGIN_FROM_PATH, INITIALIZING_PLUGIN, INITIALIZING_PLUGINS, + INITIALIZING_TIME_SYNC, } = STRINGS; /** @@ -59,6 +60,8 @@ const handModule = (method: string, pluginPath: string) => { if (pluginPath === 'builtin') { pluginPath = path.normalize(`${__dirname}/../builtins`); + } else if (pluginPath === 'lib/time-sync') { + pluginPath = path.normalize(`${__dirname}/../${pluginPath}`); } else { if (pluginPath?.startsWith(GITHUB_PATH)) { const parts = pluginPath.split('/'); @@ -100,12 +103,24 @@ const initPlugin = async ( * Registers all plugins from `manifest`.`initialize` property. */ export const initialize = async ( - plugins: GlobalPlugins + context: Context ): Promise => { console.debug(INITIALIZING_PLUGINS); - + const {plugins} = context.initialize; const storage = pluginStorage(); + /** + * If `time-sync` is requested, then add it to plugins. + */ + if (context['time-sync']) { + console.debug(INITIALIZING_TIME_SYNC); + plugins['time-sync'] = { + path: 'lib/time-sync', + method: 'TimeSync', + 'global-config': context['time-sync'], + }; + } + for await (const pluginName of Object.keys(plugins)) { const plugin = await initPlugin(plugins[pluginName]); storage.set(pluginName, plugin); From 0cbb144389a548117e42bfaaa8b580c246aa6882 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:22:12 +0400 Subject: [PATCH 450/863] feat(lib): add time sync logic to compute --- src/if-run/lib/compute.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 8a44b8ef1..bb6677819 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -111,6 +111,13 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { }); } + /** + * Adds `time-sync` as the first plugin of compute phase if requested. + */ + if (params.timeSync) { + pipelineCopy.compute = ['time-sync', ...(pipelineCopy.compute || [])]; + } + /** * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. */ From 20f74419d9d28d471db311d9034098594e1988aa Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:28:11 +0400 Subject: [PATCH 451/863] feat(util): add time sync message --- src/if-run/config/strings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 24835f8ed..59354912b 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -47,6 +47,7 @@ Note that for the '--output' option you also need to define the output type in y CHECKING_AGGREGATION_METHOD: (unitName: string) => `Checking aggregation method for ${unitName}`, INITIALIZING_PLUGINS: 'Initializing plugins', + INITIALIZING_TIME_SYNC: 'Initializing time synchronization', INITIALIZING_PLUGIN: (pluginName: string) => `Initializing ${pluginName}`, LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => `Loading ${pluginName} from ${path}`, From d44a184075a6025fc68c882e44cbd16e5bfe26ba Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:28:54 +0400 Subject: [PATCH 452/863] revert(builtins): drop time sync --- src/if-run/builtins/index.ts | 1 - src/if-run/builtins/time-sync.ts | 458 ------------------------------- 2 files changed, 459 deletions(-) delete mode 100644 src/if-run/builtins/time-sync.ts diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts index a8ccc76fd..49b30c882 100644 --- a/src/if-run/builtins/index.ts +++ b/src/if-run/builtins/index.ts @@ -1,4 +1,3 @@ -export {TimeSync} from './time-sync'; export {Interpolation} from './interpolation'; export {MockObservations} from './mock-observations'; export {Divide} from './divide'; diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts deleted file mode 100644 index 9c14b63a4..000000000 --- a/src/if-run/builtins/time-sync.ts +++ /dev/null @@ -1,458 +0,0 @@ -import {isDate} from 'node:util/types'; - -import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - ExecutePlugin, - PluginParams, - PaddingReceipt, - TimeNormalizerConfig, - TimeParams, -} from '@grnsft/if-core/types'; - -import {validate} from '../../common/util/validations'; - -import {STRINGS} from '../config'; -import {getAggregationMethod} from '../lib/aggregate'; - -Settings.defaultZone = 'utc'; - -const { - GlobalConfigError, - InvalidDateInInputError, - InvalidPaddingError, - InvalidInputError, -} = ERRORS; - -const { - INVALID_TIME_NORMALIZATION, - INVALID_OBSERVATION_OVERLAP, - AVOIDING_PADDING_BY_EDGES, - INVALID_DATE_TYPE, - START_LOWER_END, - TIMESTAMP_REQUIRED, - INVALID_DATETIME, -} = STRINGS; - -export const TimeSync = (globalConfig: TimeNormalizerConfig): ExecutePlugin => { - const metadata = { - kind: 'execute', - }; - - /** - * Take input array and return time-synchronized input array. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const validatedConfig = validateGlobalConfig(); - const timeParams = { - startTime: DateTime.fromISO(validatedConfig['start-time']), - endTime: DateTime.fromISO(validatedConfig['end-time']), - interval: validatedConfig.interval, - allowPadding: validatedConfig['allow-padding'], - }; - - const pad = checkForPadding(inputs, timeParams); - validatePadding(pad, timeParams); - - const paddedInputs = padInputs(inputs, pad, timeParams); - - const flattenInputs = paddedInputs.reduce( - (acc: PluginParams[], input, index) => { - const safeInput = Object.assign({}, input, validateInput(input, index)); - const currentMoment = parseDate(safeInput.timestamp); - - /** Checks if not the first input, then check consistency with previous ones. */ - if (index > 0) { - const previousInput = paddedInputs[index - 1]; - const previousInputTimestamp = parseDate(previousInput.timestamp); - - /** Checks for timestamps overlap. */ - if ( - parseDate(previousInput.timestamp).plus({ - seconds: previousInput.duration, - }) > currentMoment - ) { - throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); - } - - const compareableTime = previousInputTimestamp.plus({ - seconds: previousInput.duration, - }); - - const timelineGapSize = currentMoment - .diff(compareableTime) - .as('seconds'); - - /** Checks if there is gap in timeline. */ - if (timelineGapSize > 1) { - acc.push( - ...getZeroishInputPerSecondBetweenRange( - compareableTime, - currentMoment, - safeInput - ) - ); - } - } - /** Break down current observation. */ - for (let i = 0; i < safeInput.duration; i++) { - const normalizedInput = breakDownInput(safeInput, i); - - acc.push(normalizedInput); - } - - return trimInputsByGlobalTimeline(acc, timeParams); - }, - [] as PluginParams[] - ); - - const sortedInputs = flattenInputs.sort((a, b) => - parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') - ); - - return resampleInputs(sortedInputs, timeParams) as PluginParams[]; - }; - - const parseDate = (date: Date | string) => { - if (!date) { - return DateTime.invalid('Invalid date'); - } - - // dates are passed to time-sync.ts both in ISO 8601 format - // and as a Date object (from the deserialization of a YAML file) - // if the YAML parser fails to identify as a date, it passes as a string - if (isDate(date)) { - return DateTime.fromJSDate(date); - } - - if (typeof date === 'string') { - return DateTime.fromISO(date); - } - - throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); - }; - - /** - * Validates input parameters. - */ - const validateInput = (input: PluginParams, index: number) => { - const schema = z.object({ - timestamp: z - .string({ - required_error: TIMESTAMP_REQUIRED(index), - }) - .datetime({ - message: INVALID_DATETIME(index), - }) - .or(z.date()), - duration: z.number(), - }); - - return validate>(schema, input); - }; - - /** - * Validates global config parameters. - */ - const validateGlobalConfig = () => { - if (globalConfig === undefined) { - throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); - } - - const schema = z - .object({ - 'start-time': z.string().datetime(), - 'end-time': z.string().datetime(), - interval: z.number(), - 'allow-padding': z.boolean(), - }) - .refine(data => data['start-time'] < data['end-time'], { - message: START_LOWER_END, - }); - - return validate>(schema, globalConfig); - }; - - /** - * Calculates minimal factor. - */ - const convertPerInterval = (value: number, duration: number) => - value / duration; - - /** - * Normalize time per given second. - */ - const normalizeTimePerSecond = ( - currentRoundMoment: Date | string, - i: number - ) => { - const thisMoment = parseDate(currentRoundMoment).startOf('second'); - - return thisMoment.plus({seconds: i}); - }; - - /** - * Breaks down input per minimal time unit. - */ - const breakDownInput = (input: PluginParams, i: number) => { - const inputKeys = Object.keys(input); - - return inputKeys.reduce((acc, key) => { - const method = getAggregationMethod(key); - - if (key === 'timestamp') { - const perSecond = normalizeTimePerSecond(input.timestamp, i); - acc[key] = perSecond.toUTC().toISO() ?? ''; - - return acc; - } - - /** @todo use user defined resolution later */ - if (key === 'duration') { - acc[key] = 1; - - return acc; - } - - acc[key] = - method === 'sum' - ? convertPerInterval(input[key], input['duration']) - : input[key]; - - return acc; - }, {} as PluginParams); - }; - - /** - * Populates object to fill the gaps in observational timeline using zeroish values. - */ - const fillWithZeroishInput = ( - input: PluginParams, - missingTimestamp: DateTimeMaybeValid - ) => { - const metrics = Object.keys(input); - - return metrics.reduce((acc, metric) => { - if (metric === 'timestamp') { - acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; - - return acc; - } - - /** @todo later will be changed to user defined interval */ - if (metric === 'duration') { - acc[metric] = 1; - - return acc; - } - - if (metric === 'time-reserved') { - acc[metric] = acc['duration']; - - return acc; - } - - const method = getAggregationMethod(metric); - - if (method === 'avg' || method === 'sum') { - acc[metric] = 0; - - return acc; - } - - acc[metric] = input[metric]; - - return acc; - }, {} as PluginParams); - }; - - /** - * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. - */ - const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { - const {start, end} = pad; - const isPaddingNeeded = start || end; - - if (!params.allowPadding && isPaddingNeeded) { - throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); - } - }; - - /** - * Checks if padding is needed either at start of the timeline or the end and returns status. - */ - const checkForPadding = ( - inputs: PluginParams[], - params: TimeParams - ): PaddingReceipt => { - const startDiffInSeconds = parseDate(inputs[0].timestamp) - .diff(params.startTime) - .as('seconds'); - - const lastInput = inputs[inputs.length - 1]; - - const endDiffInSeconds = parseDate(lastInput.timestamp) - .plus({second: lastInput.duration}) - .diff(params.endTime) - .as('seconds'); - - return { - start: startDiffInSeconds > 0, - end: endDiffInSeconds < 0, - }; - }; - - /** - * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. - * For methods is `avg` and `none` calculating average of the frame. - */ - const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => - inputsInTimeslot.reduce((acc, input, index, inputs) => { - const metrics = Object.keys(input); - - metrics.forEach(metric => { - const method = getAggregationMethod(metric); - acc[metric] = acc[metric] ?? 0; - - if (metric === 'timestamp') { - acc[metric] = inputs[0][metric]; - - return; - } - - if (method === 'sum') { - acc[metric] += input[metric]; - - return; - } - - if (method === 'none') { - acc[metric] = input[metric]; - - return; - } - - /** - * If timeslot contains records more than one, then divide each metric by the timeslot length, - * so that their sum yields the timeslot average. - */ - if ( - inputsInTimeslot.length > 1 && - index === inputsInTimeslot.length - 1 - ) { - acc[metric] /= inputsInTimeslot.length; - - return; - } - - acc[metric] += input[metric]; - }); - - return acc; - }, {} as PluginParams); - - /** - * Takes each array frame with interval length, then aggregating them together as from units.yaml file. - */ - const resampleInputs = (inputs: PluginParams[], params: TimeParams) => - inputs.reduce((acc: PluginParams[], _input, index, inputs) => { - const frameStart = index * params.interval; - const frameEnd = (index + 1) * params.interval; - const inputsFrame = inputs.slice(frameStart, frameEnd); - - const resampledInput = resampleInputFrame(inputsFrame); - - /** Checks if resampled input is not empty, then includes in result. */ - if (Object.keys(resampledInput).length > 0) { - acc.push(resampledInput); - } - - return acc; - }, [] as PluginParams[]); - - /** - * Pads zeroish inputs from the beginning or at the end of the inputs if needed. - */ - const padInputs = ( - inputs: PluginParams[], - pad: PaddingReceipt, - params: TimeParams - ): PluginParams[] => { - const {start, end} = pad; - const paddedFromBeginning = []; - - if (start) { - paddedFromBeginning.push( - ...getZeroishInputPerSecondBetweenRange( - params.startTime, - parseDate(inputs[0].timestamp), - inputs[0] - ) - ); - } - - const paddedArray = paddedFromBeginning.concat(inputs); - - if (end) { - const lastInput = inputs[inputs.length - 1]; - const lastInputEnd = parseDate(lastInput.timestamp).plus({ - seconds: lastInput.duration, - }); - paddedArray.push( - ...getZeroishInputPerSecondBetweenRange( - lastInputEnd, - params.endTime.plus({seconds: 1}), - lastInput - ) - ); - } - - return paddedArray; - }; - - const getZeroishInputPerSecondBetweenRange = ( - startDate: DateTimeMaybeValid, - endDate: DateTimeMaybeValid, - templateInput: PluginParams - ) => { - const array: PluginParams[] = []; - const dateRange = Interval.fromDateTimes(startDate, endDate); - - for (const interval of dateRange.splitBy({second: 1})) { - array.push( - fillWithZeroishInput( - templateInput, - // as far as I can tell, start will never be null - // because if we pass an invalid start/endDate to - // Interval, we get a zero length array as the range - interval.start || DateTime.invalid('not expected - start is null') - ) - ); - } - - return array; - }; - - /* - * Checks if input's timestamp is included in global specified period then leaves it, otherwise. - */ - const trimInputsByGlobalTimeline = ( - inputs: PluginParams[], - params: TimeParams - ): PluginParams[] => - inputs.reduce((acc: PluginParams[], item) => { - const {timestamp} = item; - - if ( - parseDate(timestamp) >= params.startTime && - parseDate(timestamp) <= params.endTime - ) { - acc.push(item); - } - - return acc; - }, [] as PluginParams[]); - - return {metadata, execute}; -}; From fcdaae024f4b3a75870c324197c2dcd5b2497428 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:30:05 +0400 Subject: [PATCH 453/863] feat(src): pass time sync config to compute --- src/if-run/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 630f15c86..9e9c18c52 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -43,13 +43,14 @@ const impactEngine = async () => { // TODO: remove this after resolving timeSync to be a builtin functionality. storeAggregateMetrics(context.aggregation); - const pluginStorage = await initialize(context.initialize.plugins); + const pluginStorage = await initialize(context); const computedTree = await compute(tree, { context, pluginStorage, observe, regroup, compute: computeFlag, + timeSync: context['time-sync'], }); const aggregatedTree = aggregate(computedTree, context.aggregation); await exhaust(aggregatedTree, context, outputOptions); From efa9983dea23fecb0261d59fa9748ed6228ce58a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:31:36 +0400 Subject: [PATCH 454/863] feat(util): add time sync yo validations --- src/common/util/validations.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 76b785d6d..570d1abe7 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -49,6 +49,15 @@ export const manifestSchema = z.object({ }) .optional() .nullable(), + 'time-sync': z + .object({ + 'start-time': z.string(), + 'end-time': z.string(), + interval: z.number().gt(0), + 'allow-padding': z.boolean(), + }) + .optional() + .nullable(), initialize: z.object({ plugins: z.record( z.string(), From 1a221facecbc87b0c501aca0610fe274e2157e15 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:32:37 +0400 Subject: [PATCH 455/863] test(lib): move time sync to lib --- src/__tests__/if-run/{builtins => lib}/time-sync.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/__tests__/if-run/{builtins => lib}/time-sync.test.ts (99%) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/lib/time-sync.test.ts similarity index 99% rename from src/__tests__/if-run/builtins/time-sync.test.ts rename to src/__tests__/if-run/lib/time-sync.test.ts index e216690df..e181cd6ae 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/lib/time-sync.test.ts @@ -4,7 +4,7 @@ import {Settings, DateTime} from 'luxon'; import {AggregationParams} from '../../../common/types/manifest'; import {storeAggregateMetrics} from '../../../if-run/lib/aggregate'; -import {TimeSync} from '../../../if-run/builtins/time-sync'; +import {TimeSync} from '../../../if-run/lib/time-sync'; import {STRINGS} from '../../../if-run/config'; From f1f090ab978cbd5465b8cd6965155b3968e68802 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:34:30 +0400 Subject: [PATCH 456/863] test(lib): update and add cases to initialize --- src/__tests__/if-run/lib/initialize.test.ts | 184 ++++++++++++++------ 1 file changed, 129 insertions(+), 55 deletions(-) diff --git a/src/__tests__/if-run/lib/initialize.test.ts b/src/__tests__/if-run/lib/initialize.test.ts index f00142260..0eccda08b 100644 --- a/src/__tests__/if-run/lib/initialize.test.ts +++ b/src/__tests__/if-run/lib/initialize.test.ts @@ -18,7 +18,6 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {initialize} from '../../../if-run/lib/initialize'; import {STRINGS} from '../../../if-run/config'; -import {GlobalPlugins} from '../../../common/types/manifest'; const { MissingPluginPathError, @@ -30,8 +29,9 @@ const {MISSING_METHOD, MISSING_PATH, INVALID_MODULE_PATH} = STRINGS; describe('lib/initalize: ', () => { describe('initalize(): ', () => { it('creates instance with get and set methods.', async () => { - const plugins = {}; - const response = await initialize(plugins); + const context = {initialize: {plugins: {}}}; + // @ts-ignore + const response = await initialize(context); expect(response).toHaveProperty('get'); expect(response).toHaveProperty('set'); @@ -40,15 +40,20 @@ describe('lib/initalize: ', () => { }); it('checks if plugin is initalized, warning is logged and plugin has execute and metadata props.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'mockavizta', - method: 'Mockavizta', + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'mockavizta', + method: 'Mockavizta', + }, + }, }, }; - const storage = await initialize(plugins); + // @ts-ignore + const storage = await initialize(context); - const pluginName = Object.keys(plugins)[0]; + const pluginName = Object.keys(context.initialize.plugins)[0]; const module = storage.get(pluginName); expect(module).toHaveProperty('execute'); expect(module).toHaveProperty('metadata'); @@ -56,36 +61,45 @@ describe('lib/initalize: ', () => { }); it('checks if plugin is initalized with global config and has execute and metadata.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'mockavizta', - method: 'Mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'mockavizta', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; - const storage = await initialize(plugins); + // @ts-ignore + const storage = await initialize(context); - const pluginName = Object.keys(plugins)[0]; + const pluginName = Object.keys(context.initialize.plugins)[0]; const module = storage.get(pluginName); expect(module).toHaveProperty('execute'); expect(module).toHaveProperty('metadata'); }); it('throws error if plugin does not have path property.', async () => { - const plugins: GlobalPlugins = { - // @ts-ignore - mockavizta: { - method: 'Mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; try { - await initialize(plugins); + // @ts-ignore + await initialize(context); } catch (error) { expect(error).toBeInstanceOf(MissingPluginPathError); @@ -96,18 +110,22 @@ describe('lib/initalize: ', () => { }); it('throws error if plugin does not have path property.', async () => { - const plugins: GlobalPlugins = { - // @ts-ignore - mockavizta: { - path: 'mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; try { - await initialize(plugins); + // @ts-ignore + await initialize(context); } catch (error) { expect(error).toBeInstanceOf(MissingPluginMethodError); @@ -118,59 +136,115 @@ describe('lib/initalize: ', () => { }); it('checks if builtin plugin is initalized.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'builtin', - method: 'Mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'builtin', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; - const storage = await initialize(plugins); + // @ts-ignore + const storage = await initialize(context); - const pluginName = Object.keys(plugins)[0]; + const pluginName = Object.keys(context.initialize.plugins)[0]; const module = storage.get(pluginName); expect(module).toHaveProperty('execute'); expect(module).toHaveProperty('metadata'); }); + it('checks if time sync plugin is initalized.', async () => { + const context = { + initialize: { + plugins: { + 'time-sync': { + path: 'lib/time-sync', + method: 'TimeSync', + 'global-config': {}, + }, + }, + }, + }; + // @ts-ignore + const storage = await initialize(context); + + const pluginName = Object.keys(context.initialize.plugins)[0]; + const module = storage.get(pluginName); + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + }); + + it('initalizes time sync based on context.', async () => { + const context = { + initialize: { + plugins: {}, + }, + 'time-sync': { + 'start-time': '2024-09-04', + 'end-time': '2024-09-05', + 'allow-padding': true, + interval: 5, + }, + }; + // @ts-ignore + const storage = await initialize(context); + const module = storage.get('time-sync'); + + expect(module).toHaveProperty('execute'); + expect(module).toHaveProperty('metadata'); + }); + it('checks if github plugin is initalized.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'https://github.com/mockavizta', - method: 'Mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'https://github.com/mockavizta', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; - const storage = await initialize(plugins); + // @ts-ignore + const storage = await initialize(context); - const pluginName = Object.keys(plugins)[0]; + const pluginName = Object.keys(context.initialize.plugins)[0]; const module = storage.get(pluginName); expect(module).toHaveProperty('execute'); expect(module).toHaveProperty('metadata'); }); it('throws error if plugin path is invalid.', async () => { - const plugins: GlobalPlugins = { - mockavizta: { - path: 'failing-mock', - method: 'Mockavizta', - 'global-config': { - verbose: true, + const context = { + initialize: { + plugins: { + mockavizta: { + path: 'failing-mock', + method: 'Mockavizta', + 'global-config': { + verbose: true, + }, + }, }, }, }; try { - await initialize(plugins); + // @ts-ignore + await initialize(context); } catch (error: any) { expect(error).toBeInstanceOf(PluginInitializationError); expect(error.message).toEqual( INVALID_MODULE_PATH( - plugins.mockavizta.path, + context.initialize.plugins.mockavizta.path, new Error( "Cannot find module 'failing-mock' from 'src/if-run/lib/initialize.ts'" ) From 1ac50381d03799a348113484fdc615434eda2da2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 09:35:04 +0400 Subject: [PATCH 457/863] test(lib): update and add cases to compute --- src/__tests__/if-run/lib/compute.test.ts | 132 ++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index b019d4c67..1549f22f8 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -19,6 +19,59 @@ describe('lib/compute: ', () => { kind: 'execute', }, }); + const mockObservePlugin = () => ({ + execute: () => [ + {timestamp: '2024-09-02', duration: 40, 'cpu/utilization': 30}, + {timestamp: '2024-09-03', duration: 60, 'cpu/utilization': 40}, + ], + metadata: { + kind: 'execute', + }, + }); + const mockObservePluginTimeSync = () => ({ + execute: () => [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 60, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:01:00.000Z', + duration: 60, + 'cpu/utilization': 40, + }, + ], + metadata: { + kind: 'execute', + }, + }); + const mockTimeSync = () => ({ + execute: () => [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 30, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:00:30.000Z', + duration: 30, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:01:00.000Z', + duration: 30, + 'cpu/utilization': 40, + }, + { + timestamp: '2023-12-12T00:01:30.000Z', + duration: 30, + 'cpu/utilization': 40, + }, + ], + metadata: { + kind: 'execute', + }, + }); /** * Compute params. */ @@ -35,7 +88,11 @@ describe('lib/compute: ', () => { }, }, }, - pluginStorage: pluginStorage().set('mock', mockExecutePlugin()), + pluginStorage: pluginStorage() + .set('mock', mockExecutePlugin()) + .set('mock-observe', mockObservePlugin()) + .set('mock-observe-time-sync', mockObservePluginTimeSync()) + .set('time-sync', mockTimeSync()), }; describe('compute(): ', () => { @@ -221,4 +278,77 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); }); + + it('computes simple tree with observe plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {observe: ['mock-observe']}, + }, + }, + }; + + const response = await compute(tree, paramsExecute); + const expectedResult = [ + {timestamp: '2024-09-02', duration: 40, 'cpu/utilization': 30}, + {timestamp: '2024-09-03', duration: 60, 'cpu/utilization': 40}, + ]; + + expect(response.children.mockChild.inputs).toEqual(expectedResult); + }); + + it('computes simple tree with time sync plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {observe: ['mock-observe-time-sync']}, + }, + }, + }; + const timeSync = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:02:00.000Z', + interval: 5, + 'allow-padding': true, + }; + + const response = await compute(tree, {...paramsExecute, timeSync}); + const expectedInputs = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 60, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:01:00.000Z', + duration: 60, + 'cpu/utilization': 40, + }, + ]; + const expectedOutput = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 30, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:00:30.000Z', + duration: 30, + 'cpu/utilization': 30, + }, + { + timestamp: '2023-12-12T00:01:00.000Z', + duration: 30, + 'cpu/utilization': 40, + }, + { + timestamp: '2023-12-12T00:01:30.000Z', + duration: 30, + 'cpu/utilization': 40, + }, + ]; + + expect(response.children.mockChild.inputs).toEqual(expectedInputs); + expect(response.children.mockChild.outputs).toEqual(expectedOutput); + }); }); From 49a42d578015678a5e56d06174b8ed3ef86137ac Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 26 Jul 2024 14:28:08 +0400 Subject: [PATCH 458/863] feat(.github): init dispatch workflow --- .../workflows/dispatch-integration-test.yml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/dispatch-integration-test.yml diff --git a/.github/workflows/dispatch-integration-test.yml b/.github/workflows/dispatch-integration-test.yml new file mode 100644 index 000000000..6fe4904d7 --- /dev/null +++ b/.github/workflows/dispatch-integration-test.yml @@ -0,0 +1,23 @@ +name: Run if-check on requested branch + +on: + workflow_dispatch: + +jobs: + run: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + - name: Install dependencies + run: npm install + + - name: Run integration tests + run: npm run if-check -- -d manifests/outputs From 80ccf37714e82920983f79ac39404c359138eaf0 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 17:28:09 +0400 Subject: [PATCH 459/863] 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 460/863] 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 461/863] 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 462/863] 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 463/863] 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 464/863] 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 465/863] 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 466/863] 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 467/863] 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 468/863] 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 725fcfd95ebe8f754ae2213f054778bf9a002053 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 18:50:09 +0400 Subject: [PATCH 469/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ebf1239a..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.15", + "@grnsft/if-core": "^0.0.16", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1185,9 +1185,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.15.tgz", - "integrity": "sha512-2x38VgvoQNRXPQscIHi8s+OkgsbV38ZcU65IwgNEHEEptpo+7xlYblMUDwnZJX5alI2JFn/uVX3W1IDjxoqTfQ==", + "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", "zod": "^3.23.8" diff --git a/package.json b/package.json index 9a9457f81..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.15", + "@grnsft/if-core": "^0.0.16", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 14a2d1e9c4dd3d002eda6b49b0833de81f0ce8af Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 18:51:54 +0400 Subject: [PATCH 470/863] test(lib): fix git and ts waning on these tests --- src/__tests__/if-run/lib/explain.test.ts | 15 ++++++++++++++- src/__tests__/if-run/util/helpers.test.ts | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 509c3ba32..506c62669 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ import {explain, addExplainData} from '../../../if-run/lib/explain'; describe('lib/explain: ', () => { @@ -34,16 +35,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 +70,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); }); diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts index cd60b10a7..c694c0a9a 100644 --- a/src/__tests__/if-run/util/helpers.test.ts +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ const mockWarn = jest.fn(); const mockError = jest.fn(); @@ -180,9 +181,10 @@ describe('if-run/util/helpers: ', () => { }); describe('storeAggregationMethods(): ', () => { + // @typescript-eslint/no-unused-vars const mockPluginStorage = { get: jest.fn(), - set: jest.fn((_name, _plugin) => {}), + set: jest.fn(() => {}), }; const mockPlugins: GlobalPlugins = { From bbb219d2955127338cf1c7b0d3c5908573a751a7 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 26 Jul 2024 19:13:40 +0400 Subject: [PATCH 471/863] docs(builtins): add `aggregation-method` to the docs --- src/if-run/builtins/coefficient/README.md | 4 +++- src/if-run/builtins/copy-param/README.md | 4 +++- src/if-run/builtins/csv-lookup/README.md | 15 +++++++++++++++ src/if-run/builtins/divide/README.md | 4 +++- src/if-run/builtins/exponent/README.md | 4 +++- src/if-run/builtins/interpolation/README.md | 4 +++- src/if-run/builtins/mock-observations/README.md | 15 +++++++++++++++ src/if-run/builtins/multiply/README.md | 4 +++- src/if-run/builtins/regex/README.md | 5 +++-- src/if-run/builtins/sci-embodied/README.md | 4 +++- src/if-run/builtins/sci/README.md | 4 +++- src/if-run/builtins/shell/README.md | 15 +++++++++++++++ src/if-run/builtins/subtract/README.md | 4 +++- src/if-run/builtins/sum/README.md | 4 +++- 14 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index f0e16cb4b..a80f4e4fb 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -18,17 +18,19 @@ Three parameters are required in global config: `input-parameter`, `coefficient` ### Plugin parameter metadata -The `parameter-metadata` section contains information about `description` and `unit` +The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `input-parameter` of the global config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe parameters of the `output-parameter` of the global config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 8e6ef563a..309a83fde 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -41,16 +41,18 @@ Three parameters are required in config: `from` and `to` and `keep-existing`. ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameter of the `from` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameters of the `to` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 317f3c897..31bdcdb17 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -53,6 +53,21 @@ All the following values are valid for the `output` field: - `["processor-name", "processor-model-id"]` - `[["processor-name", "processor-model-id"],["tdp","thermal-design-power"]]` +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs + +- `inputs`: describe the parameters of the `inputs`. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + +- `outputs`: describe the parameters in the `output` of the config block. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + ### 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. diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 98e5c0314..b17925dff 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -14,16 +14,18 @@ You provide the names of the values you want to divide, and a name to use to add ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameter of the `numerator` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `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 + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index ed1c74b35..b4f4d7d17 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -18,16 +18,18 @@ Three parameters are required in global config: `input-parameter`, `exponent` an ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes:: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index dedcfe5e9..a6d897f32 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -27,16 +27,18 @@ To employ the `Interpolation` plugin, adhere to these steps: ## 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameters of the `output-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ## Input Parameters diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 0da9211da..91f418ccb 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -17,6 +17,21 @@ The mode currently mocks 2 types of observation data: - `generators` define which fields to generate for each observation - `components` define the components for which to generate observations. The observations generated according to `timestamp-from`, `timestamp-to`, `duration` and `generators` will be duplicated for each component. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs + +- `inputs`: describe the parameters of the `inputs`. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + +- `outputs`: describe the output parameters. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + ### Authentication N/A diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 6acbb847a..86a65aecb 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -17,16 +17,18 @@ Two parameters are required in global config: `input-parameters` and `output-par ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 9a0d388c2..d9f382274 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -18,16 +18,18 @@ Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-26 ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameter of the `parameter` value of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameters of the `output` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs @@ -37,7 +39,6 @@ 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()`. diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 21266fba7..ed9c1841e 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -12,16 +12,18 @@ Not Needed ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe the parameters of the `inputs`. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the `carbon-embodied` parameter. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 4d9544ad2..d0b08c9c5 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -10,16 +10,18 @@ ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `inputs`. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the `sci` parameter which has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index 962fb46d4..5e529f922 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -22,6 +22,21 @@ The `shell` plugin interface requires a path to the plugin command. This path is - `command`: the path to the plugin executable along with the execution command as it would be entered into a shell. +### Plugin parameter metadata + +The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs + +- `inputs`: describe the parameters of the `inputs`. Each parameter has: + + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + +- `outputs`: describe the output parameter. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + ### Inputs The parameters included in the `inputs` field in the `manifest` depend entirely on the plugin itself. A typical plugin might expect the following common data to be provided as `inputs`: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 9916404bc..89a186ab3 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -17,16 +17,18 @@ Two parameters are required in global config: `input-parameters` and `output-par ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 4d861f2c9..014111c6c 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -17,16 +17,18 @@ Two parameters are required in global config: `input-parameters` and `output-par ### 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`, `unit` and `aggregation-method` of the parameters of the inputs and outputs - `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter + - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) ### Inputs From 00baf6c9aacfd3cd4baa77ac234d7c47c845c0fc Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 29 Jul 2024 20:07:10 +0400 Subject: [PATCH 472/863] feat(builtins): add time-converter plugin --- src/if-run/builtins/index.ts | 1 + src/if-run/builtins/time-converter/index.ts | 103 ++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/if-run/builtins/time-converter/index.ts diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts index d22491aca..9153b95a3 100644 --- a/src/if-run/builtins/index.ts +++ b/src/if-run/builtins/index.ts @@ -14,3 +14,4 @@ export {CSVLookup} from './csv-lookup'; export {Shell} from './shell'; export {Regex} from './regex'; export {Copy} from './copy-param'; +export {TimeConverter} from './time-converter'; diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts new file mode 100644 index 000000000..cb25951a9 --- /dev/null +++ b/src/if-run/builtins/time-converter/index.ts @@ -0,0 +1,103 @@ +import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + ExecutePlugin, + PluginParams, + PluginParametersMetadata, + ConfigParams, +} from '@grnsft/if-core/types'; + +import {validate} from '../../../common/util/validations'; + +import {STRINGS} from '../../config'; + +import {TIME_UNITS_IN_SECONDS} from './config'; + +const {GlobalConfigError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +export const TimeConverter = ( + globalConfig: ConfigParams, + parametersMetadata: PluginParametersMetadata +): ExecutePlugin => { + const metadata = { + kind: 'execute', + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, + }; + + const execute = (inputs: PluginParams[]) => { + const safeGlobalConfig = validateGlobalConfig(); + const inputParameter = safeGlobalConfig['input-parameter']; + const outputParameter = safeGlobalConfig['output-parameter']; + + return inputs.map(input => { + validateInput(input, inputParameter); + + return { + ...input, + [outputParameter]: calculateEnergy(input), + }; + }); + }; + + /** + * Calculates the energy for given period. + */ + const calculateEnergy = (input: PluginParams) => { + const originalTimeUnit = globalConfig['original-time-unit']; + const originalTimeUnitInSeoncds = TIME_UNITS_IN_SECONDS[originalTimeUnit]; + const energyPerPeriod = input[globalConfig['input-parameter']]; + const newTimeUnit = + globalConfig['new-time-unit'] === 'duration' + ? input.duration + : TIME_UNITS_IN_SECONDS[globalConfig['new-time-unit']]; + const result = (energyPerPeriod / originalTimeUnitInSeoncds) * newTimeUnit; + + return Number(result.toFixed(6)); + }; + + /** + * Checks for required fields in input. + */ + const validateInput = (input: PluginParams, inputParameter: string) => { + const schema = z.object({ + duration: z.number().gte(1), + [inputParameter]: z.number(), + }); + + return validate>(schema, input); + }; + + /** + * Checks global config value are valid. + */ + const validateGlobalConfig = () => { + if (!globalConfig) { + throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + } + + const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); + const originalTimeUnitValuesWithDuration = [ + 'duration', + ...timeUnitsValues, + ] as const; + const originalTimeUnitValues = timeUnitsValues as [string, ...string[]]; + + const globalConfigSchema = z.object({ + 'input-parameter': z.string(), + 'original-time-unit': z.enum(originalTimeUnitValues), + 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), + 'output-parameter': z.string().min(1), + }); + + return validate>( + globalConfigSchema, + globalConfig + ); + }; + return { + metadata, + execute, + }; +}; From 997fd434c7d7b2a51ab42ff68396c4ee46af436d Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 29 Jul 2024 20:08:22 +0400 Subject: [PATCH 473/863] feat(builtins): add config file --- .../{sci => time-converter}/config.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) rename src/if-run/builtins/{sci => time-converter}/config.ts (64%) diff --git a/src/if-run/builtins/sci/config.ts b/src/if-run/builtins/time-converter/config.ts similarity index 64% rename from src/if-run/builtins/sci/config.ts rename to src/if-run/builtins/time-converter/config.ts index edbf8881e..e6cdec1bf 100644 --- a/src/if-run/builtins/sci/config.ts +++ b/src/if-run/builtins/time-converter/config.ts @@ -24,17 +24,17 @@ export const TIME_UNITS_IN_SECONDS: Record = { wks: 604800, week: 604800, weeks: 604800, - m: 2419200, - mnth: 2419200, - mth: 2419200, - mnths: 2419200, - mths: 2419200, - month: 2419200, - months: 2419200, - y: 31536000, - ys: 31536000, - yr: 31536000, - yrs: 31536000, - year: 31536000, - years: 31536000, + m: 2628336, + mnth: 2628336, + mth: 2628336, + mnths: 2628336, + mths: 2628336, + month: 2628336, + months: 2628336, + y: 31556952, + ys: 31556952, + yr: 31556952, + yrs: 31556952, + year: 31556952, + years: 31556952, }; From 684f42fe2d2a8b33aa6beb77ad66fa156a0b9631 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 29 Jul 2024 20:09:55 +0400 Subject: [PATCH 474/863] docs(builtins): add README file for plugin --- src/if-run/builtins/time-converter/README.md | 136 +++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/if-run/builtins/time-converter/README.md diff --git a/src/if-run/builtins/time-converter/README.md b/src/if-run/builtins/time-converter/README.md new file mode 100644 index 000000000..4fb7d8725 --- /dev/null +++ b/src/if-run/builtins/time-converter/README.md @@ -0,0 +1,136 @@ +# Time Converter + +`time-coversion` is a generic plugin for converting energy values from a specifed time unit to a new given time unit. + +You provide the energy value, the time unit associated with this energy, and a new time unit to which you want to convert it. + +For example, you could add `energy-per-year`, the time unit `year`, and the new time unit `duration`. The `energy-per-duration` would then be added to every observation in your input array as the converted value of `energy-per-year`, `year` and `duration`. + +## Parameters + +### Plugin config + +These parameters are required in global config: + +- `input-parameter`: a string that should match an existing key in the `inputs` array +- `original-time-unit`: a string that defines the time unit of the `input-parameter`. The original time unit should be a valid unit, like `year`, `month`, `day`, `hour` and so on +- `new-time-unit`: a string that defines the new time unit that the `input-parameter` value should be converted to. The time unit can be `duration`(in which case it grabs the value from the `duration` in the input), or can be other time unit like `second`, `month`, `day`, `week` and so on +- `output-parameter`: a string defining the name to use to add the result of converting the input parameter to the output array + +### Plugin parameter metadata + +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: + + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: the aggregation method of the parameter (can be `sum`, `avg` or `none`) + +- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: + - `description`: description of the parameter + - `unit`: unit of the parameter + - `aggregation-method`: the aggregation method of the parameter (can be `sum`, `avg` or `none`) + +### Inputs + +The `input-parameter` must be available in the input array. + +## Returns + +- `output-parameter`: the converted energy of the `input-parameter` with the parameter name defined by `output-parameter` in global config. + +## Calculation + +```pseudocode +output = input-parameter / original-time-unit * new-time-unit +``` + +## Implementation + +To run the plugin, you must first create an instance of `TimeConverter`. Then, you can call `execute()`. + +```typescript +const config = { + 'input-parameter': 'energy-per-year', + 'original-time-unit': 'year', + 'new-time-unit': 'duration', + 'output-parameter': 'energy-per-duration', +}; + +const timeConverter = TimeConverter(config, parametersMetadata); +const result = timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, +]); +``` + +## 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 and does not have to be done explicitly by the user. The following is an example manifest that calls `time-coverstion`: + +```yaml +name: time-coverstion demo +description: +tags: +initialize: + plugins: + time-converter: + method: TimeConverter + path: builtin + global-config: + input-parameter: 'energy-per-year' + original-time-unit: 'year' + new-time-unit: 'duration' + output-parameter: 'energy-per-duration' +tree: + children: + child: + pipeline: + - time-converter + config: + defaults: + energy-per-year: 10000 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 +``` + +You can run this example by saving it as `./examples/manifests/time-coverstion.yml` and executing the following command from the project root: + +```sh +if-run --manifest ./examples/manifests/time-coverstion.yml --output ./examples/outputs/time-coverstion.yml +``` + +The results will be saved to a new `yaml` file in `./examples/outputs`. + +## Errors + +`TimeConverter` exposes two of the IF error classes. + +### GlobalConfigError + +You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. + +The required parameters are: + +- `input-parameter`: this must be a string, which is the name of parameter in the `inputs` array +- `original-time-unit`: this must be a string of time units (`minutes`, `seconds` and so on) +- `new-time-unit`: this must be a string of time units (e.g. `duration`, `minutes`, `seconds` and so on) +- `output-parameter`: this must be a string + +You can fix this error by checking you are providing valid values for each parameter in the config. + +### `MissingInputDataError` + +This error arises when a necessary piece of input data is missing from the `inputs` array. +Every element in the `inputs` array must contain: + +- `timestamp` +- `duration` +- whatever values you passed to `input-parameter` + +For more information on our error classes, please visit [our docs](https://if.greensoftware.foundation/reference/errors). From cedde08dd1046fdacd21fa4a074ad51f6ea939bd Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 29 Jul 2024 20:10:54 +0400 Subject: [PATCH 475/863] test(builtins): add tests for the plugin --- .../if-run/builtins/time-converter.test.ts | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/__tests__/if-run/builtins/time-converter.test.ts diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts new file mode 100644 index 000000000..ae55daf5d --- /dev/null +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -0,0 +1,126 @@ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {TimeConverter} from '../../../if-run/builtins/time-converter'; + +import {STRINGS} from '../../../if-run/config'; + +const {GlobalConfigError, InputValidationError} = ERRORS; +const {MISSING_GLOBAL_CONFIG} = STRINGS; + +describe('builtins/time-converter: ', () => { + describe('TimeConverter: ', () => { + const globalConfig = { + 'input-parameter': 'energy-per-year', + 'original-time-unit': 'year', + 'new-time-unit': 'duration', + 'output-parameter': 'energy-per-duration', + }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const timeConverter = TimeConverter(globalConfig, parametersMetadata); + + describe('init: ', () => { + it('successfully initalized.', () => { + expect(timeConverter).toHaveProperty('metadata'); + expect(timeConverter).toHaveProperty('execute'); + }); + }); + + describe('execute(): ', () => { + it('successfully applies TimeConverter strategy to given input.', () => { + expect.assertions(1); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + 'energy-per-duration': 1.140795, + }, + ]; + + const result = timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('throws an error when global config is not provided.', () => { + const config = undefined; + const timeConverter = TimeConverter(config!, parametersMetadata); + + expect.assertions(1); + + try { + timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new GlobalConfigError(MISSING_GLOBAL_CONFIG) + ); + } + }); + + it('throws an error on missing params in input.', () => { + expect.assertions(1); + + try { + timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new InputValidationError( + '"energy-per-year" parameter is required. Error code: invalid_type.' + ) + ); + } + }); + + it('returns a result when `new-time-unit` is a different time unit than `duration`.', () => { + expect.assertions(1); + const newConfig = { + 'input-parameter': 'energy-per-year', + 'original-time-unit': 'year', + 'new-time-unit': 'month', + 'output-parameter': 'energy-per-duration', + }; + const timeConverter = TimeConverter(newConfig, parametersMetadata); + + const data = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]; + const response = timeConverter.execute(data); + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + 'energy-per-duration': 832.886522, + }, + ]; + + expect(response).toEqual(expectedResult); + }); + }); + }); +}); From af4951d18e9424e04f19d53321da7d0fdff2a63a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 29 Jul 2024 20:12:52 +0400 Subject: [PATCH 476/863] feat(manifests): add success.yaml for the plugin --- .../builtins/time-converter/success.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 manifests/examples/builtins/time-converter/success.yaml diff --git a/manifests/examples/builtins/time-converter/success.yaml b/manifests/examples/builtins/time-converter/success.yaml new file mode 100644 index 000000000..30c5d987e --- /dev/null +++ b/manifests/examples/builtins/time-converter/success.yaml @@ -0,0 +1,24 @@ +name: time-converter demo +description: successful path +tags: +initialize: + plugins: + time-converter: + method: TimeConverter + path: builtin + global-config: + input-parameter: "energy-per-year" + original-time-unit: "year" + new-time-unit: "duration" + output-parameter: "energy-per-duration" +tree: + children: + child: + pipeline: + - time-converter + config: + defaults: + energy-per-year: 10000 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 From de4866da979de27d6da64af13956ea0e833724c5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 09:01:59 +0400 Subject: [PATCH 477/863] feat(src): drop time sync from plugins after exec --- src/if-run/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 481f076ce..293fef905 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -51,6 +51,10 @@ const impactEngine = async () => { timeSync: context['time-sync'], }); + if (context['time-sync']) { + delete context.initialize.plugins['time-sync']; + } + if (context.aggregation) { storeAggregationMetrics({metrics: context.aggregation?.metrics}); } From 88d3d9933d856e558aaf6a010333861654db171f Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 31 Jul 2024 15:35:59 +0400 Subject: [PATCH 478/863] fix(manifests): update pipeline with mocks --- .../pipelines/pipeline-with-mocks.yml | 123 +- .../pipelines/pipeline-with-mocks.yaml | 1290 ++++++++++------- 2 files changed, 836 insertions(+), 577 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 0ef54f32c..69605dd23 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -43,7 +43,7 @@ initialize: description: region cloud instance unit: none aggregation-method: none - "interpolate": + interpolate: method: Interpolation path: "builtin" global-config: @@ -63,7 +63,7 @@ initialize: description: result of interpolate unit: kWh aggregation-method: avg - "cpu-factor-to-wattage": + cpu-factor-to-wattage: method: Multiply path: builtin global-config: @@ -71,29 +71,59 @@ initialize: output-parameter: "cpu-wattage" parameter-metadata: inputs: + cpu-factor: + description: result of interpolate + unit: kWh + aggregation-method: avg cpu/thermal-design-power: description: thermal design power for a processor - unit: kwh + unit: kWh aggregation-method: avg outputs: cpu-wattage: description: the energy used by the CPU - unit: kwh + unit: kWh aggregation-method: sum - "wattage-times-duration": + wattage-times-duration: method: Multiply path: builtin global-config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" - "wattage-to-energy-kwh": + parameter-metadata: + inputs: + cpu-wattage: + description: Energy used by the CPU + unit: kWh + aggregation-method: sum + duration: + description: Duration of the observation + unit: seconds + aggregation-method: sum + outputs: + cpu-wattage-times-duration: + description: CPU wattage multiplied by duration + unit: kWh + aggregation-method: sum + wattage-to-energy-kwh: method: Divide path: "builtin" global-config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw - "calculate-vcpu-ratio": + parameter-metadata: + inputs: + cpu-wattage-times-duration: + description: CPU wattage multiplied by duration + unit: kWh + aggregation-method: sum + outputs: + cpu-energy-raw: + description: Raw energy used by CPU in kWh + unit: kWh + aggregation-method: sum + calculate-vcpu-ratio: method: Divide path: "builtin" global-config: @@ -110,17 +140,37 @@ initialize: description: number of vcpus allocated to particular resource unit: count aggregation-method: none - "correct-cpu-energy-for-vcpu-ratio": + outputs: + vcpu-ratio: + description: Ratio of vCPUs + unit: none + aggregation-method: none + correct-cpu-energy-for-vcpu-ratio: method: Divide path: "builtin" global-config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh - "sci-embodied": + parameter-metadata: + inputs: + cpu-energy-raw: + description: Raw energy used by CPU in kWh + unit: kWh + aggregation-method: sum + vcpu-ratio: + description: Ratio of vCPUs + unit: none + aggregation-method: none + outputs: + cpu-energy-kwh: + description: Corrected CPU energy in kWh + unit: kWh + aggregation-method: sum + sci-embodied: path: "builtin" method: SciEmbodied - "operational-carbon": + operational-carbon: method: Multiply path: builtin global-config: @@ -128,11 +178,20 @@ initialize: output-parameter: "carbon-operational" parameter-metadata: inputs: + cpu-energy-kwh: + description: Corrected CPU energy in kWh + unit: kWh + aggregation-method: sum grid/carbon-intensity: description: Carbon intensity for the grid unit: gCO2eq/kWh aggregation-method: avg - "sum-carbon": + outputs: + carbon-operational: + description: Operational carbon footprint + unit: gCO2eq + aggregation-method: sum + sum-carbon: path: "builtin" method: Sum global-config: @@ -140,7 +199,22 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon - "sci": + parameter-metadata: + inputs: + carbon-operational: + description: Operational carbon footprint + unit: gCO2eq + aggregation-method: sum + carbon-embodied: + description: Embodied carbon footprint + unit: gCO2eq + aggregation-method: sum + outputs: + carbon: + description: Total carbon footprint + unit: gCO2eq + aggregation-method: sum + sci: path: "builtin" method: Sci global-config: @@ -151,7 +225,12 @@ initialize: description: expressed the final SCI value unit: none aggregation-method: sum - "time-sync": + outputs: + sci: + description: Scientific Carbon Intensity + unit: none + aggregation-method: none + time-sync: method: TimeSync path: "builtin" global-config: @@ -165,9 +244,25 @@ initialize: description: time reserved for a component unit: seconds aggregation-method: avg - "group-by": + outputs: + synced-time: + description: Synced time + unit: none + aggregation-method: none + group-by: path: builtin method: GroupBy + parameter-metadata: + inputs: + group: + description: Group by fields + unit: none + aggregation-method: none + outputs: + grouped-data: + description: Grouped data + unit: none + aggregation-method: none tree: children: child-1: diff --git a/manifests/outputs/pipelines/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/pipeline-with-mocks.yaml index f09bc3401..39d7fef1b 100644 --- a/manifests/outputs/pipelines/pipeline-with-mocks.yaml +++ b/manifests/outputs/pipelines/pipeline-with-mocks.yaml @@ -12,19 +12,36 @@ initialize: path: builtin method: MockObservations global-config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:10 + timestamp-from: 2023-12-12T00:00 + timestamp-to: 2023-12-12T00:10 duration: 60 components: - cloud/instance-type: A1 generators: common: cloud/region: uk-west - common-key: common-val randint: cpu/utilization: min: 1 max: 99 + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none interpolate: path: builtin method: Interpolation @@ -42,6 +59,17 @@ initialize: - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -50,6 +78,21 @@ initialize: - cpu-factor - cpu/thermal-design-power output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum wattage-times-duration: path: builtin method: Multiply @@ -58,6 +101,21 @@ initialize: - cpu-wattage - duration output-parameter: cpu-wattage-times-duration + parameter-metadata: + inputs: + cpu-wattage: + unit: kWh + description: Energy used by the CPU + aggregation-method: sum + duration: + unit: seconds + description: Duration of the observation + aggregation-method: sum + outputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum wattage-to-energy-kwh: path: builtin method: Divide @@ -65,6 +123,17 @@ initialize: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -72,6 +141,21 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -79,6 +163,21 @@ initialize: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh + parameter-metadata: + inputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none + outputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum sci-embodied: path: builtin method: SciEmbodied @@ -90,6 +189,21 @@ initialize: - cpu-energy-kwh - grid/carbon-intensity output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum sum-carbon: path: builtin method: Sum @@ -98,11 +212,37 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum + carbon-embodied: + unit: gCO2eq + description: Embodied carbon footprint + aggregation-method: sum + outputs: + carbon: + unit: gCO2eq + description: Total carbon footprint + aggregation-method: sum sci: path: builtin method: Sci global-config: functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum + outputs: + sci: + unit: none + description: Scientific Carbon Intensity + aggregation-method: none time-sync: path: builtin method: TimeSync @@ -111,27 +251,49 @@ initialize: end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true + parameter-metadata: + inputs: + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + outputs: + synced-time: + unit: none + description: Synced time + aggregation-method: none group-by: path: builtin method: GroupBy + parameter-metadata: + inputs: + group: + unit: none + description: Group by fields + aggregation-method: none + outputs: + grouped-data: + unit: none + description: Grouped data + aggregation-method: none execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m manifests/examples/pipelines/pipeline-with-mocks.yml -o - manifests/outputs/pipelines/pipeline-with-mocks + manifests/outputs/pipelines/pipeline-with-mocks-update environment: if-version: 0.5.0 os: macOS os-version: '14.5' node-version: 18.14.2 - date-time: 2024-07-19T06:34:10.878Z (UTC) + date-time: 2024-07-30T05:35:42.937Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - '@grnsft/if-core@0.0.16' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -156,12 +318,13 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: child-1: pipeline: + - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration @@ -213,308 +376,309 @@ tree: requests: 50 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 26 - requests: 62 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 - device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 - device/expected-lifespan: 170294400 - vcpus-total: 14.399999999999999 - vcpus-allocated: 1.7999999999999998 - cpu-factor: 0.662 - cpu-wattage: 66.19999999999999 - cpu-wattage-times-duration: 203 - cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: 14.399999999999999 - cpu-energy-kwh: 0.000007048611111111113 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.0056388888888888895 - carbon: 0.005649016996448503 - sci: 0.00009111317736207264 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:05.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan - requests: 25.14285714285714 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 - device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 - device/expected-lifespan: 72983314.28571428 - vcpus-total: 6.171428571428571 - vcpus-allocated: 0.7714285714285714 - cpu-factor: 0.29907142857142854 - cpu-wattage: 29.907142857142862 - cpu-wattage-times-duration: 192.25 - cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 - cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.000212800234075919 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:10.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan - requests: 16.19047619047619 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 - device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 - device/expected-lifespan: 46853485.71428572 - vcpus-total: 3.9619047619047616 - vcpus-allocated: 0.4952380952380952 - cpu-factor: 0.1850952380952381 - cpu-wattage: 18.50952380952381 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 - cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.00032124443213358406 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:15.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 - requests: 8.333333333333334 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0006241320395738205 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:20.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 - requests: 8.333333333333334 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0006241320395738205 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:25.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 - requests: 8.333333333333334 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0006241320395738205 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:30.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 - requests: 8.333333333333334 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0006241320395738205 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:35.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 - requests: 8.333333333333334 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0006241320395738205 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:40.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 - requests: 5 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 - device/emissions-embodied: 153.312 - time-reserved: 362 - device/expected-lifespan: 9460800 - vcpus-total: 0.8 - vcpus-allocated: 0.1 - cpu-factor: 0.037375 - cpu-wattage: 3.7375 - cpu-wattage-times-duration: 112.125 - cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 - cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 - carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0006241320395738205 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:45.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: 0 - cloud/region: 0 - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:50.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: 0 - cloud/region: 0 - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:55.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cloud/instance-type: 0 - cloud/region: 0 - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:01:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west duration: 1 - cloud/instance-type: 0 - cloud/region: 0 - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 25.552 + time-reserved: 3600 + device/expected-lifespan: 1576800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.0000020256215119228817 + carbon-operational: '*' + carbon: '*' + sci: '*' aggregated: - carbon: 0.04532668505834602 + carbon: '*' child-2: pipeline: + - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration @@ -567,344 +731,344 @@ tree: outputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - cpu/utilization: 52.400000000000006 - cloud/instance-type: .nan - cloud/region: .nan - requests: 62 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 - device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 - device/expected-lifespan: 170294400 - vcpus-total: 14.399999999999999 - vcpus-allocated: 1.7999999999999998 - cpu-factor: 0.9458 - cpu-wattage: 94.57999999999998 - cpu-wattage-times-duration: 258.9 - cpu-energy-raw: 0.00007191666666666668 - vcpu-ratio: 14.399999999999999 - cpu-energy-kwh: 0.000008989583333333334 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007191666666666666 - carbon: 0.007201794774226282 - sci: 0.00011615798022945616 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 28.45714285714286 - cloud/instance-type: .nan - cloud/region: .nan - requests: 36.57142857142857 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 - device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 - device/expected-lifespan: 72983314.28571428 - vcpus-total: 6.171428571428571 - vcpus-allocated: 0.7714285714285714 - cpu-factor: 0.469842857142857 - cpu-wattage: 46.98428571428572 - cpu-wattage-times-duration: 308.35 - cpu-energy-raw: 0.00008565277777777778 - vcpu-ratio: 6.171428571428571 - cpu-energy-kwh: 0.000010706597222222223 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.008565277777777778 - carbon: 0.008575405885337391 - sci: 0.0002344837546771943 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 19.342857142857145 - cloud/instance-type: .nan - cloud/region: .nan - requests: 25.42857142857143 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 - device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 - device/expected-lifespan: 46853485.71428572 - vcpus-total: 3.9619047619047616 - vcpus-allocated: 0.4952380952380952 - cpu-factor: 0.3131738095238096 - cpu-wattage: 31.31738095238095 - cpu-wattage-times-duration: 306.2 - cpu-energy-raw: 0.00008505555555555556 - vcpu-ratio: 3.9619047619047616 - cpu-energy-kwh: 0.000010631944444444445 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.008505555555555556 - carbon: 0.00851568366311517 - sci: 0.0003348864361899224 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan - requests: 10 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan - requests: 10 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan - requests: 10 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan - requests: 10 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan - requests: 10 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 - device/emissions-embodied: 255.51999999999998 - time-reserved: 600 - device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cpu/utilization: 3.3000000000000003 - cloud/instance-type: .nan - cloud/region: .nan - requests: 6 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 - device/emissions-embodied: 153.312 - time-reserved: 362 - device/expected-lifespan: 9460800 - vcpus-total: 0.8 - vcpus-allocated: 0.1 - cpu-factor: 0.05672500000000001 - cpu-wattage: 5.6725 - cpu-wattage-times-duration: 170.175 - cpu-energy-raw: 0.00004727083333333333 - vcpu-ratio: 0.8 - cpu-energy-kwh: 0.000005908854166666666 - carbon-embodied: 0.000006076864535768645 - carbon-operational: 0.004727083333333333 - carbon: 0.0047331601978691015 - sci: 0.0007888600329781836 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 5 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 25.552 + time-reserved: 3600 + device/expected-lifespan: 1576800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' aggregated: - carbon: 0.06846904616945712 + carbon: '*' outputs: - - carbon: 0.012850811770674785 + - carbon: '*' timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - - carbon: 0.013925811770674782 + - carbon: '*' timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - - carbon: 0.013716783992897007 + - carbon: '*' timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - - carbon: 0.013089700659563674 + - carbon: '*' timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - - carbon: 0.013089700659563674 + - carbon: '*' timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - - carbon: 0.013089700659563674 + - carbon: '*' timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - - carbon: 0.013089700659563674 + - carbon: '*' timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - - carbon: 0.013089700659563674 + - carbon: '*' timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - - carbon: 0.007853820395738204 + - carbon: '*' timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - - carbon: 0 + - carbon: '*' timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - - carbon: 0 + - carbon: '*' timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - - carbon: 0 + - carbon: '*' timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - - carbon: 0 + - carbon: '*' timestamp: '2023-12-12T00:01:00.000Z' duration: 1 aggregated: - carbon: 0.11379573122780316 + carbon: '*' From 6eac818b587c27dd618c36cbde60ad67706ebaa9 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 31 Jul 2024 16:51:07 +0400 Subject: [PATCH 479/863] fix(manifests): update pipeline with aggregate --- .../pipelines/pipeline-with-aggregate.yml | 100 ++++ .../pipelines/pipeline-with-aggregate.yaml | 560 +++++++++++------- 2 files changed, 430 insertions(+), 230 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index a833bcb9b..f83760e0b 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -17,12 +17,38 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: "cpu/utilization" output-parameter: "cpu-factor" + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg "cpu-factor-to-wattage": method: Multiply path: builtin global-config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum "wattage-times-duration": method: Multiply path: builtin @@ -36,6 +62,17 @@ initialize: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum "calculate-vcpu-ratio": method: Divide path: "builtin" @@ -43,6 +80,21 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -59,11 +111,32 @@ initialize: global-config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum "sci": path: "builtin" method: Sci global-config: functional-unit: requests # factor to convert per time to per f.unit + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum "sum-carbon": path: "builtin" method: Sum @@ -80,6 +153,33 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + outputs: + synced-time: + unit: none + description: Synced time + aggregation-method: none tree: children: child-1: diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml index 82e9a6280..9c0e8a05d 100644 --- a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml +++ b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml @@ -25,6 +25,17 @@ initialize: - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -33,6 +44,21 @@ initialize: - cpu-factor - cpu/thermal-design-power output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum wattage-times-duration: path: builtin method: Multiply @@ -48,6 +74,17 @@ initialize: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -55,6 +92,21 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -73,11 +125,32 @@ initialize: - cpu-energy-kwh - grid/carbon-intensity output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum sci: path: builtin method: Sci global-config: functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum sum-carbon: path: builtin method: Sum @@ -94,24 +167,51 @@ initialize: end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + outputs: + synced-time: + unit: none + description: Synced time + aggregation-method: none execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m manifests/examples/pipelines/pipeline-with-aggregate.yml -o - manifests/outputs/pipelines/pipeline-with-aggregate + manifests/outputs/pipelines/pipeline-with-aggregate-1.yaml environment: if-version: 0.5.0 os: macOS os-version: '14.5' node-version: 18.14.2 - date-time: 2024-07-19T06:33:37.703Z (UTC) + date-time: 2024-07-31T12:41:31.920Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - '@grnsft/if-core@0.0.16' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -136,7 +236,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: @@ -193,23 +293,23 @@ tree: requests: 30 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 26 + cpu/utilization: 14 requests: 14 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-total: 14.399999999999999 - vcpus-allocated: 1.7999999999999998 - cpu-factor: 0.662 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.3205 cpu-wattage: 66.19999999999999 cpu-wattage-times-duration: 203 cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000007048611111111113 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.0056388888888888895 @@ -217,22 +317,22 @@ tree: sci: 0.000403501214032036 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west requests: 9.571428571428571 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-total: 6.171428571428571 - vcpus-allocated: 0.7714285714285714 - cpu-factor: 0.29907142857142854 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.30975 cpu-wattage: 29.907142857142862 cpu-wattage-times-duration: 192.25 cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005340277777777777 @@ -240,22 +340,22 @@ tree: sci: 0.0005589976298113692 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west requests: 8.428571428571429 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-total: 3.9619047619047616 - vcpus-allocated: 0.4952380952380952 - cpu-factor: 0.1850952380952381 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 18.50952380952381 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005190972222222222 @@ -263,22 +363,22 @@ tree: sci: 0.0006170797001436077 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 requests: 5 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -286,22 +386,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 requests: 5 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -309,22 +409,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 requests: 5 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -332,22 +432,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 requests: 5 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -355,22 +455,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 requests: 5 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.06229166666666667 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -378,22 +478,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 requests: 3 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-total: 0.8 - vcpus-allocated: 0.1 - cpu-factor: 0.037375 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.22425 cpu-wattage: 3.7375 cpu-wattage-times-duration: 112.125 cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 @@ -401,22 +501,22 @@ tree: sci: 0.0010402200659563674 - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -424,22 +524,22 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -447,22 +547,22 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -470,8 +570,8 @@ tree: sci: 0 - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 requests: 0 cpu/thermal-design-power: 0 @@ -479,13 +579,13 @@ tree: device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -547,22 +647,22 @@ tree: outputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - cpu/utilization: 52.400000000000006 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 22.8 + cloud/instance-type: A1 + cloud/region: uk-west requests: 220 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-total: 14.399999999999999 - vcpus-allocated: 1.7999999999999998 - cpu-factor: 0.9458 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.41509999999999997 cpu-wattage: 94.57999999999998 cpu-wattage-times-duration: 258.9 cpu-energy-raw: 0.00007191666666666668 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000008989583333333334 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007191666666666666 @@ -570,22 +670,22 @@ tree: sci: 0.00003273543079193765 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 28.45714285714286 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 29.6 + cloud/instance-type: A1 + cloud/region: uk-west requests: 92.85714285714285 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-total: 6.171428571428571 - vcpus-allocated: 0.7714285714285714 - cpu-factor: 0.469842857142857 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.48819999999999997 cpu-wattage: 46.98428571428572 cpu-wattage-times-duration: 308.35 cpu-energy-raw: 0.00008565277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000010706597222222223 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.008565277777777778 @@ -593,22 +693,22 @@ tree: sci: 0.00009235052491901808 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 19.342857142857145 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 30.6 + cloud/instance-type: A1 + cloud/region: uk-west requests: 59.14285714285714 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-total: 3.9619047619047616 - vcpus-allocated: 0.4952380952380952 - cpu-factor: 0.3131738095238096 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.49894999999999995 cpu-wattage: 31.31738095238095 cpu-wattage-times-duration: 306.2 cpu-energy-raw: 0.00008505555555555556 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.000010631944444444445 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.008505555555555556 @@ -616,22 +716,22 @@ tree: sci: 0.0001439849894729618 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west requests: 30 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 cpu-wattage: 9.454166666666667 cpu-wattage-times-duration: 283.625 cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007878472222222222 @@ -639,22 +739,22 @@ tree: sci: 0.0002629533443260612 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west requests: 30 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 cpu-wattage: 9.454166666666667 cpu-wattage-times-duration: 283.625 cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007878472222222222 @@ -662,22 +762,22 @@ tree: sci: 0.0002629533443260612 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west requests: 30 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 cpu-wattage: 9.454166666666667 cpu-wattage-times-duration: 283.625 cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007878472222222222 @@ -685,22 +785,22 @@ tree: sci: 0.0002629533443260612 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west requests: 30 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 cpu-wattage: 9.454166666666667 cpu-wattage-times-duration: 283.625 cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007878472222222222 @@ -708,22 +808,22 @@ tree: sci: 0.0002629533443260612 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cpu/utilization: 5.5 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west requests: 30 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-total: 1.3333333333333333 - vcpus-allocated: 0.16666666666666666 - cpu-factor: 0.09454166666666668 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 cpu-wattage: 9.454166666666667 cpu-wattage-times-duration: 283.625 cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.007878472222222222 @@ -731,22 +831,22 @@ tree: sci: 0.0002629533443260612 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cpu/utilization: 3.3000000000000003 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 19.8 + cloud/instance-type: A1 + cloud/region: uk-west requests: 18 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-total: 0.8 - vcpus-allocated: 0.1 - cpu-factor: 0.05672500000000001 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.34035000000000004 cpu-wattage: 5.6725 cpu-wattage-times-duration: 170.175 cpu-energy-raw: 0.00004727083333333333 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000005908854166666666 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.004727083333333333 @@ -755,21 +855,21 @@ tree: - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -778,21 +878,21 @@ tree: - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -801,21 +901,21 @@ tree: - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -824,21 +924,21 @@ tree: - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 cpu/utilization: 0 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-total: 0 - vcpus-allocated: 0 + vcpus-total: 8 + vcpus-allocated: 1 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 From cfa1470d1919bae51a6169d863b51c954dcc72af Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 31 Jul 2024 17:19:49 +0400 Subject: [PATCH 480/863] fix(manifests): remove unused param from pipeline with aggregate --- manifests/outputs/pipelines/pipeline-with-aggregate.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml index 9c0e8a05d..e227dd7ef 100644 --- a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml +++ b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml @@ -189,11 +189,6 @@ initialize: unit: seconds description: time reserved for a component aggregation-method: avg - outputs: - synced-time: - unit: none - description: Synced time - aggregation-method: none execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node From faeaf6f2baae6b6d91168f6828d7e30428c667b4 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 31 Jul 2024 17:20:35 +0400 Subject: [PATCH 481/863] fix(manifests): update nesting pipeline --- manifests/examples/pipelines/nesting.yml | 90 ++ manifests/outputs/pipelines/nesting.yaml | 1002 ++++++++++++---------- 2 files changed, 636 insertions(+), 456 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index 9f034092f..2a154e41e 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -20,12 +20,38 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: "cpu/utilization" output-parameter: "cpu-factor" + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg "cpu-factor-to-wattage": method: Multiply path: builtin global-config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum "wattage-times-duration": method: Multiply path: builtin @@ -39,6 +65,17 @@ initialize: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum "calculate-vcpu-ratio": method: Divide path: "builtin" @@ -46,6 +83,12 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -62,11 +105,32 @@ initialize: global-config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum sci: path: "builtin" method: Sci global-config: functional-unit: "requests" + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum "sum-carbon": path: "builtin" method: Sum @@ -83,6 +147,32 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + network/energy: + description: 'Energy consumed by the Network of the component' + unit: 'kWh' + aggregation-method: 'sum' tree: children: child-0: diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index a29ceada2..13980cecd 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -28,6 +28,17 @@ initialize: - 1.02 input-parameter: cpu/utilization output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -36,6 +47,21 @@ initialize: - cpu-factor - cpu/thermal-design-power output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum wattage-times-duration: path: builtin method: Multiply @@ -51,6 +77,17 @@ initialize: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -58,6 +95,12 @@ initialize: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio + parameter-metadata: + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -76,11 +119,32 @@ initialize: - cpu-energy-kwh - grid/carbon-intensity output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum sci: path: builtin method: Sci global-config: functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum sum-carbon: path: builtin method: Sum @@ -97,24 +161,50 @@ initialize: end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + network/energy: + unit: kWh + description: Energy consumed by the Network of the component + aggregation-method: sum execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m manifests/examples/pipelines/nesting.yml -o - manifests/outputs/pipelines/nesting + manifests/outputs/pipelines/nesting-1.yaml environment: if-version: 0.5.0 os: macOS os-version: '14.5' node-version: 18.14.2 - date-time: 2024-07-19T06:32:05.687Z (UTC) + date-time: 2024-07-31T13:17:29.944Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' + - '@grnsft/if-core@0.0.16' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -139,7 +229,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: @@ -195,24 +285,24 @@ tree: requests: 55 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 66 + cpu/utilization: 22 network/energy: 0.0000018 requests: 98 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-allocated: 1.7999999999999998 - vcpus-total: 14.399999999999999 - cpu-factor: 1.0919999999999999 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4065 cpu-wattage: 109.19999999999999 cpu-wattage-times-duration: 246 cpu-energy-raw: 0.00006833333333333335 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.006833333333333334 @@ -220,23 +310,23 @@ tree: sci: 0.00006983123919278518 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 7.714285714285713e-7 requests: 52 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-allocated: 0.7714285714285714 - vcpus-total: 6.171428571428571 - cpu-factor: 0.29907142857142854 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.30975 cpu-wattage: 29.907142857142862 cpu-wattage-times-duration: 192.25 cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005340277777777777 @@ -244,23 +334,23 @@ tree: sci: 0.0001028924208718729 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 4.952380952380952e-7 requests: 33.666666666666664 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-allocated: 0.4952380952380952 - vcpus-total: 3.9619047619047616 - cpu-factor: 0.1850952380952381 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 18.50952380952381 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005190972222222222 @@ -268,23 +358,23 @@ tree: sci: 0.0001544881286073813 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 9.166666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -292,23 +382,23 @@ tree: sci: 0.0005673927632489277 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 9.166666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -316,23 +406,23 @@ tree: sci: 0.0005673927632489277 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 9.166666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -340,23 +430,23 @@ tree: sci: 0.0005673927632489277 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 9.166666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -364,23 +454,23 @@ tree: sci: 0.0005673927632489277 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 9.166666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -388,23 +478,23 @@ tree: sci: 0.0005673927632489277 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 network/energy: 1.e-7 requests: 5.5 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-allocated: 0.1 - vcpus-total: 0.8 - cpu-factor: 0.037375 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.22425 cpu-wattage: 3.7375 cpu-wattage-times-duration: 112.125 cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 @@ -412,23 +502,23 @@ tree: sci: 0.0005673927632489276 - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -436,23 +526,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -460,23 +550,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -484,8 +574,8 @@ tree: sci: 0 - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 @@ -494,13 +584,13 @@ tree: device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -560,24 +650,24 @@ tree: requests: 22 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 66 + cpu/utilization: 22 network/energy: 0.0000018 requests: 82 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-allocated: 1.7999999999999998 - vcpus-total: 14.399999999999999 - cpu-factor: 1.0919999999999999 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4065 cpu-wattage: 109.19999999999999 cpu-wattage-times-duration: 246 cpu-energy-raw: 0.00006833333333333335 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.006833333333333334 @@ -585,23 +675,23 @@ tree: sci: 0.0000834568468401579 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 7.714285714285713e-7 requests: 35.14285714285714 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-allocated: 0.7714285714285714 - vcpus-total: 6.171428571428571 - cpu-factor: 0.29907142857142854 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.30975 cpu-wattage: 29.907142857142862 cpu-wattage-times-duration: 192.25 cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005340277777777777 @@ -609,23 +699,23 @@ tree: sci: 0.00015224732194049487 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 4.952380952380952e-7 requests: 14.323809523809523 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-allocated: 0.4952380952380952 - vcpus-total: 3.9619047619047616 - cpu-factor: 0.1850952380952381 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 18.50952380952381 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005190972222222222 @@ -633,23 +723,23 @@ tree: sci: 0.000363108733129716 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 3.6666666666666665 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -657,23 +747,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 3.6666666666666665 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -681,23 +771,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 3.6666666666666665 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -705,23 +795,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 3.6666666666666665 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -729,23 +819,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 3.6666666666666665 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -753,23 +843,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 network/energy: 1.e-7 requests: 2.1999999999999997 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-allocated: 0.1 - vcpus-total: 0.8 - cpu-factor: 0.037375 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.22425 cpu-wattage: 3.7375 cpu-wattage-times-duration: 112.125 cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 @@ -777,23 +867,23 @@ tree: sci: 0.0014184819081223194 - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -801,23 +891,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -825,23 +915,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -849,8 +939,8 @@ tree: sci: 0 - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 @@ -859,13 +949,13 @@ tree: device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -927,24 +1017,24 @@ tree: requests: 40 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 66 + cpu/utilization: 22 network/energy: 0.0000018 requests: 102 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-allocated: 1.7999999999999998 - vcpus-total: 14.399999999999999 - cpu-factor: 1.0919999999999999 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4065 cpu-wattage: 109.19999999999999 cpu-wattage-times-duration: 246 cpu-energy-raw: 0.00006833333333333335 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.006833333333333334 @@ -952,23 +1042,23 @@ tree: sci: 0.00006709275922444067 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 7.714285714285713e-7 requests: 58.71428571428572 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-allocated: 0.7714285714285714 - vcpus-total: 6.171428571428571 - cpu-factor: 0.29907142857142854 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.30975 cpu-wattage: 29.907142857142862 cpu-wattage-times-duration: 192.25 cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005340277777777777 @@ -976,23 +1066,23 @@ tree: sci: 0.0000911261343001502 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 4.952380952380952e-7 requests: 36.952380952380956 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-allocated: 0.4952380952380952 - vcpus-total: 3.9619047619047616 - cpu-factor: 0.1850952380952381 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 18.50952380952381 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005190972222222222 @@ -1000,23 +1090,23 @@ tree: sci: 0.00014075142645028166 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1024,23 +1114,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1048,23 +1138,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1072,23 +1162,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1096,23 +1186,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1120,23 +1210,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 network/energy: 1.e-7 requests: 4 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-allocated: 0.1 - vcpus-total: 0.8 - cpu-factor: 0.037375 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.22425 cpu-wattage: 3.7375 cpu-wattage-times-duration: 112.125 cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 @@ -1144,23 +1234,23 @@ tree: sci: 0.0007801650494672755 - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1168,23 +1258,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1192,23 +1282,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1216,8 +1306,8 @@ tree: sci: 0 - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 @@ -1226,13 +1316,13 @@ tree: device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1292,24 +1382,24 @@ tree: requests: 40 outputs: - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: .nan - cloud/region: .nan + cloud/instance-type: A1 + cloud/region: uk-west duration: 5 - cpu/utilization: 66 + cpu/utilization: 22 network/energy: 0.0000018 requests: 90 - cpu/thermal-design-power: 180 - grid/carbon-intensity: 1440 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 2759.6159999999995 - time-reserved: 6480 + time-reserved: 2880 device/expected-lifespan: 170294400 - vcpus-allocated: 1.7999999999999998 - vcpus-total: 14.399999999999999 - cpu-factor: 1.0919999999999999 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.4065 cpu-wattage: 109.19999999999999 cpu-wattage-times-duration: 246 cpu-energy-raw: 0.00006833333333333335 - vcpu-ratio: 14.399999999999999 + vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.006833333333333334 @@ -1317,23 +1407,23 @@ tree: sci: 0.00007603846045436609 - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - cpu/utilization: 12.57142857142857 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 7.714285714285713e-7 requests: 44.28571428571428 - cpu/thermal-design-power: 77.14285714285714 - grid/carbon-intensity: 617.1428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 1182.6925714285712 - time-reserved: 2777.142857142857 + time-reserved: 2880 device/expected-lifespan: 72983314.28571428 - vcpus-allocated: 0.7714285714285714 - vcpus-total: 6.171428571428571 - cpu-factor: 0.29907142857142854 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.30975 cpu-wattage: 29.907142857142862 cpu-wattage-times-duration: 192.25 cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005340277777777777 @@ -1341,23 +1431,23 @@ tree: sci: 0.00012081561676568304 - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - cpu/utilization: 7.428571428571429 - cloud/instance-type: .nan - cloud/region: .nan + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west network/energy: 4.952380952380952e-7 requests: 28.38095238095238 - cpu/thermal-design-power: 49.52380952380953 - grid/carbon-intensity: 396.19047619047626 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 759.2594285714285 - time-reserved: 1782.8571428571431 + time-reserved: 2880 device/expected-lifespan: 46853485.71428572 - vcpus-allocated: 0.4952380952380952 - vcpus-total: 3.9619047619047616 - cpu-factor: 0.1850952380952381 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 18.50952380952381 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 + vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 carbon-embodied: 0.000010128107559614407 carbon-operational: 0.005190972222222222 @@ -1365,23 +1455,23 @@ tree: sci: 0.0001832602465191587 - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1389,23 +1479,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1413,23 +1503,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1437,23 +1527,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1461,23 +1551,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 2.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 network/energy: 1.6666666666666668e-7 requests: 6.666666666666666 - cpu/thermal-design-power: 16.666666666666668 - grid/carbon-intensity: 133.33333333333334 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 device/emissions-embodied: 255.51999999999998 - time-reserved: 600 + time-reserved: 2880 device/expected-lifespan: 15768000 - vcpus-allocated: 0.16666666666666666 - vcpus-total: 1.3333333333333333 - cpu-factor: 0.06229166666666667 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.29900000000000004 cpu-wattage: 6.229166666666667 cpu-wattage-times-duration: 186.875 cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 + vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 carbon-embodied: 0.000010128107559614409 carbon-operational: 0.005190972222222222 @@ -1485,23 +1575,23 @@ tree: sci: 0.0007801650494672756 - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - cloud/instance-type: .nan - cloud/region: .nan - cpu/utilization: 1.5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 network/energy: 1.e-7 requests: 4 - cpu/thermal-design-power: 10 - grid/carbon-intensity: 80 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 device/emissions-embodied: 153.312 - time-reserved: 362 + time-reserved: 2160.2 device/expected-lifespan: 9460800 - vcpus-allocated: 0.1 - vcpus-total: 0.8 - cpu-factor: 0.037375 + vcpus-allocated: 1 + vcpus-total: 8 + cpu-factor: 0.22425 cpu-wattage: 3.7375 cpu-wattage-times-duration: 112.125 cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 + vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 carbon-embodied: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 @@ -1509,23 +1599,23 @@ tree: sci: 0.0007801650494672755 - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1533,23 +1623,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1557,23 +1647,23 @@ tree: sci: 0 - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 device/emissions-embodied: 0 - time-reserved: 5 + time-reserved: 0.8 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 @@ -1581,8 +1671,8 @@ tree: sci: 0 - timestamp: '2023-12-12T00:01:00.000Z' duration: 1 - cloud/instance-type: 0 - cloud/region: 0 + cloud/instance-type: A1 + cloud/region: uk-west cpu/utilization: 0 network/energy: 0 requests: 0 @@ -1591,13 +1681,13 @@ tree: device/emissions-embodied: 0 time-reserved: 1 device/expected-lifespan: 0 - vcpus-allocated: 0 - vcpus-total: 0 + vcpus-allocated: 1 + vcpus-total: 8 cpu-factor: 0 cpu-wattage: 0 cpu-wattage-times-duration: 0 cpu-energy-raw: 0 - vcpu-ratio: 0 + vcpu-ratio: 8 cpu-energy-kwh: 0 carbon-embodied: 0 carbon-operational: 0 From b615bc6210c6a95cafd731e52d26fbfc7c5df978 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Wed, 31 Jul 2024 18:09:34 +0400 Subject: [PATCH 482/863] fix(manifests): update mock obs time sync --- .../outputs/pipelines/mock-obs-time-sync.yaml | 192 +++++++++--------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index 623305f0b..d1340e974 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -207,181 +207,181 @@ tree: cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: 14 + cpu/utilization: '*' cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.662 - cpu-wattage: 66.19999999999999 - cpu-wattage-times-duration: 203 - cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: 14.399999999999999 - cpu-energy-kwh: 0.000007048611111111113 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - cpu/utilization: 13 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.29907142857142854 - cpu-wattage: 29.907142857142862 - cpu-wattage-times-duration: 192.25 - cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 6.171428571428571 - cpu-energy-kwh: 0.000006675347222222222 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - cpu/utilization: 12 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.1850952380952381 - cpu-wattage: 18.50952380952381 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 3.9619047619047616 - cpu-energy-kwh: 0.0000064887152777777775 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 12 cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 12 cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 12 cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 12 cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 12 cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.06229166666666667 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 1.3333333333333333 - cpu-energy-kwh: 0.000006488715277777778 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 9 - cpu/thermal-design-power: 60 + cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0.037375 - cpu-wattage: 3.7375 - cpu-wattage-times-duration: 112.125 - cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 0.8 - cpu-energy-kwh: 0.000003893229166666667 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 0 - cpu/thermal-design-power: 0 + cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 0 - cpu/thermal-design-power: 0 + cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 0 - cpu/thermal-design-power: 0 + cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 + cpu/utilization: '*' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 0 - cpu/thermal-design-power: 0 + cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 0 - cpu-energy-kwh: 0 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: '*' + cpu-energy-kwh: '*' From fbeff3406ca5183e305075d0706e4124fedce882 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:11:04 +0400 Subject: [PATCH 483/863] revert(types): drop isGroupBy interface --- src/if-run/types/interface.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/if-run/types/interface.ts b/src/if-run/types/interface.ts index 6834a3ebb..7b6c19b33 100644 --- a/src/if-run/types/interface.ts +++ b/src/if-run/types/interface.ts @@ -4,6 +4,3 @@ export type PluginInterface = ExecutePlugin | GroupByPlugin; export const isExecute = (plugin: PluginInterface): plugin is ExecutePlugin => (plugin as ExecutePlugin).metadata.kind === 'execute'; - -export const isGroupBy = (plugin: PluginInterface): plugin is GroupByPlugin => - (plugin as GroupByPlugin).metadata.kind === 'groupby'; From b44e95f89a21a482350bff227a0fe5107f422fdd Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:12:24 +0400 Subject: [PATCH 484/863] fix(types): use plugin options in explain --- src/if-run/types/explain.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index b1b684882..c7f1a6d38 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -1,7 +1,9 @@ import {ParameterMetadata} from '@grnsft/if-core/types'; +import {PluginOptions} from '../../common/types/manifest'; + export type ExplainParams = { pluginName: string; - pluginData: {method: string; path: string}; + pluginData: PluginOptions; metadata: {inputs?: ParameterMetadata; outputs?: ParameterMetadata}; }; From 45ce81fc6dd801641818451c33393ff13845529f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:22:09 +0400 Subject: [PATCH 485/863] fix(lib): tune types in initialize --- src/if-run/lib/initialize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 1ddc745ba..afa93a2da 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -87,7 +87,7 @@ const initPlugin = async ( path, 'global-config': globalConfig, 'parameter-metadata': parameterMetadata, - } = initPluginParams; + } = initPluginParams!; console.debug(INITIALIZING_PLUGIN(method)); From 2ab3e15767666117a486ca8d21d4caab33760f6c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:22:51 +0400 Subject: [PATCH 486/863] fix(util): make plugins optional --- src/common/util/validations.ts | 64 ++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index ea1863c26..1907ed82f 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -63,37 +63,39 @@ export const manifestSchema = z.object({ initialize: z.object({ plugins: z.record( z.string(), - z.object({ - path: z.string(), - method: z.string(), - 'global-config': z.record(z.string(), z.any()).optional(), - 'parameter-metadata': z - .object({ - inputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - outputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - }) - .optional(), - }) + z + .object({ + path: z.string(), + method: z.string(), + 'global-config': z.record(z.string(), z.any()).optional(), + 'parameter-metadata': z + .object({ + inputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': z.string(), + }) + ) + .optional() + .nullable(), + outputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': z.string(), + }) + ) + .optional() + .nullable(), + }) + .optional(), + }) + .optional() ), }), execution: z From 7fc18824c2b27ea6e2aca6624e113e75c9b49b21 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:23:48 +0400 Subject: [PATCH 487/863] fix(lib): tune types in explain --- src/if-run/lib/explain.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index add1a02b6..dce49b75a 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -30,8 +30,8 @@ export const addExplainData = (params: ExplainParams) => { const {pluginName, pluginData, metadata} = params; const plugin = { [pluginName]: { - method: pluginData.method, - path: pluginData.path, + method: pluginData!.method, + path: pluginData!.path, inputs: metadata?.inputs || 'undefined', outputs: metadata?.outputs || 'undefined', }, From 84502867c65ca13811d0658958c7edaad6c9f787 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:24:50 +0400 Subject: [PATCH 488/863] fix(lib): fallback pipeline to empty object if missing, fix regroup pipeline --- src/if-run/lib/compute.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index dfa2197b4..7840a80bd 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -75,7 +75,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { let inputStorage = structuredClone(node.inputs) as PluginParams[]; inputStorage = mergeDefaults(inputStorage, defaults); - const pipelineCopy = structuredClone(pipeline); + const pipelineCopy = structuredClone(pipeline) || {}; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -94,7 +94,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { addExplainData({ pluginName, metadata: plugin.metadata, - pluginData: params.context.initialize.plugins[pluginName], + pluginData: params.context.initialize!.plugins[pluginName], }); } @@ -106,8 +106,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { /** * If regroup is requested, execute regroup strategy, delete child's inputs, outputs and empty regroup array. */ - if ((noFlags || params.regroup) && pipeline.regroup) { - node.children = Regroup(inputStorage, pipeline.regroup); + if ((noFlags || params.regroup) && pipelineCopy.regroup) { + node.children = Regroup(inputStorage, pipelineCopy.regroup); delete node.inputs; delete node.outputs; @@ -126,7 +126,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { * Adds `time-sync` as the first plugin of compute phase if requested. */ if (params.timeSync) { - pipelineCopy.compute = ['time-sync', ...(pipelineCopy.compute || [])]; + pipelineCopy.compute = [ + 'time-sync', + ...((pipelineCopy && pipelineCopy.compute) || []), + ]; } /** From 593c7afe4ec7632b278d4a9c5671e21053d0cea7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 31 Jul 2024 19:26:59 +0400 Subject: [PATCH 489/863] feat(builtins): update time sync success manifest --- .../examples/builtins/time-sync/success.yml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/manifests/examples/builtins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml index 6d1841e97..90b80580f 100644 --- a/manifests/examples/builtins/time-sync/success.yml +++ b/manifests/examples/builtins/time-sync/success.yml @@ -1,23 +1,16 @@ name: time-sync description: successful path tags: +'time-sync': + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true initialize: - output: - - yaml - plugins: - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true + plugins: {} tree: children: child: - pipeline: - - time-sync config: inputs: - timestamp: '2023-12-12T00:00:00.000Z' From 729080aaa21892b77a1edf9846b599e67cc87eac Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:17:00 +0400 Subject: [PATCH 490/863] fix(util): improve `isDirectoryExists` function in the fs.ts --- src/common/util/fs.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/util/fs.ts b/src/common/util/fs.ts index bf10af9ba..dbd6d2dcb 100644 --- a/src/common/util/fs.ts +++ b/src/common/util/fs.ts @@ -18,8 +18,8 @@ export const isFileExists = async (filePath: string) => { */ export const isDirectoryExists = async (directoryPath: string) => { try { - await fs.access(directoryPath); - return true; + const stat = await fs.lstat(directoryPath); + return stat.isDirectory(); } catch (error) { return false; } @@ -35,9 +35,9 @@ export const getYamlFiles = async (directory: string) => { for (const file of files) { const fullPath = path.join(directory, file); - const stat = await fs.lstat(fullPath); + const isDirExists = await isDirectoryExists(fullPath); - if (stat.isDirectory()) { + if (isDirExists) { yamlFiles = yamlFiles.concat(await getYamlFiles(fullPath)); } else { if (file.endsWith('.yml') || file.endsWith('.yaml')) { From b5222efc8290b8c9cc548e3d9b3ca42abfa1019f Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:20:11 +0400 Subject: [PATCH 491/863] test(mocks): update fs.ts mocks --- src/__mocks__/fs/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 0f37a4291..927509cba 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -151,7 +151,8 @@ export const readdir = (directoryPath: string) => { export const lstat = (filePath: string) => { if ( filePath.includes('mock-directory') || - filePath.includes('mock-sub-directory/subdir') + filePath.includes('mock-sub-directory/subdir') || + filePath === 'true' ) { return { isDirectory: () => true, From c52ae5a006ce4cdcb4f6539b62e55db43c265a6a Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:27:35 +0400 Subject: [PATCH 492/863] fix(config): move `DIRECTORY_NOT_FOUND` from if-check into common config --- src/common/config/strings.ts | 1 + src/if-check/config/strings.ts | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config/strings.ts b/src/common/config/strings.ts index b68d5ce7c..82592463f 100644 --- a/src/common/config/strings.ts +++ b/src/common/config/strings.ts @@ -9,4 +9,5 @@ Incubation projects are experimental, offer no support guarantee, have minimal g MANIFEST_NOT_FOUND: 'Manifest file not found.', SUCCESS_MESSAGE: 'The environment is successfully setup!', MANIFEST_IS_MISSING: 'Manifest is missing.', + DIRECTORY_NOT_FOUND: 'Directory not found.', }; diff --git a/src/if-check/config/strings.ts b/src/if-check/config/strings.ts index 1b6f1c3ef..024d57134 100644 --- a/src/if-check/config/strings.ts +++ b/src/if-check/config/strings.ts @@ -2,7 +2,6 @@ export const STRINGS = { CHECKING: 'Checking...', IF_CHECK_FLAGS_MISSING: 'Either the `--manifest` or `--directory` command should be provided with a path', - DIRECTORY_NOT_FOUND: 'Directory not found.', DIRECTORY_YAML_FILES_NOT_FOUND: 'The directory does not contain any YAML/YML files.\n', IF_CHECK_EXECUTING: (filename: string) => `Executing \`${filename}\``, From 431b30a4ba1e821a59b549bb83d2508371369222 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:29:10 +0400 Subject: [PATCH 493/863] fix(util): move `DIRECTORY_NOT_FOUND` from if-check into common config --- src/if-check/util/args.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/if-check/util/args.ts b/src/if-check/util/args.ts index ab6e3fd93..8b60f6f15 100644 --- a/src/if-check/util/args.ts +++ b/src/if-check/util/args.ts @@ -19,8 +19,9 @@ const { const {ARGS, HELP} = CONFIG; -const {IF_CHECK_FLAGS_MISSING, DIRECTORY_NOT_FOUND} = STRINGS; -const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML} = COMMON_STRINGS; +const {IF_CHECK_FLAGS_MISSING} = STRINGS; +const {MANIFEST_NOT_FOUND, SOURCE_IS_NOT_YAML, DIRECTORY_NOT_FOUND} = + COMMON_STRINGS; /** * Parses `if-check` process arguments. From d02cf9c39e04ff93d622f0ac35abdad4460fc736 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:36:32 +0400 Subject: [PATCH 494/863] fix(config): remove `optional: false` from if-csv to allow the lib to handle error --- src/if-csv/config/config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-csv/config/config.ts b/src/if-csv/config/config.ts index 8be9dba75..255776542 100644 --- a/src/if-csv/config/config.ts +++ b/src/if-csv/config/config.ts @@ -22,7 +22,6 @@ export const CONFIG = { }, params: { type: String, - optional: false, alias: 'p', description: '[parameter to export]', }, From 0ebccdf77fca548852b7a3bc508e06bf2e82b4d3 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:49:25 +0400 Subject: [PATCH 495/863] fix(config): remove `PARAMS_NOT_PRESENT` unneseccary string from if-csv --- src/if-csv/config/strings.ts | 1 - src/if-csv/util/args.ts | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/if-csv/config/strings.ts b/src/if-csv/config/strings.ts index 717461c1b..c104a19a3 100644 --- a/src/if-csv/config/strings.ts +++ b/src/if-csv/config/strings.ts @@ -1,4 +1,3 @@ export const STRINGS = { - PARAMS_NOT_PRESENT: 'Parameter not provided.', FAILURE_MESSAGE_OUTPUTS: 'Manifest outputs are not available!', }; diff --git a/src/if-csv/util/args.ts b/src/if-csv/util/args.ts index 4b9674882..fc4117460 100644 --- a/src/if-csv/util/args.ts +++ b/src/if-csv/util/args.ts @@ -4,7 +4,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {checkIfFileIsYaml} from '../../common/util/yaml'; import {prependFullFilePath} from '../../common/util/helpers'; -import {CONFIG, STRINGS} from '../config'; +import {CONFIG} from '../config'; import {STRINGS as COMMON_STRINGS} from '../../common/config'; import {IFCsvArgs} from '../types/process-args'; @@ -13,7 +13,6 @@ import {isFileExists} from '../../common/util/fs'; const {ParseCliParamsError, CliSourceFileError} = ERRORS; const {ARGS, HELP} = CONFIG; -const {PARAMS_NOT_PRESENT} = STRINGS; const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = COMMON_STRINGS; /** @@ -37,10 +36,6 @@ const validateAndParseIfCsvArgs = () => { export const parseIfCsvArgs = async () => { const {manifest, output, params} = validateAndParseIfCsvArgs(); - if (!params) { - throw new ParseCliParamsError(PARAMS_NOT_PRESENT); - } - if (manifest) { const response = prependFullFilePath(manifest); const isManifestFileExists = await isFileExists(response); From 0dafebd93b9b02e9555a4095f421a487651e81e8 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:51:33 +0400 Subject: [PATCH 496/863] test(util): update if-check test related to changes --- src/__tests__/if-check/util/args.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-check/util/args.test.ts b/src/__tests__/if-check/util/args.test.ts index de0f2a045..63a87d9d2 100644 --- a/src/__tests__/if-check/util/args.test.ts +++ b/src/__tests__/if-check/util/args.test.ts @@ -72,8 +72,9 @@ const { CliSourceFileError, ParseCliParamsError, } = ERRORS; -const {DIRECTORY_NOT_FOUND, IF_CHECK_FLAGS_MISSING} = STRINGS; -const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = COMMON_STRINGS; +const {IF_CHECK_FLAGS_MISSING} = STRINGS; +const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND, DIRECTORY_NOT_FOUND} = + COMMON_STRINGS; describe('if-check/util: ', () => { const originalEnv = process.env; From addd01b287412ff717e230bb64ceb77f12a76863 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:53:15 +0400 Subject: [PATCH 497/863] feat(config): add config and string for if-merge --- src/if-merge/config/config.ts | 41 ++++++++++++++++++++++++++++++++++ src/if-merge/config/index.ts | 2 ++ src/if-merge/config/strings.ts | 6 +++++ 3 files changed, 49 insertions(+) create mode 100644 src/if-merge/config/config.ts create mode 100644 src/if-merge/config/index.ts create mode 100644 src/if-merge/config/strings.ts diff --git a/src/if-merge/config/config.ts b/src/if-merge/config/config.ts new file mode 100644 index 000000000..d4c3059ad --- /dev/null +++ b/src/if-merge/config/config.ts @@ -0,0 +1,41 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IFMergeArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + IF_MERGE: { + ARGS: { + manifests: { + type: String, + multiple: true, + alias: 'm', + description: '[path to the manifests files]', + }, + name: { + type: String, + optional: true, + alias: 'n', + description: '[name of the merged manifest]', + }, + description: { + type: String, + optional: true, + alias: 'd', + description: '[decription of the merged manifest]', + }, + } as unknown as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Merge Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, + }, +}; diff --git a/src/if-merge/config/index.ts b/src/if-merge/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-merge/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-merge/config/strings.ts b/src/if-merge/config/strings.ts new file mode 100644 index 000000000..aa224b0ba --- /dev/null +++ b/src/if-merge/config/strings.ts @@ -0,0 +1,6 @@ +export const STRINGS = { + MERGING: 'Merging...', + SUCCESS_MESSAGE: 'Manifests are merged successfully!', + MANIFEST_IS_NOT_YAML: (path: string) => + `The \`${path}\` is not in yaml format.`, +}; From 875c86301bfd15beab23b7c30c99f6aa282a1825 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:55:39 +0400 Subject: [PATCH 498/863] feat(types): add `IFMergeArgs` type --- src/if-merge/types/process-args.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/if-merge/types/process-args.ts diff --git a/src/if-merge/types/process-args.ts b/src/if-merge/types/process-args.ts new file mode 100644 index 000000000..f34b65e8b --- /dev/null +++ b/src/if-merge/types/process-args.ts @@ -0,0 +1,5 @@ +export interface IFMergeArgs { + manifests: string[]; + name?: string; + description?: string; +} From a11de2e9864a07d3dc7c6176358deadd66920bca Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:56:39 +0400 Subject: [PATCH 499/863] feat(util): add args.ts for if-merge --- src/if-merge/util/args.ts | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/if-merge/util/args.ts diff --git a/src/if-merge/util/args.ts b/src/if-merge/util/args.ts new file mode 100644 index 000000000..98e28738f --- /dev/null +++ b/src/if-merge/util/args.ts @@ -0,0 +1,69 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {isFileExists, isDirectoryExists} from '../../common/util/fs'; +import {prependFullFilePath} from '../../common/util/helpers'; +import {checkIfFileIsYaml} from '../../common/util/yaml'; + +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFMergeArgs} from '../types/process-args'; + +import {CONFIG, STRINGS} from '../config'; + +const {ParseCliParamsError, InvalidDirectoryError, CliSourceFileError} = ERRORS; +const {IF_MERGE} = CONFIG; +const {MANIFEST_IS_NOT_YAML} = STRINGS; +const {MANIFEST_NOT_FOUND, DIRECTORY_NOT_FOUND} = COMMON_STRINGS; + +/** + * Parses `if-merge` process arguments. + */ +const validateAndParseIfMergeArgs = () => { + try { + return parse(IF_MERGE.ARGS, IF_MERGE.HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks if the `manifests` command is provided and they are valid manifests files or a folder. + */ +export const parseIfMergeArgs = async () => { + const {manifests, name, description} = validateAndParseIfMergeArgs(); + + const manifestsWithFullPath = []; + + if (manifests.length === 1) { + const isDirectory = await isDirectoryExists(manifests[0]); + if (!isDirectory) { + throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); + } + + return {manifests, name, description}; + } + + for await (const manifest of manifests) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + const isYamlFile = checkIfFileIsYaml(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(`${manifest} ${MANIFEST_NOT_FOUND}`); + } + + if (!isYamlFile) { + throw new CliSourceFileError(MANIFEST_IS_NOT_YAML(manifest)); + } + + if (checkIfFileIsYaml(manifest)) { + manifestsWithFullPath.push(response); + } + } + return {manifests: manifestsWithFullPath, name, description}; +}; From 0b680ee28a745e3df01c680b6adb8692eb0d8722 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:58:11 +0400 Subject: [PATCH 500/863] feat(util): add helpers functions for if-merge --- src/if-merge/util/helpers.ts | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/if-merge/util/helpers.ts diff --git a/src/if-merge/util/helpers.ts b/src/if-merge/util/helpers.ts new file mode 100644 index 000000000..33123c828 --- /dev/null +++ b/src/if-merge/util/helpers.ts @@ -0,0 +1,67 @@ +import * as path from 'path'; + +import {getFileName, getYamlFiles} from '../../common/util/fs'; +import {load} from '../../common/lib/load'; +import {Context} from '../../common/types/manifest'; + +import {ExportYaml} from '../../if-run/builtins/export-yaml'; + +import {IFMergeArgs} from '../types/process-args'; + +/** + * Merges the given manifests in the one file. + */ +export const mergeManifests = async (commandArgs: IFMergeArgs) => { + const {manifests: commandManifests, name, description} = commandArgs; + let manifests = commandManifests; + let manifestPath = process.env.CURRENT_DIR || process.cwd(); + + if (commandManifests.length === 1) { + manifests = await getYamlFiles(commandManifests[0]); + manifestPath = commandManifests[0]; + } + + const context = { + name: name || 'if-merge', + description: description || 'merged manifest', + tags: null, + initialize: {plugins: {}}, + }; + const tree: any = {children: {}}; + + for await (const manifest of manifests) { + const manifestName = getFileName(manifest); + const {rawManifest} = await load(manifest); + + context.tags = Object.assign({}, context.tags, rawManifest.tags); + context.initialize.plugins = { + ...context.initialize.plugins, + ...rawManifest.initialize.plugins, + }; + + Object.keys(rawManifest.tree.children).forEach(child => { + tree.children[`${child}-${manifestName}`] = { + ...rawManifest.tree.children[child], + }; + }); + } + const manifestName = name + ? `${name.replace(' ', '-')}.yaml` + : 'merged-manifest.yaml'; + const outputPath = path.join(manifestPath, manifestName); + + await saveMergedManifest(tree, context, outputPath); +}; + +/** + * Saves the merged manifest in the `merged-manifest.yaml` file. + */ +const saveMergedManifest = async ( + tree: any, + context: Context, + outputPath: string +) => { + const exportYaml = ExportYaml(); + + await exportYaml.execute(tree, context, outputPath); +}; From ac575eff8df29473393116bb626215c61a879522 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 10:59:15 +0400 Subject: [PATCH 501/863] test(util): add tests for args.ts and helpers.ts --- src/__tests__/if-merge/util/args.test.ts | 163 +++++++++++++++++++ src/__tests__/if-merge/util/helpers.test.ts | 167 ++++++++++++++++++++ src/if-merge/util/helpers.ts | 2 +- 3 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 src/__tests__/if-merge/util/args.test.ts create mode 100644 src/__tests__/if-merge/util/helpers.test.ts diff --git a/src/__tests__/if-merge/util/args.test.ts b/src/__tests__/if-merge/util/args.test.ts new file mode 100644 index 000000000..904c7e317 --- /dev/null +++ b/src/__tests__/if-merge/util/args.test.ts @@ -0,0 +1,163 @@ +import * as path from 'path'; + +jest.mock('../../../common/util/fs', () => ({ + isFileExists: () => { + if (process.env.fileExists === 'true') { + return true; + } + return false; + }, + isDirectoryExists: () => { + if (process.env.directoryExists === 'true') { + return true; + } + return false; + }, +})); + +jest.mock('ts-command-line-args', () => ({ + __esModule: true, + parse: () => { + switch (process.env.result) { + case 'manifests-are-provided': + return {manifests: ['mock-manifest1.yaml', 'mock-manifest2.yaml']}; + case 'directory-is-provided': + return {manifests: ['/mock-directory']}; + case 'flags-are-not-provided': + return {manifests: undefined, name: undefined, description: undefined}; + case 'manifest-is-not-yaml': + return {manifests: ['mock-manifest1.yaml', './mock-manifest2']}; + case 'env-throw-error': + throw new Error('mock-error'); + case 'env-throw': + throw 'mock-error'; + default: + return { + manifests: ['mock-manifest1.yaml', 'mock-manifest2.yaml'], + output: 'mock-output', + }; + } + }, +})); + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {parseIfMergeArgs} from '../../../if-merge/util/args'; + +import {STRINGS as COMMON_STRINGS} from '../../../common/config'; + +import {STRINGS} from '../../../if-merge/config'; + +const {InvalidDirectoryError, CliSourceFileError, ParseCliParamsError} = ERRORS; + +const {DIRECTORY_NOT_FOUND, MANIFEST_NOT_FOUND} = COMMON_STRINGS; +const {MANIFEST_IS_NOT_YAML} = STRINGS; + +describe('if-merge/util/args: ', () => { + const originalEnv = process.env; + + describe('parseIfMergeArgs(): ', () => { + const manifests = [ + path.join(process.cwd(), 'mock-manifest1.yaml'), + path.join(process.cwd(), 'mock-manifest2.yaml'), + ]; + it('executes when `manifest` is provided.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifests-are-provided'; + const response = await parseIfMergeArgs(); + + expect.assertions(1); + + expect(response).toEqual({ + name: undefined, + description: undefined, + manifests, + }); + }); + + it('executes when the directory is provided.', async () => { + process.env.directoryExists = 'true'; + process.env.result = 'directory-is-provided'; + + const response = await parseIfMergeArgs(); + + expect.assertions(1); + + expect(response).toEqual({ + name: undefined, + description: undefined, + manifests: ['/mock-directory'], + }); + }); + + it('throws an error when the directory does not exist.', async () => { + process.env.directoryExists = 'false'; + process.env.result = 'directory-is-provided'; + expect.assertions(1); + + try { + await parseIfMergeArgs(); + } catch (error) { + expect(error).toEqual(new InvalidDirectoryError(DIRECTORY_NOT_FOUND)); + } + }); + + it('throws an error if one of manifests is not a yaml.', async () => { + process.env.fileExists = 'true'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfMergeArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual( + new CliSourceFileError(MANIFEST_IS_NOT_YAML('./mock-manifest2')) + ); + } + } + }); + + it('throws an error if `manifest` path is invalid.', async () => { + process.env.fileExists = 'false'; + process.env.result = 'manifest-is-not-yaml'; + expect.assertions(1); + + try { + await parseIfMergeArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual( + new ParseCliParamsError(`mock-manifest1.yaml ${MANIFEST_NOT_FOUND}`) + ); + } + } + }); + + it('throws an error if parsing failed.', async () => { + process.env.result = 'env-throw-error'; + expect.assertions(1); + + try { + await parseIfMergeArgs(); + } catch (error) { + if (error instanceof Error) { + expect(error).toEqual(new ParseCliParamsError('mock-error')); + } + } + }); + + it('throws error if parsing failed (not instance of error).', async () => { + process.env.result = 'env-throw'; + expect.assertions(1); + + try { + await parseIfMergeArgs(); + } catch (error) { + expect(error).toEqual('mock-error'); + } + }); + }); + + process.env = originalEnv; +}); diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts new file mode 100644 index 000000000..f69ddd27c --- /dev/null +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -0,0 +1,167 @@ +import {mergeManifests} from '../../../if-merge/util/helpers'; +import {getFileName, getYamlFiles} from '../../../common/util/fs'; + +import {load} from '../../../common/lib/load'; + +jest.mock('../../../common/util/fs', () => ({ + getYamlFiles: jest.fn(), + getFileName: jest.fn(), + load: jest.fn(), +})); + +jest.mock('../../../common/lib/load', () => ({ + load: jest.fn(), +})); + +jest.mock('../../../if-run/builtins/export-yaml', () => ({ + ExportYaml: jest.fn().mockImplementation(() => ({ + // @ts-ignore + execute: (tree, context, outputPath) => { + const expectedContext = { + name: 'if-merge', + description: 'merged manifest', + tags: {}, + initialize: { + plugins: { + multiply: { + path: 'builtin', + method: 'Multiply', + 'global-config': { + 'input-parameters': ['cpu/utilization', 'duration'], + 'output-parameter': 'cpu-times-duration', + }, + }, + }, + }, + }; + + if (process.env.CONTEXT !== 'default-name-description') { + expectedContext.name = 'mock name'; + expectedContext.description = 'mock description'; + expect(outputPath).toBe('mock-dir/mock-name.yaml'); + } else { + expect(outputPath).toBe('mock-dir/merged-manifest.yaml'); + } + + expect(context).toEqual(expectedContext); + }, + })), +})); + +describe('if-merge/util/helpers: ', () => { + describe('mergeManifests(): ', () => { + const mockCommandArgs = { + manifests: ['manifest1.yaml', 'manifest2.yaml'], + name: 'mock name', + description: 'mock description', + }; + + const tree = { + children: { + 'child-0': { + defaults: { + 'cpu/thermal-design-power': 100, + }, + pipeline: ['sum'], + inputs: [ + { + timestamp: '2023-07-06T00:00', + duration: 1, + 'cpu/utilization': 20, + 'cpu/energy': 20, + 'network/energy': 30, + }, + ], + outputs: [ + { + timestamp: '2023-07-06T00:00', + duration: 1, + 'cpu/utilization': 20, + 'cpu/energy': 20, + 'network/energy': 30, + 'cpu/thermal-design-power': 100, + 'energy-sum': 50, + }, + ], + }, + }, + }; + const context = { + name: 'mock name', + description: 'mock description', + tags: null, + initialize: { + plugins: { + multiply: { + path: 'builtin', + method: 'Multiply', + 'global-config': { + 'input-parameters': ['cpu/utilization', 'duration'], + 'output-parameter': 'cpu-times-duration', + }, + }, + }, + }, + }; + const mockRawManifest = { + ...context, + tree, + }; + + beforeEach(() => { + jest.clearAllMocks(); + process.env.CURRENT_DIR = 'mock-dir'; + }); + + it('merges manifests correctly when there is more than one manifest.', async () => { + (getFileName as jest.Mock).mockImplementation(file => + file.replace('.yaml', '') + ); + (load as jest.Mock).mockResolvedValue({rawManifest: mockRawManifest}); + + await mergeManifests(mockCommandArgs); + + expect.assertions(4); + + expect(getFileName).toHaveBeenCalledTimes(2); + expect(load).toHaveBeenCalledTimes(2); + }); + + it('gets YAML files when there is only one manifest.', async () => { + const singleManifestArgs = { + manifests: ['mock-dir'], + name: 'mock name', + description: 'mock description', + }; + (getYamlFiles as jest.Mock).mockResolvedValue([ + 'manifest1.yaml', + 'manifest2.yaml', + ]); + (getFileName as jest.Mock).mockImplementation(file => + file.replace('.yaml', '') + ); + (load as jest.Mock).mockResolvedValue({rawManifest: mockRawManifest}); + + await mergeManifests(singleManifestArgs); + + expect.assertions(4); + expect(getYamlFiles).toHaveBeenCalledWith('mock-dir'); + expect(load).toHaveBeenCalledTimes(2); + }); + + it('uses default values for name and description if not provided.', async () => { + process.env.CONTEXT = 'default-name-description'; + + const defaultArgs = {manifests: ['manifest1.yaml', 'manifest2.yaml']}; + + (getFileName as jest.Mock).mockImplementation(file => + file.replace('.yaml', '') + ); + (load as jest.Mock).mockResolvedValue({rawManifest: mockRawManifest}); + + await mergeManifests(defaultArgs); + + expect.assertions(2); + }); + }); +}); diff --git a/src/if-merge/util/helpers.ts b/src/if-merge/util/helpers.ts index 33123c828..61fb3d59d 100644 --- a/src/if-merge/util/helpers.ts +++ b/src/if-merge/util/helpers.ts @@ -1,8 +1,8 @@ import * as path from 'path'; import {getFileName, getYamlFiles} from '../../common/util/fs'; -import {load} from '../../common/lib/load'; import {Context} from '../../common/types/manifest'; +import {load} from '../../common/lib/load'; import {ExportYaml} from '../../if-run/builtins/export-yaml'; From 54a46d90853f630c1e1e479c09cdb69d4c387360 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 11:00:32 +0400 Subject: [PATCH 502/863] feat(src): add if-merge logic --- src/if-merge/index.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/if-merge/index.ts diff --git a/src/if-merge/index.ts b/src/if-merge/index.ts new file mode 100644 index 000000000..d9d93bb0d --- /dev/null +++ b/src/if-merge/index.ts @@ -0,0 +1,33 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import {debugLogger} from '../common/util/debug-logger'; +import {logger} from '../common/util/logger'; + +import {parseIfMergeArgs} from './util/args'; +import {mergeManifests} from './util/helpers'; + +import {STRINGS} from './config'; + +const {MERGING, SUCCESS_MESSAGE} = STRINGS; + +const IfMerge = async () => { + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + + const commandArgs = await parseIfMergeArgs(); + + console.log(`${MERGING}\n`); + + await mergeManifests(commandArgs); + + console.log(SUCCESS_MESSAGE); + + process.exit(0); +}; + +IfMerge().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 1fa432660f9b10d2ba50366d4810f05cd78d415b Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 11:05:46 +0400 Subject: [PATCH 503/863] feat(package): add `if-merge` command tool into package.json --- package-lock.json | 5 +++-- package.json | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index df1de316d..03650a619 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@grnsft/if", + "name": "if-environment", "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@grnsft/if", + "name": "if-environment", "version": "0.5.0", "license": "MIT", "dependencies": { @@ -28,6 +28,7 @@ "if-csv": "build/if-csv/index.js", "if-diff": "build/if-diff/index.js", "if-env": "build/if-env/index.js", + "if-merge": "build/if-merge/index.js", "if-run": "build/if-run/index.js" }, "devDependencies": { diff --git a/package.json b/package.json index f8df2255f..0d5d9e821 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@grnsft/if", + "name": "if-environment", "description": "Impact Framework", "version": "0.5.0", "author": { @@ -11,7 +11,8 @@ "if-run": "./build/if-run/index.js", "if-env": "./build/if-env/index.js", "if-check": "./build/if-check/index.js", - "if-csv": "./build/if-csv/index.js" + "if-csv": "./build/if-csv/index.js", + "if-merge": "./build/if-merge/index.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -80,6 +81,7 @@ "if-csv": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-csv/index.ts", "if-diff": "npx ts-node src/if-diff/index.ts", "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-env/index.ts", + "if-merge": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-merge/index.ts", "if-run": "npx ts-node src/if-run/index.ts", "lint": "gts lint", "pre-commit": "lint-staged", @@ -89,4 +91,4 @@ "test": "jest --verbose --testPathPattern=src/__tests__/" }, "stability": "stable" -} +} \ No newline at end of file From 81961699f941e7da2f5c71416ecb67a696126def Mon Sep 17 00:00:00 2001 From: Manushak Keramyan Date: Thu, 1 Aug 2024 13:21:37 +0400 Subject: [PATCH 504/863] Update package.json Co-authored-by: Narek Hovhannisyan Signed-off-by: Manushak Keramyan --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d5d9e821..96e57f8e5 100644 --- a/package.json +++ b/package.json @@ -91,4 +91,4 @@ "test": "jest --verbose --testPathPattern=src/__tests__/" }, "stability": "stable" -} \ No newline at end of file +} From 49b2b5bb665c1a10e8b438091788ca46f149df87 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 13:23:19 +0400 Subject: [PATCH 505/863] fix(package): revert package name to correct one --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03650a619..256cca7e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "if-environment", + "name": "@grnsft/if", "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "if-environment", + "name": "@grnsft/if", "version": "0.5.0", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 96e57f8e5..a5e2a8083 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "if-environment", + "name": "@grnsft/if", "description": "Impact Framework", "version": "0.5.0", "author": { From 6f99d7fa1f8df04718baf74b6c1b4071b3ab412c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 13:58:04 +0400 Subject: [PATCH 506/863] test(util): add eslint comment --- src/__tests__/if-merge/util/helpers.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index f69ddd27c..db52a2a84 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -15,6 +15,7 @@ jest.mock('../../../common/lib/load', () => ({ jest.mock('../../../if-run/builtins/export-yaml', () => ({ ExportYaml: jest.fn().mockImplementation(() => ({ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore execute: (tree, context, outputPath) => { const expectedContext = { From a828eb35730b33b56df362971cec02ff9180f84f Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 1 Aug 2024 14:02:48 +0400 Subject: [PATCH 507/863] feat(util): imporve `mergeManifests` helper function --- src/if-merge/util/helpers.ts | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/if-merge/util/helpers.ts b/src/if-merge/util/helpers.ts index 61fb3d59d..362791a6f 100644 --- a/src/if-merge/util/helpers.ts +++ b/src/if-merge/util/helpers.ts @@ -11,8 +11,8 @@ import {IFMergeArgs} from '../types/process-args'; /** * Merges the given manifests in the one file. */ -export const mergeManifests = async (commandArgs: IFMergeArgs) => { - const {manifests: commandManifests, name, description} = commandArgs; +export const mergeManifests = async (mergeArgs: IFMergeArgs) => { + const {manifests: commandManifests, name, description} = mergeArgs; let manifests = commandManifests; let manifestPath = process.env.CURRENT_DIR || process.cwd(); @@ -20,13 +20,22 @@ export const mergeManifests = async (commandArgs: IFMergeArgs) => { manifests = await getYamlFiles(commandManifests[0]); manifestPath = commandManifests[0]; } - const context = { name: name || 'if-merge', description: description || 'merged manifest', tags: null, initialize: {plugins: {}}, }; + const tree = await mergeManifestsData(manifests, context); + const outputPath = getOutputPath(name, manifestPath); + + await saveMergedManifest(tree, context, outputPath); +}; + +/** + * Merges manifests data. + */ +const mergeManifestsData = async (manifests: string[], context: Context) => { const tree: any = {children: {}}; for await (const manifest of manifests) { @@ -45,12 +54,17 @@ export const mergeManifests = async (commandArgs: IFMergeArgs) => { }; }); } - const manifestName = name - ? `${name.replace(' ', '-')}.yaml` - : 'merged-manifest.yaml'; - const outputPath = path.join(manifestPath, manifestName); - await saveMergedManifest(tree, context, outputPath); + return tree; +}; + +/** + * Gets output path. + */ +const getOutputPath = (name: string | undefined, manifestPath: string) => { + const manifestName = `${(name || 'merged-manifest').replace(' ', '-')}.yaml`; + + return path.join(manifestPath, manifestName); }; /** From 55f6b835cbb1125d35d43e2b9228ee0b983e18af Mon Sep 17 00:00:00 2001 From: Manushak Keramyan Date: Thu, 1 Aug 2024 14:05:05 +0400 Subject: [PATCH 508/863] Update src/if-run/builtins/time-converter/README.md Co-authored-by: Narek Hovhannisyan Signed-off-by: Manushak Keramyan --- src/if-run/builtins/time-converter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/time-converter/README.md b/src/if-run/builtins/time-converter/README.md index 4fb7d8725..b6c945c20 100644 --- a/src/if-run/builtins/time-converter/README.md +++ b/src/if-run/builtins/time-converter/README.md @@ -1,6 +1,6 @@ # Time Converter -`time-coversion` is a generic plugin for converting energy values from a specifed time unit to a new given time unit. +`time-conversion` is a generic plugin for converting time values from a specified time unit to a new given time unit. You provide the energy value, the time unit associated with this energy, and a new time unit to which you want to convert it. From 62e20babffa894cde662f198b8de59656fcee080 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:37:52 +0400 Subject: [PATCH 509/863] feat(manifests): convert to coefficient samples to phased exec --- .../coefficient/failure-invalid-config-input-param.yml | 3 ++- .../builtins/coefficient/failure-output-param-is-null.yaml | 3 ++- manifests/examples/builtins/coefficient/success.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml index 938c126aa..5d497b948 100644 --- a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml +++ b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml @@ -14,7 +14,8 @@ tree: children: child: pipeline: - - coefficient + compute: + - coefficient config: sum: inputs: diff --git a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml index c02f42cf9..1ef932df0 100644 --- a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml @@ -14,7 +14,8 @@ tree: children: child: pipeline: - - coefficient + compute: + - coefficient config: sum: inputs: diff --git a/manifests/examples/builtins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml index bd7d2cc94..69dd764eb 100644 --- a/manifests/examples/builtins/coefficient/success.yml +++ b/manifests/examples/builtins/coefficient/success.yml @@ -14,7 +14,8 @@ tree: children: child: pipeline: - - coefficient + compute: + - coefficient config: sum: inputs: From cf920fa9424a4289be179d2a695c2e42fd569407 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:39:04 +0400 Subject: [PATCH 510/863] feat(manifests): convert to cloud metadata samples to phased exec --- .../cloud-metadata/failure-invalid-instance-type.yaml | 3 ++- .../csv-lookup/cloud-metadata/failure-invalid-vendor.yaml | 3 ++- .../csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml | 3 ++- .../examples/builtins/csv-lookup/cloud-metadata/success.yml | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index befa110a6..21f9769b4 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 1cd9b609a..c9fbb8296 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index a01156154..62de6150d 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml index 52bda60b6..84e10112b 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred From 0b39b2e381d2f040601ebabc4d74fe595b5a7d79 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:39:43 +0400 Subject: [PATCH 511/863] feat(manifests): convert to region metadata samples to phased exec --- .../csv-lookup/region-metadata/failure-missing-column.yml | 3 ++- .../csv-lookup/region-metadata/failure-missing-output.yml | 3 ++- .../builtins/csv-lookup/region-metadata/success-renaming.yml | 3 ++- .../examples/builtins/csv-lookup/region-metadata/success.yml | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml index 68d3bc917..5b4e9583b 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index 64354be35..71417932d 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml index c30e11f9c..4c2767a3a 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml index 64354be35..71417932d 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 623a09b729547b7a6a626a6f174391b68a57b833 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:43:59 +0400 Subject: [PATCH 512/863] feat(manifests): convert tdp finder samples to phased exec --- .../csv-lookup/tdp-finder/failure-missing-input-param.yml | 3 ++- .../tdp-finder/failure-unsupported-physical-processor.yml | 3 ++- manifests/examples/builtins/csv-lookup/tdp-finder/success.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml index 52d2b660c..991bdbb8b 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -15,7 +15,8 @@ tree: children: child: pipeline: - - tdp-finder + compute: + - tdp-finder config: inputs: - timestamp: 2023-07-06T00:00 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml index f86767455..3d433d6b2 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -15,7 +15,8 @@ tree: children: child: pipeline: - - tdp-finder + compute: + - tdp-finder config: inputs: - timestamp: 2023-07-06T00:00 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml index b1953f5ca..a04288e0c 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -15,7 +15,8 @@ tree: children: child: pipeline: - - tdp-finder + compute: + - tdp-finder config: inputs: - timestamp: 2023-07-06T00:00 From bbfb0a9632189d56a3ade9711bcd7221d71f601d Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:45:31 +0400 Subject: [PATCH 513/863] feat(manifests): convert divide samples to phased exec --- .../builtins/divide/failure-denominator-equal-zero.yml | 5 +++-- .../builtins/divide/failure-invalid-config-denominator.yml | 5 +++-- .../examples/builtins/divide/failure-missing-numerator.yml | 5 +++-- manifests/examples/builtins/divide/success.yml | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index d26272a82..96d627aee 100644 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -23,8 +23,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide + compute: + - cloud-metadata + - divide config: divide: defaults: diff --git a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 01347d943..fef8a1a7c 100644 --- a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -23,8 +23,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide + compute: + - cloud-metadata + - divide config: divide: defaults: diff --git a/manifests/examples/builtins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml index eda63d49d..5645f0ecf 100644 --- a/manifests/examples/builtins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -23,8 +23,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide + compute: + - cloud-metadata + - divide config: divide: defaults: diff --git a/manifests/examples/builtins/divide/success.yml b/manifests/examples/builtins/divide/success.yml index 02222a6f4..407622985 100644 --- a/manifests/examples/builtins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -23,8 +23,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide + compute: + - cloud-metadata + - divide config: divide: defaults: From f76459c846bdc2d29deae805c0688dcd541dc30d Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:46:36 +0400 Subject: [PATCH 514/863] feat(manifests): drop node config from divide sample --- manifests/examples/builtins/divide/success.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/manifests/examples/builtins/divide/success.yml b/manifests/examples/builtins/divide/success.yml index 407622985..32b247a87 100644 --- a/manifests/examples/builtins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -26,8 +26,6 @@ tree: compute: - cloud-metadata - divide - config: - divide: defaults: cloud/vendor: aws cloud/instance-type: m5n.large From 2a4cab3536ed939bdb71f121e9712e840c6dd86e Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:48:02 +0400 Subject: [PATCH 515/863] feat(manifests): convert exponent samples to phased exec --- manifests/examples/builtins/exponent/success.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/exponent/success.yml b/manifests/examples/builtins/exponent/success.yml index fe54f30a2..163dd1460 100644 --- a/manifests/examples/builtins/exponent/success.yml +++ b/manifests/examples/builtins/exponent/success.yml @@ -14,9 +14,8 @@ tree: children: child: pipeline: - - exponent - config: - exponent: + compute: + - exponent inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From c7d2b8b58072ee671040f2994cb1b6ac436b2ca4 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:53:05 +0400 Subject: [PATCH 516/863] feat(manifests): convert groupby samples to phased exec --- .../builtins/groupby/failure-invalid-config-group.yml | 11 +++-------- .../groupby/failure-missing-cloud-instance-type.yml | 9 +++------ manifests/examples/builtins/groupby/success.yml | 9 +++------ 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml index eca1dd8a9..f35e624b3 100644 --- a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml +++ b/manifests/examples/builtins/groupby/failure-invalid-config-group.yml @@ -1,18 +1,13 @@ name: groupby description: failure when `config->group-by->group` is not an array initialize: - plugins: - group-by: - path: "builtin" - method: GroupBy + plugins: {} tree: children: my-app: pipeline: - - group-by - config: - group-by: - group: cloud/region + regroup: + cloud/region inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml index 34f31266d..adf03ba8f 100644 --- a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml +++ b/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml @@ -9,12 +9,9 @@ tree: children: my-app: pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/examples/builtins/groupby/success.yml b/manifests/examples/builtins/groupby/success.yml index f3f4161f6..1f1f7d634 100644 --- a/manifests/examples/builtins/groupby/success.yml +++ b/manifests/examples/builtins/groupby/success.yml @@ -9,12 +9,9 @@ tree: children: my-app: pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type inputs: - timestamp: 2023-07-06T00:00 duration: 300 From 3af0dcfc9ca43fc04b235df8fcd8e67bec5bf474 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 16:58:43 +0400 Subject: [PATCH 517/863] feat(manifests): move regroup to features --- .../regroup}/failure-invalid-config-group.yml | 2 +- .../regroup}/failure-missing-cloud-instance-type.yml | 2 +- .../examples/{builtins/groupby => features/regroup}/success.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename manifests/examples/{builtins/groupby => features/regroup}/failure-invalid-config-group.yml (98%) rename manifests/examples/{builtins/groupby => features/regroup}/failure-missing-cloud-instance-type.yml (98%) rename manifests/examples/{builtins/groupby => features/regroup}/success.yml (98%) diff --git a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml b/manifests/examples/features/regroup/failure-invalid-config-group.yml similarity index 98% rename from manifests/examples/builtins/groupby/failure-invalid-config-group.yml rename to manifests/examples/features/regroup/failure-invalid-config-group.yml index f35e624b3..5d331ba05 100644 --- a/manifests/examples/builtins/groupby/failure-invalid-config-group.yml +++ b/manifests/examples/features/regroup/failure-invalid-config-group.yml @@ -1,4 +1,4 @@ -name: groupby +name: regroup description: failure when `config->group-by->group` is not an array initialize: plugins: {} diff --git a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml similarity index 98% rename from manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml rename to manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml index adf03ba8f..0b02593fd 100644 --- a/manifests/examples/builtins/groupby/failure-missing-cloud-instance-type.yml +++ b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml @@ -1,4 +1,4 @@ -name: groupby +name: regroup description: initialize: plugins: diff --git a/manifests/examples/builtins/groupby/success.yml b/manifests/examples/features/regroup/success.yml similarity index 98% rename from manifests/examples/builtins/groupby/success.yml rename to manifests/examples/features/regroup/success.yml index 1f1f7d634..4677e8edb 100644 --- a/manifests/examples/builtins/groupby/success.yml +++ b/manifests/examples/features/regroup/success.yml @@ -1,4 +1,4 @@ -name: groupby +name: regroup description: successful path initialize: plugins: From 91b11d2869f62407d828d45fcfb7d7f2ac244a73 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:07:52 +0400 Subject: [PATCH 518/863] feat(manifests): convert interpolation samples to phased exec --- manifests/examples/builtins/interpolation/interpolation.yml | 4 ++-- manifests/examples/builtins/interpolation/success.yml | 3 ++- .../mock-observations/failure-invalid-config-cpu-range.yml | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/manifests/examples/builtins/interpolation/interpolation.yml b/manifests/examples/builtins/interpolation/interpolation.yml index 35d750e48..394946467 100644 --- a/manifests/examples/builtins/interpolation/interpolation.yml +++ b/manifests/examples/builtins/interpolation/interpolation.yml @@ -12,12 +12,12 @@ initialize: y: [0.12, 0.32, 0.75, 1.02] input-parameter: "cpu/utilization" output-parameter: "result" - tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/interpolation/success.yml b/manifests/examples/builtins/interpolation/success.yml index cce024727..394946467 100644 --- a/manifests/examples/builtins/interpolation/success.yml +++ b/manifests/examples/builtins/interpolation/success.yml @@ -16,7 +16,8 @@ tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml index fc74d71a6..472f797fd 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml @@ -29,5 +29,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: From dbe94cba159203fb333b2335b240ff0b392b9ccf Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:15:46 +0400 Subject: [PATCH 519/863] feat(manifests): convert mock observation samples to phased exec --- .../failure-invalid-memory-utilization-range.yml | 3 ++- .../mock-observations/failure-missing-timestamp-from-param.yml | 3 ++- manifests/examples/builtins/mock-observations/success.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml index 0184d280a..85e3f566b 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml @@ -29,5 +29,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: diff --git a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml index 72cd6c347..58545dcec 100644 --- a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml +++ b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml @@ -29,5 +29,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: diff --git a/manifests/examples/builtins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml index 7767a68bc..5ca2d1942 100644 --- a/manifests/examples/builtins/mock-observations/success.yml +++ b/manifests/examples/builtins/mock-observations/success.yml @@ -29,5 +29,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: From d72228cb01194f4c8a9bb820352070349e3cb1b8 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:49:23 +0400 Subject: [PATCH 520/863] feat(manifests): convert multiply samples to phased exec --- .../builtins/multiply/failure-input-parameter-is-missing.yml | 5 ++--- .../builtins/multiply/success-with-multiple-inputs.yml | 5 ++--- manifests/examples/builtins/multiply/success.yml | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml index d71f9f096..988a33fc2 100644 --- a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml +++ b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml index 0a70ba5b3..e6e138723 100644 --- a/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml +++ b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/multiply/success.yml b/manifests/examples/builtins/multiply/success.yml index 88b7bbf71..c5d53e046 100644 --- a/manifests/examples/builtins/multiply/success.yml +++ b/manifests/examples/builtins/multiply/success.yml @@ -14,9 +14,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 8585f555993d5e0fbad5e5e327147d85719f3a02 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:51:20 +0400 Subject: [PATCH 521/863] feat(manifests): convert regex samples to phased exec --- .../examples/builtins/regex/failure-missing-input-param.yml | 5 ++--- .../builtins/regex/failure-not-matching-with-regex.yml | 5 ++--- manifests/examples/builtins/regex/success.yml | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/manifests/examples/builtins/regex/failure-missing-input-param.yml b/manifests/examples/builtins/regex/failure-missing-input-param.yml index f6732c632..84adc0cb2 100644 --- a/manifests/examples/builtins/regex/failure-missing-input-param.yml +++ b/manifests/examples/builtins/regex/failure-missing-input-param.yml @@ -14,9 +14,8 @@ tree: children: child: pipeline: - - regex - config: - regex: + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml index d8818265a..8341d08e6 100644 --- a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml +++ b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml @@ -14,9 +14,8 @@ tree: children: child: pipeline: - - regex - config: - regex: + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/regex/success.yml b/manifests/examples/builtins/regex/success.yml index 8e97d4c43..425dd9e67 100644 --- a/manifests/examples/builtins/regex/success.yml +++ b/manifests/examples/builtins/regex/success.yml @@ -14,9 +14,8 @@ tree: children: child: pipeline: - - regex - config: - regex: + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 5581dd16d1c390a01bb93141aa8e3bc589d47a22 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:52:44 +0400 Subject: [PATCH 522/863] feat(manifests): convert sci samples to phased exec --- .../examples/builtins/sci/failure-invalid-config-value.yml | 3 ++- .../examples/builtins/sci/failure-missing-input-param.yml | 3 ++- manifests/examples/builtins/sci/success.yml | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/manifests/examples/builtins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml index 798e1debd..5882111dd 100644 --- a/manifests/examples/builtins/sci/failure-invalid-config-value.yml +++ b/manifests/examples/builtins/sci/failure-invalid-config-value.yml @@ -13,7 +13,8 @@ tree: children: child: pipeline: - - sci + compute: + - sci config: sci: functional-unit: 999 # factor to convert per time to per f.unit diff --git a/manifests/examples/builtins/sci/failure-missing-input-param.yml b/manifests/examples/builtins/sci/failure-missing-input-param.yml index d30f21550..0a7677261 100644 --- a/manifests/examples/builtins/sci/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sci/failure-missing-input-param.yml @@ -14,7 +14,8 @@ tree: children: child: pipeline: - - sci + compute: + - sci inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/sci/success.yml b/manifests/examples/builtins/sci/success.yml index 95979fd28..85dd19db2 100644 --- a/manifests/examples/builtins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -13,8 +13,8 @@ tree: children: child: pipeline: - - sci - config: + compute: + - sci inputs: - timestamp: 2023-07-06T00:00 duration: 3600 From fc7fe2ffd4b4e7eff5985eb00c4994241035d19e Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:54:24 +0400 Subject: [PATCH 523/863] feat(manifests): convert sci embodied samples to phased exec --- .../sci-embodied/failure-invalid-default-emission-value.yml | 3 ++- .../sci-embodied/failure-missing-expected-lifespan.yml | 3 ++- manifests/examples/builtins/sci-embodied/success.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml index 6ccd41a6e..503300f84 100644 --- a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml +++ b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml @@ -10,7 +10,8 @@ tree: children: child: pipeline: - - sci-embodied # duration & config -> embodied + compute: + - sci-embodied # duration & config -> embodied defaults: device/emissions-embodied: "fail" # gCO2eq time-reserved: 3600 # 1hr in seconds diff --git a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml index 26edf154c..8fd3e5784 100644 --- a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml +++ b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml @@ -10,7 +10,8 @@ tree: children: child: pipeline: - - sci-embodied # duration & config -> embodied + compute: + - sci-embodied # duration & config -> embodied defaults: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds diff --git a/manifests/examples/builtins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml index 219e76845..991569404 100644 --- a/manifests/examples/builtins/sci-embodied/success.yml +++ b/manifests/examples/builtins/sci-embodied/success.yml @@ -10,7 +10,8 @@ tree: children: child: pipeline: - - sci-embodied # duration & config -> embodied + compute: + - sci-embodied # duration & config -> embodied defaults: device/emissions-embodied: 1533.120 # gCO2eq time-reserved: 3600 # 1hr in seconds From 1ee49b7d4684e89b086a6a30b0fa4d379373f049 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:55:50 +0400 Subject: [PATCH 524/863] feat(manifests): convert shell embodied samples to phased exec --- manifests/examples/builtins/shell/failure-invalid-command.yml | 3 ++- manifests/examples/builtins/shell/success.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/manifests/examples/builtins/shell/failure-invalid-command.yml b/manifests/examples/builtins/shell/failure-invalid-command.yml index 2944bc3ea..e67aff103 100644 --- a/manifests/examples/builtins/shell/failure-invalid-command.yml +++ b/manifests/examples/builtins/shell/failure-invalid-command.yml @@ -12,7 +12,8 @@ tree: children: child: pipeline: - - shell + compute: + - shell inputs: - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 diff --git a/manifests/examples/builtins/shell/success.yml b/manifests/examples/builtins/shell/success.yml index b44ca2892..a26af274d 100644 --- a/manifests/examples/builtins/shell/success.yml +++ b/manifests/examples/builtins/shell/success.yml @@ -12,7 +12,8 @@ tree: children: child: pipeline: - - shell + compute: + - shell inputs: - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 From 779c0dd96c6b88cb1a9632012f448d3c54bfa4b6 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:58:12 +0400 Subject: [PATCH 525/863] feat(manifests): convert sum samples to phased exec --- .../examples/builtins/sum/failure-missing-input-param.yml | 5 ++--- .../examples/builtins/sum/failure-missing-output-param.yml | 5 ++--- manifests/examples/builtins/sum/success.yml | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/manifests/examples/builtins/sum/failure-missing-input-param.yml b/manifests/examples/builtins/sum/failure-missing-input-param.yml index 65004b679..1e963b694 100644 --- a/manifests/examples/builtins/sum/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-input-param.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - sum - config: - sum: + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/sum/failure-missing-output-param.yml b/manifests/examples/builtins/sum/failure-missing-output-param.yml index b3c21ac3e..0248bf449 100644 --- a/manifests/examples/builtins/sum/failure-missing-output-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-output-param.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - sum - config: - sum: + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/sum/success.yml b/manifests/examples/builtins/sum/success.yml index 4f5f7452b..366ae5580 100644 --- a/manifests/examples/builtins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - sum - config: - sum: + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 4d73983d7e4975c5c1def67e00bd317bf87e5890 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 17:59:22 +0400 Subject: [PATCH 526/863] feat(manifests): convert subtract samples to phased exec --- manifests/examples/builtins/subtract/success.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/manifests/examples/builtins/subtract/success.yml b/manifests/examples/builtins/subtract/success.yml index b29d89fd0..745ceb067 100644 --- a/manifests/examples/builtins/subtract/success.yml +++ b/manifests/examples/builtins/subtract/success.yml @@ -13,9 +13,8 @@ tree: children: child: pipeline: - - subtract - config: - subtract: + compute: + - subtract inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From a2efb709c94759f34bcfd866011d1420186cf900 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 1 Aug 2024 18:30:41 +0400 Subject: [PATCH 527/863] fix(util): make time sync non nullable --- src/common/util/validations.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 1907ed82f..3b69b1a37 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -58,8 +58,7 @@ export const manifestSchema = z.object({ interval: z.number().gt(0), 'allow-padding': z.boolean(), }) - .optional() - .nullable(), + .optional(), initialize: z.object({ plugins: z.record( z.string(), From e9bb9ab7cee066f7b0943824615fd662809a7e6b Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 18:32:39 +0400 Subject: [PATCH 528/863] feat(manifests): convert time sync samples to phased exec --- .../failure-config-start-later-end.yml | 20 ++++++------------- .../failure-missing-global-config.yml | 20 ++++++------------- .../time-sync/success.yml | 1 - 3 files changed, 12 insertions(+), 29 deletions(-) rename manifests/examples/{builtins => features}/time-sync/failure-config-start-later-end.yml (64%) rename manifests/examples/{builtins => features}/time-sync/failure-missing-global-config.yml (61%) rename manifests/examples/{builtins => features}/time-sync/success.yml (97%) diff --git a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml b/manifests/examples/features/time-sync/failure-config-start-later-end.yml similarity index 64% rename from manifests/examples/builtins/time-sync/failure-config-start-later-end.yml rename to manifests/examples/features/time-sync/failure-config-start-later-end.yml index e6bc3a230..b2132db37 100644 --- a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml +++ b/manifests/examples/features/time-sync/failure-config-start-later-end.yml @@ -1,24 +1,16 @@ name: time-sync description: failure with `global-config.start-time` being later than `global-config.end-time` tags: +'time-sync': + start-time: '2023-12-12T00:01:00.000Z' + end-time: '2023-12-12T00:00:00.000Z' + interval: 5 + allow-padding: true initialize: - output: - - yaml - plugins: - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - start-time: '2023-12-12T00:01:00.000Z' - end-time: '2023-12-12T00:00:00.000Z' - interval: 5 - allow-padding: true + plugins: {} tree: children: child: - pipeline: - - time-sync - config: inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 diff --git a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml b/manifests/examples/features/time-sync/failure-missing-global-config.yml similarity index 61% rename from manifests/examples/builtins/time-sync/failure-missing-global-config.yml rename to manifests/examples/features/time-sync/failure-missing-global-config.yml index 7b8e110fb..948aa0bb5 100644 --- a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml +++ b/manifests/examples/features/time-sync/failure-missing-global-config.yml @@ -1,24 +1,16 @@ name: time-sync description: missing global config tags: +'time-sync': + # start-time: '2023-12-12T00:00:00.000Z' + # end-time: '2023-12-12T00:01:00.000Z' + # interval: 5 + # allow-padding: true initialize: - output: - - yaml - plugins: - 'time-sync': - method: TimeSync - path: "builtin" - global-config: - # start-time: '2023-12-12T00:00:00.000Z' - # end-time: '2023-12-12T00:01:00.000Z' - # interval: 5 - # allow-padding: true + plugins: {} tree: children: child: - pipeline: - - time-sync - config: inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 3 diff --git a/manifests/examples/builtins/time-sync/success.yml b/manifests/examples/features/time-sync/success.yml similarity index 97% rename from manifests/examples/builtins/time-sync/success.yml rename to manifests/examples/features/time-sync/success.yml index 90b80580f..27a903c50 100644 --- a/manifests/examples/builtins/time-sync/success.yml +++ b/manifests/examples/features/time-sync/success.yml @@ -11,7 +11,6 @@ initialize: tree: children: child: - config: inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 From 81355e726aad38d83be2601f0979b234a1d8f4ed Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Thu, 1 Aug 2024 18:39:55 +0400 Subject: [PATCH 529/863] feat(manifests): convert pipeline samples to phased exec --- manifests/examples/pipelines/generics.yml | 18 +++--- .../examples/pipelines/instance-metadata.yml | 5 +- .../examples/pipelines/pipeline-teads-sci.yml | 22 +++---- .../pipelines/pipeline-with-aggregate.yml | 62 +++++++++---------- manifests/examples/pipelines/sci.yml | 24 +++---- manifests/examples/pipelines/teads-curve.yml | 13 ++-- manifests/examples/pipelines/zeros.yml | 31 +++++----- 7 files changed, 87 insertions(+), 88 deletions(-) diff --git a/manifests/examples/pipelines/generics.yml b/manifests/examples/pipelines/generics.yml index 4fd3fa018..f9a19a6b3 100644 --- a/manifests/examples/pipelines/generics.yml +++ b/manifests/examples/pipelines/generics.yml @@ -62,15 +62,15 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - coefficient - - multiply - config: + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - coefficient + - multiply defaults: cpu/thermal-design-power: 100 vcpus-allocated: 1 diff --git a/manifests/examples/pipelines/instance-metadata.yml b/manifests/examples/pipelines/instance-metadata.yml index d79dedb8c..0a64e9ac3 100644 --- a/manifests/examples/pipelines/instance-metadata.yml +++ b/manifests/examples/pipelines/instance-metadata.yml @@ -23,8 +23,9 @@ tree: children: child: pipeline: - - cloud-instance-metadata - - extract-processor-name + compute: + - cloud-instance-metadata + - extract-processor-name inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/pipelines/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml index c07b093bd..d80d0e89e 100644 --- a/manifests/examples/pipelines/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -79,17 +79,17 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - sci - config: + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index f83760e0b..dd4dffa1c 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -184,22 +184,21 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -235,22 +234,21 @@ tree: requests: 30 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 diff --git a/manifests/examples/pipelines/sci.yml b/manifests/examples/pipelines/sci.yml index 927f4eaf5..949d9e7df 100644 --- a/manifests/examples/pipelines/sci.yml +++ b/manifests/examples/pipelines/sci.yml @@ -79,18 +79,18 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sum-energy-components - - embodied-carbon - - operational-carbon - - sum-carbon - - sci - config: + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sum-energy-components + - embodied-carbon + - operational-carbon + - sum-carbon + - sci defaults: cpu/thermal-design-power: 100 vcpus-total: 8 diff --git a/manifests/examples/pipelines/teads-curve.yml b/manifests/examples/pipelines/teads-curve.yml index 924384c20..1679a0976 100644 --- a/manifests/examples/pipelines/teads-curve.yml +++ b/manifests/examples/pipelines/teads-curve.yml @@ -49,12 +49,13 @@ tree: children: child: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio defaults: thermal-design-power: 100 vcpus-total: 8 diff --git a/manifests/examples/pipelines/zeros.yml b/manifests/examples/pipelines/zeros.yml index da5541789..f76a2c79f 100644 --- a/manifests/examples/pipelines/zeros.yml +++ b/manifests/examples/pipelines/zeros.yml @@ -106,22 +106,21 @@ tree: children: child-1: pipeline: - - sum-zero-and-one - - sum-zero-and-zero - - subtract-one-and-zero - - subtract-zero-and-zero - - subtract-zero-and-one - - coefficient-one-times-zero - - coefficient-zero-times-one - - coefficient-zero-times-zero - - multiply-one-times-zero - - multiply-zero-times-one - - exponent-one-to-zero - - exponent-zero-to-one - - exponent-zero-to-zero - - sci - config: - defaults: + compute: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 From 6e6bb63f53e91a2d3a538ee6ccaaff697dd0f6b7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 1 Aug 2024 23:26:11 +0400 Subject: [PATCH 530/863] feat(util): add parameter metadata to time sync --- src/common/util/validations.ts | 58 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 3b69b1a37..f1c8812ab 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -24,6 +24,36 @@ export const atLeastOneDefined = ( export const allDefined = (obj: Record) => Object.values(obj).every(v => v !== undefined); +/** + * Schema for parameter metadata. + */ +const parameterMetadataSchema = z + .object({ + inputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': z.string(), + }) + ) + .optional() + .nullable(), + outputs: z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': z.string(), + }) + ) + .optional() + .nullable(), + }) + .optional(); + /** * Validation schema for manifests. */ @@ -57,6 +87,7 @@ export const manifestSchema = z.object({ 'end-time': z.string(), interval: z.number().gt(0), 'allow-padding': z.boolean(), + 'parameter-metadata': parameterMetadataSchema, }) .optional(), initialize: z.object({ @@ -67,32 +98,7 @@ export const manifestSchema = z.object({ path: z.string(), method: z.string(), 'global-config': z.record(z.string(), z.any()).optional(), - 'parameter-metadata': z - .object({ - inputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - outputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - }) - .optional(), + 'parameter-metadata': parameterMetadataSchema, }) .optional() ), From 08ed51849d013daf6ba77b59921030eab322e829 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 1 Aug 2024 23:26:52 +0400 Subject: [PATCH 531/863] feat(lib): add parameter metadata initialize/time sync --- src/if-run/lib/initialize.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index afa93a2da..9b7ee812e 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -123,6 +123,7 @@ export const initialize = async ( path: 'lib/time-sync', method: 'TimeSync', 'global-config': context['time-sync'], + 'parameter-metadata': context['time-sync']['parameter-metadata'], }; } From f6f1e2f82456016b92fe1268abb7e7bfcc37561b Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 15:07:30 +0400 Subject: [PATCH 532/863] feat(src): move store aggregation before initializing plugin --- src/if-run/index.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 293fef905..cd9e714d4 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -41,6 +41,11 @@ const impactEngine = async () => { try { const {tree, ...context} = validateManifest(envManifest); + + if (context.aggregation) { + storeAggregationMetrics({metrics: context.aggregation?.metrics}); + } + const pluginStorage = await initialize(context); const computedTree = await compute(tree, { context, @@ -55,10 +60,6 @@ const impactEngine = async () => { delete context.initialize.plugins['time-sync']; } - if (context.aggregation) { - storeAggregationMetrics({metrics: context.aggregation?.metrics}); - } - const aggregatedTree = aggregate(computedTree, context.aggregation); envManifest.explainer && (context.explain = explain()); From c2dc2e1f2b07a701edaeff7f5f9868d7bb8911da Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 15:09:21 +0400 Subject: [PATCH 533/863] feat(lib): store aggregation from plugins --- src/if-run/lib/initialize.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 9b7ee812e..1c677df87 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -11,6 +11,7 @@ import {CONFIG, STRINGS} from '../config'; import {PluginInterface} from '../types/interface'; import {Context, PluginOptions} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; +import {storeAggregationMetrics} from './aggregate'; const { PluginInitializationError, @@ -129,6 +130,14 @@ export const initialize = async ( for await (const pluginName of Object.keys(plugins)) { const plugin = await initPlugin(plugins[pluginName]); + const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; + + Object.keys(parameters).forEach(key => { + storeAggregationMetrics({ + metrics: {[key]: {method: parameters[key]['aggregation-method']}}, + }); + }); + storage.set(pluginName, plugin); } From cf115eddda65cb9c3a157bf03cf7ae4c2984b267 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 15:10:40 +0400 Subject: [PATCH 534/863] fix(builtins): add missing `aggregation-method` into sci-embodied --- src/if-run/builtins/sci-embodied/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 35e012b72..e8b69cd2b 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -35,6 +35,7 @@ export const SciEmbodied = ( 'resources-total': { description: 'total resources available', unit: 'count', + 'aggregation-method': 'none', }, 'vcpus-allocated': { description: 'number of vcpus allocated to particular resource', From 067c2676d005fe4543667938251683112bd1135a Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 15:13:12 +0400 Subject: [PATCH 535/863] feat(types): removed `GroupByPlugin` type --- src/if-run/types/interface.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-run/types/interface.ts b/src/if-run/types/interface.ts index 7b6c19b33..3884305a2 100644 --- a/src/if-run/types/interface.ts +++ b/src/if-run/types/interface.ts @@ -1,6 +1,6 @@ -import {ExecutePlugin, GroupByPlugin} from '@grnsft/if-core/types'; +import {ExecutePlugin} from '@grnsft/if-core/types'; -export type PluginInterface = ExecutePlugin | GroupByPlugin; +export type PluginInterface = ExecutePlugin; -export const isExecute = (plugin: PluginInterface): plugin is ExecutePlugin => +export const isExecute = (plugin: ExecutePlugin): plugin is ExecutePlugin => (plugin as ExecutePlugin).metadata.kind === 'execute'; From 8717017aaeba18ac8667d7408bf32688ef382a69 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:34:17 +0400 Subject: [PATCH 536/863] revert(builtins): bring time sync back --- src/if-run/{lib => builtins}/time-sync.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/if-run/{lib => builtins}/time-sync.ts (100%) diff --git a/src/if-run/lib/time-sync.ts b/src/if-run/builtins/time-sync.ts similarity index 100% rename from src/if-run/lib/time-sync.ts rename to src/if-run/builtins/time-sync.ts From 201237e39661fe6a568ebfa3619808849b1faf2b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:36:16 +0400 Subject: [PATCH 537/863] revert(lib): changes on initialize for time sync --- src/if-run/lib/initialize.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 1c677df87..f047be117 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -28,7 +28,6 @@ const { LOADING_PLUGIN_FROM_PATH, INITIALIZING_PLUGIN, INITIALIZING_PLUGINS, - INITIALIZING_TIME_SYNC, } = STRINGS; /** @@ -61,8 +60,6 @@ const handModule = (method: string, pluginPath: string) => { if (pluginPath === 'builtin') { pluginPath = path.normalize(`${__dirname}/../builtins`); - } else if (pluginPath === 'lib/time-sync') { - pluginPath = path.normalize(`${__dirname}/../${pluginPath}`); } else { if (pluginPath?.startsWith(GITHUB_PATH)) { const parts = pluginPath.split('/'); @@ -115,19 +112,6 @@ export const initialize = async ( const {plugins} = context.initialize; const storage = pluginStorage(); - /** - * If `time-sync` is requested, then add it to plugins. - */ - if (context['time-sync']) { - console.debug(INITIALIZING_TIME_SYNC); - plugins['time-sync'] = { - path: 'lib/time-sync', - method: 'TimeSync', - 'global-config': context['time-sync'], - 'parameter-metadata': context['time-sync']['parameter-metadata'], - }; - } - for await (const pluginName of Object.keys(plugins)) { const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; From 990ea8c861d4880f0542607a5cc9be296cec991b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:36:45 +0400 Subject: [PATCH 538/863] revert(lib): changes on compute for time sync --- src/if-run/lib/compute.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 7840a80bd..41a153448 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -122,16 +122,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { }); } - /** - * Adds `time-sync` as the first plugin of compute phase if requested. - */ - if (params.timeSync) { - pipelineCopy.compute = [ - 'time-sync', - ...((pipelineCopy && pipelineCopy.compute) || []), - ]; - } - /** * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. */ From 43f3a16d905ab07524449a17ac4c387f812c3544 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:37:20 +0400 Subject: [PATCH 539/863] revert(config): drop time sync init string --- src/if-run/config/strings.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 59354912b..24835f8ed 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -47,7 +47,6 @@ Note that for the '--output' option you also need to define the output type in y CHECKING_AGGREGATION_METHOD: (unitName: string) => `Checking aggregation method for ${unitName}`, INITIALIZING_PLUGINS: 'Initializing plugins', - INITIALIZING_TIME_SYNC: 'Initializing time synchronization', INITIALIZING_PLUGIN: (pluginName: string) => `Initializing ${pluginName}`, LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => `Loading ${pluginName} from ${path}`, From 66206dee78db7dc66aab302e2cce69b1c8cbd156 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:37:43 +0400 Subject: [PATCH 540/863] revert(builtins): re-export time sync --- src/if-run/builtins/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts index 49b30c882..36a414c95 100644 --- a/src/if-run/builtins/index.ts +++ b/src/if-run/builtins/index.ts @@ -12,3 +12,4 @@ export {CSVLookup} from './csv-lookup'; export {Shell} from './shell'; export {Regex} from './regex'; export {Copy} from './copy-param'; +export {TimeSync} from './time-sync'; From 414b70186b606c4d29b325e2026d429c25f61bc4 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 15:38:18 +0400 Subject: [PATCH 541/863] test(lib): revert time sync changes --- .../{lib => builtins}/time-sync.test.ts | 2 +- src/__tests__/if-run/lib/compute.test.ts | 55 ------------------- src/__tests__/if-run/lib/initialize.test.ts | 41 -------------- 3 files changed, 1 insertion(+), 97 deletions(-) rename src/__tests__/if-run/{lib => builtins}/time-sync.test.ts (99%) diff --git a/src/__tests__/if-run/lib/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts similarity index 99% rename from src/__tests__/if-run/lib/time-sync.test.ts rename to src/__tests__/if-run/builtins/time-sync.test.ts index 2d5a9c983..314ed06d4 100644 --- a/src/__tests__/if-run/lib/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -4,7 +4,7 @@ import {Settings, DateTime} from 'luxon'; import {AggregationParams} from '../../../common/types/manifest'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; -import {TimeSync} from '../../../if-run/lib/time-sync'; +import {TimeSync} from '../../../if-run/builtins/time-sync'; import {STRINGS} from '../../../if-run/config'; diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index 1549f22f8..912793381 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -296,59 +296,4 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.inputs).toEqual(expectedResult); }); - - it('computes simple tree with time sync plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: {observe: ['mock-observe-time-sync']}, - }, - }, - }; - const timeSync = { - 'start-time': '2023-12-12T00:00:00.000Z', - 'end-time': '2023-12-12T00:02:00.000Z', - interval: 5, - 'allow-padding': true, - }; - - const response = await compute(tree, {...paramsExecute, timeSync}); - const expectedInputs = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 60, - 'cpu/utilization': 30, - }, - { - timestamp: '2023-12-12T00:01:00.000Z', - duration: 60, - 'cpu/utilization': 40, - }, - ]; - const expectedOutput = [ - { - timestamp: '2023-12-12T00:00:00.000Z', - duration: 30, - 'cpu/utilization': 30, - }, - { - timestamp: '2023-12-12T00:00:30.000Z', - duration: 30, - 'cpu/utilization': 30, - }, - { - timestamp: '2023-12-12T00:01:00.000Z', - duration: 30, - 'cpu/utilization': 40, - }, - { - timestamp: '2023-12-12T00:01:30.000Z', - duration: 30, - 'cpu/utilization': 40, - }, - ]; - - expect(response.children.mockChild.inputs).toEqual(expectedInputs); - expect(response.children.mockChild.outputs).toEqual(expectedOutput); - }); }); diff --git a/src/__tests__/if-run/lib/initialize.test.ts b/src/__tests__/if-run/lib/initialize.test.ts index 0eccda08b..a1eda8924 100644 --- a/src/__tests__/if-run/lib/initialize.test.ts +++ b/src/__tests__/if-run/lib/initialize.test.ts @@ -158,47 +158,6 @@ describe('lib/initalize: ', () => { expect(module).toHaveProperty('metadata'); }); - it('checks if time sync plugin is initalized.', async () => { - const context = { - initialize: { - plugins: { - 'time-sync': { - path: 'lib/time-sync', - method: 'TimeSync', - 'global-config': {}, - }, - }, - }, - }; - // @ts-ignore - const storage = await initialize(context); - - const pluginName = Object.keys(context.initialize.plugins)[0]; - const module = storage.get(pluginName); - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - }); - - it('initalizes time sync based on context.', async () => { - const context = { - initialize: { - plugins: {}, - }, - 'time-sync': { - 'start-time': '2024-09-04', - 'end-time': '2024-09-05', - 'allow-padding': true, - interval: 5, - }, - }; - // @ts-ignore - const storage = await initialize(context); - const module = storage.get('time-sync'); - - expect(module).toHaveProperty('execute'); - expect(module).toHaveProperty('metadata'); - }); - it('checks if github plugin is initalized.', async () => { const context = { initialize: { From 0647800ccb9503d72da57bff4f28f3f9b1e8c864 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:35:00 +0400 Subject: [PATCH 542/863] feat(manifests): convert pipelines to phased exec --- .../pipelines/cloud-metadata-divide.yaml | 7 +- manifests/outputs/pipelines/generics.yaml | 18 +- .../outputs/pipelines/instance-metadata.yaml | 5 +- .../outputs/pipelines/mock-obs-time-sync.yaml | 102 +- manifests/outputs/pipelines/nesting.yaml | 23 +- .../outputs/pipelines/pipeline-teads-sci.yaml | 29 +- .../pipelines/pipeline-with-aggregate.yaml | 985 --------------- .../pipelines/pipeline-with-mocks.yaml | 1074 ----------------- manifests/outputs/pipelines/sci.yaml | 24 +- manifests/outputs/pipelines/teads-curve.yaml | 13 +- manifests/outputs/pipelines/zeros.yaml | 31 +- 11 files changed, 154 insertions(+), 2157 deletions(-) delete mode 100644 manifests/outputs/pipelines/pipeline-with-aggregate.yaml delete mode 100644 manifests/outputs/pipelines/pipeline-with-mocks.yaml diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml index befa2d0cb..02ff19b86 100644 --- a/manifests/outputs/pipelines/cloud-metadata-divide.yaml +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -69,10 +69,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide - config: - divide: null + compute: + - cloud-metadata + - divide defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/outputs/pipelines/generics.yaml b/manifests/outputs/pipelines/generics.yaml index 4f724754e..613a65f83 100644 --- a/manifests/outputs/pipelines/generics.yaml +++ b/manifests/outputs/pipelines/generics.yaml @@ -122,15 +122,15 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - coefficient - - multiply - config: null + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - coefficient + - multiply defaults: cpu/thermal-design-power: 100 vcpus-allocated: 1 diff --git a/manifests/outputs/pipelines/instance-metadata.yaml b/manifests/outputs/pipelines/instance-metadata.yaml index fbff57e45..369d54c27 100644 --- a/manifests/outputs/pipelines/instance-metadata.yaml +++ b/manifests/outputs/pipelines/instance-metadata.yaml @@ -67,8 +67,9 @@ tree: children: child: pipeline: - - cloud-instance-metadata - - extract-processor-name + compute: + - cloud-instance-metadata + - extract-processor-name inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index d1340e974..04eb881ec 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -169,39 +169,101 @@ tree: children: child-1: pipeline: - - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - time-sync + observe: + - mock-observations + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - time-sync defaults: cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - - timestamp: "2023-12-12T00:00:01.000Z" - duration: 5 - cpu/utilization: 20 + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:01:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:02:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:03:00.000Z' cloud/instance-type: A1 cloud/region: uk-west - - timestamp: "2023-12-12T00:00:06.000Z" - duration: 7 - cpu/utilization: 15 + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:04:00.000Z' cloud/instance-type: A1 cloud/region: uk-west - - timestamp: "2023-12-12T00:00:13.000Z" - duration: 30 + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:05:00.000Z' cloud/instance-type: A1 cloud/region: uk-west - cpu/utilization: 15 + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:06:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:07:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:08:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:09:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: '*' + cpu/thermal-design-power: 100 + vcpus-total: 8 + vcpus-allocated: 1 outputs: - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 13980cecd..83ed612d5 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -243,17 +243,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index fc8e6d0f8..1c2a9d005 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -83,14 +83,6 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon - time-sync: - path: builtin - method: TimeSync - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -139,16 +131,17 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - sci config: null defaults: cpu/thermal-design-power: 100 diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml deleted file mode 100644 index e227dd7ef..000000000 --- a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml +++ /dev/null @@ -1,985 +0,0 @@ -name: pipeline-with-aggregate -description: a full pipeline with the aggregate feature enabled -tags: null -aggregation: - metrics: - carbon: - method: sum - type: both -initialize: - plugins: - interpolate: - path: builtin - method: Interpolation - 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-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: sum - wattage-times-duration: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - wattage-to-energy-kwh: - path: builtin - method: Divide - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: none - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: none - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: sum - sci: - path: builtin - method: Sci - global-config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: sum - sum-carbon: - path: builtin - method: Sum - global-config: - input-parameters: - - carbon-operational - - carbon-embodied - output-parameter: carbon - time-sync: - path: builtin - method: TimeSync - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: none - time-reserved: - unit: seconds - description: time reserved for a component - aggregation-method: avg -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m - manifests/examples/pipelines/pipeline-with-aggregate.yml -o - manifests/outputs/pipelines/pipeline-with-aggregate-1.yaml - environment: - if-version: 0.5.0 - os: macOS - os-version: '14.5' - node-version: 18.14.2 - date-time: 2024-07-31T12:41:31.920Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 10 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 5 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 15 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 30 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: 14 - requests: 14 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 - time-reserved: 2880 - device/expected-lifespan: 170294400 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.3205 - cpu-wattage: 66.19999999999999 - cpu-wattage-times-duration: 203 - cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000007048611111111113 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.0056388888888888895 - carbon: 0.005649016996448503 - sci: 0.000403501214032036 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 13 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 9.571428571428571 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 - time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.30975 - cpu-wattage: 29.907142857142862 - cpu-wattage-times-duration: 192.25 - cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.0005589976298113692 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 12 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 8.428571428571429 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 - time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 18.50952380952381 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.0006170797001436077 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 9 - requests: 3 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 - time-reserved: 2160.2 - device/expected-lifespan: 9460800 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.22425 - cpu-wattage: 3.7375 - cpu-wattage-times-duration: 112.125 - cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 - carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.04532668505834602 - child-2: - pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 150 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 110 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 180 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cpu/utilization: 22.8 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 220 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 - time-reserved: 2880 - device/expected-lifespan: 170294400 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.41509999999999997 - cpu-wattage: 94.57999999999998 - cpu-wattage-times-duration: 258.9 - cpu-energy-raw: 0.00007191666666666668 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000008989583333333334 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007191666666666666 - carbon: 0.007201794774226282 - sci: 0.00003273543079193765 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 29.6 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 92.85714285714285 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 - time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.48819999999999997 - cpu-wattage: 46.98428571428572 - cpu-wattage-times-duration: 308.35 - cpu-energy-raw: 0.00008565277777777778 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000010706597222222223 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.008565277777777778 - carbon: 0.008575405885337391 - sci: 0.00009235052491901808 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 30.6 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 59.14285714285714 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 - time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.49894999999999995 - cpu-wattage: 31.31738095238095 - cpu-wattage-times-duration: 306.2 - cpu-energy-raw: 0.00008505555555555556 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000010631944444444445 - carbon-embodied: 0.000010128107559614407 - carbon-operational: 0.008505555555555556 - carbon: 0.00851568366311517 - sci: 0.0001439849894729618 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 - time-reserved: 2880 - device/expected-lifespan: 15768000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 - carbon-operational: 0.007878472222222222 - carbon: 0.007888600329781836 - sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cpu/utilization: 19.8 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 18 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 - time-reserved: 2160.2 - device/expected-lifespan: 9460800 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.34035000000000004 - cpu-wattage: 5.6725 - cpu-wattage-times-duration: 170.175 - cpu-energy-raw: 0.00004727083333333333 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000005908854166666666 - carbon-embodied: 0.000006076864535768645 - carbon-operational: 0.004727083333333333 - carbon: 0.0047331601978691015 - sci: 0.00026295334432606117 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - carbon-embodied: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.06846904616945712 - outputs: - - carbon: 0.012850811770674785 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.013925811770674782 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.013716783992897007 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.007853820395738204 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - aggregated: - carbon: 0.11379573122780316 diff --git a/manifests/outputs/pipelines/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/pipeline-with-mocks.yaml deleted file mode 100644 index 39d7fef1b..000000000 --- a/manifests/outputs/pipelines/pipeline-with-mocks.yaml +++ /dev/null @@ -1,1074 +0,0 @@ -name: pipeline-with-mocks -description: a full pipeline seeded with data from mock-observations feature -tags: null -aggregation: - metrics: - carbon: - method: sum - type: both -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - global-config: - timestamp-from: 2023-12-12T00:00 - timestamp-to: 2023-12-12T00:10 - duration: 60 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - randint: - cpu/utilization: - min: 1 - max: 99 - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: none - interpolate: - path: builtin - method: Interpolation - 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-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: sum - wattage-times-duration: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - parameter-metadata: - inputs: - cpu-wattage: - unit: kWh - description: Energy used by the CPU - aggregation-method: sum - duration: - unit: seconds - description: Duration of the observation - aggregation-method: sum - outputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: sum - wattage-to-energy-kwh: - path: builtin - method: Divide - global-config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: none - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: none - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - global-config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - parameter-metadata: - inputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: sum - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: none - outputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: sum - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - global-config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: sum - sum-carbon: - path: builtin - method: Sum - global-config: - input-parameters: - - carbon-operational - - carbon-embodied - output-parameter: carbon - parameter-metadata: - inputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: sum - carbon-embodied: - unit: gCO2eq - description: Embodied carbon footprint - aggregation-method: sum - outputs: - carbon: - unit: gCO2eq - description: Total carbon footprint - aggregation-method: sum - sci: - path: builtin - method: Sci - global-config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: sum - outputs: - sci: - unit: none - description: Scientific Carbon Intensity - aggregation-method: none - time-sync: - path: builtin - method: TimeSync - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true - parameter-metadata: - inputs: - time-reserved: - unit: seconds - description: time reserved for a component - aggregation-method: avg - outputs: - synced-time: - unit: none - description: Synced time - aggregation-method: none - group-by: - path: builtin - method: GroupBy - parameter-metadata: - inputs: - group: - unit: none - description: Group by fields - aggregation-method: none - outputs: - grouped-data: - unit: none - description: Grouped data - aggregation-method: none -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m - manifests/examples/pipelines/pipeline-with-mocks.yml -o - manifests/outputs/pipelines/pipeline-with-mocks-update - environment: - if-version: 0.5.0 - os: macOS - os-version: '14.5' - node-version: 18.14.2 - date-time: 2024-07-30T05:35:42.937Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 30 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 40 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 50 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:05.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:10.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:15.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:20.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:25.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:30.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:35.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:40.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:45.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:50.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:55.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: '*' - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:01:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: '*' - requests: 0.5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 25.552 - time-reserved: 3600 - device/expected-lifespan: 1576800 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: 0.0000020256215119228817 - carbon-operational: '*' - carbon: '*' - sci: '*' - aggregated: - carbon: '*' - child-2: - pipeline: - - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 40 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 50 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 60 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 127.75999999999999 - time-reserved: 2880 - device/expected-lifespan: 7884000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - cpu/utilization: '*' - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0.5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 25.552 - time-reserved: 3600 - device/expected-lifespan: 1576800 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - aggregated: - carbon: '*' - outputs: - - carbon: '*' - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - aggregated: - carbon: '*' diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml index 5c5f0d822..c4fa641c2 100644 --- a/manifests/outputs/pipelines/sci.yaml +++ b/manifests/outputs/pipelines/sci.yaml @@ -138,18 +138,18 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sum-energy-components - - embodied-carbon - - operational-carbon - - sum-carbon - - sci - config: null + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sum-energy-components + - embodied-carbon + - operational-carbon + - sum-carbon + - sci defaults: cpu/thermal-design-power: 100 vcpus-total: 8 diff --git a/manifests/outputs/pipelines/teads-curve.yaml b/manifests/outputs/pipelines/teads-curve.yaml index 3f5d2d323..26885e1c7 100644 --- a/manifests/outputs/pipelines/teads-curve.yaml +++ b/manifests/outputs/pipelines/teads-curve.yaml @@ -105,12 +105,13 @@ tree: children: child: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio defaults: thermal-design-power: 100 vcpus-total: 8 diff --git a/manifests/outputs/pipelines/zeros.yaml b/manifests/outputs/pipelines/zeros.yaml index 523728097..3efd3c0fb 100644 --- a/manifests/outputs/pipelines/zeros.yaml +++ b/manifests/outputs/pipelines/zeros.yaml @@ -155,22 +155,21 @@ tree: children: child-1: pipeline: - - sum-zero-and-one - - sum-zero-and-zero - - subtract-one-and-zero - - subtract-zero-and-zero - - subtract-zero-and-one - - coefficient-one-times-zero - - coefficient-zero-times-one - - coefficient-zero-times-zero - - multiply-one-times-zero - - multiply-zero-times-one - - exponent-one-to-zero - - exponent-zero-to-one - - exponent-zero-to-zero - - sci - config: null - defaults: null + compute: + - sum-zero-and-one + - sum-zero-and-zero + - subtract-one-and-zero + - subtract-zero-and-zero + - subtract-zero-and-one + - coefficient-one-times-zero + - coefficient-zero-times-one + - coefficient-zero-times-zero + - multiply-one-times-zero + - multiply-zero-times-one + - exponent-one-to-zero + - exponent-zero-to-one + - exponent-zero-to-zero + - sci inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 From 5fcfe93e7c7331990b99fa8f239af9e00b37992b Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:37:19 +0400 Subject: [PATCH 543/863] feat(manifests): convert features to phased exec --- .../aggregate-failure-invalid-metrics.yaml | 3 +- ...gate-failure-missing-metric-in-inputs.yaml | 3 +- .../features/aggregate-horizontal.yaml | 6 +- .../outputs/features/aggregate-vertical.yaml | 6 +- manifests/outputs/features/aggregate.yaml | 6 +- .../failure-invalid-config-group.yaml | 88 +++++++++++++++++++ .../failure-missing-cloud-instance-type.yaml | 86 ++++++++++++++++++ 7 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 manifests/outputs/features/failure-invalid-config-group.yaml create mode 100644 manifests/outputs/features/failure-missing-cloud-instance-type.yaml diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index 870be308a..11e7f5865 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -70,7 +70,8 @@ tree: children: application: pipeline: - - cloud-metadata + compute: + - cloud-metadata children: uk-west: children: diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 4a3da85ae..0e308d509 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -70,7 +70,8 @@ tree: children: application: pipeline: - - cloud-metadata + compute: + - cloud-metadata children: uk-west: children: diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index f870bb4d2..0fef8d756 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -3,7 +3,7 @@ description: Apply `horizontal` aggregation aggregation: metrics: "cpu/utilization": - method: sum + method: avg type: horizontal initialize: plugins: @@ -36,7 +36,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -67,7 +66,8 @@ tree: children: application: pipeline: - - cloud-metadata + compute: + - cloud-metadata children: uk-west: children: diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 0fd5b170a..dfd604c73 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -3,7 +3,7 @@ description: Apply `vertical` aggregation aggregation: metrics: "cpu/utilization": - method: sum + method: avg type: vertical initialize: plugins: @@ -36,7 +36,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -67,7 +66,8 @@ tree: children: application: pipeline: - - cloud-metadata + compute: + - cloud-metadata children: uk-west: children: diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index 35ab21423..79736b9c0 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -3,7 +3,7 @@ description: Apply both `horizontal` and `vertical` aggregations aggregation: metrics: "cpu/utilization": - method: sum + method: avg type: both initialize: plugins: @@ -36,7 +36,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -67,7 +66,8 @@ tree: children: application: pipeline: - - cloud-metadata + compute: + - cloud-metadata children: uk-west: children: diff --git a/manifests/outputs/features/failure-invalid-config-group.yaml b/manifests/outputs/features/failure-invalid-config-group.yaml new file mode 100644 index 000000000..1ed31b06d --- /dev/null +++ b/manifests/outputs/features/failure-invalid-config-group.yaml @@ -0,0 +1,88 @@ +name: groupby +description: failure when `config->group-by->group` is not an array +initialize: + plugins: {} +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-invalid-config-group.yml -o + manifests/outputs/plugins/groupby/failure-invalid-config-group + environment: + if-version: 0.4.0 + os: macOS + os-version: "13.2" + node-version: 18.14.2 + date-time: 2024-07-02T19:11:23.166Z (UTC) + dependencies: + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: >- + InputValidationError: "groups" parameter is expected array, received string. + Error code: invalid_type. +tree: + children: + my-app: + pipeline: + regroup: + cloud/region + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/features/failure-missing-cloud-instance-type.yaml b/manifests/outputs/features/failure-missing-cloud-instance-type.yaml new file mode 100644 index 000000000..741544461 --- /dev/null +++ b/manifests/outputs/features/failure-missing-cloud-instance-type.yaml @@ -0,0 +1,86 @@ +name: groupby +description: null +initialize: + plugins: {} +execution: + status: fail + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yml -o + manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type + environment: + if-version: 0.4.0 + os: macOS + os-version: "13.2" + node-version: 18.14.2 + date-time: 2024-07-02T19:10:00.820Z (UTC) + dependencies: + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.22.4 + error: "InvalidGroupingError: Invalid group cloud/instance-type." +tree: + children: + my-app: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/region: uk-west + cpu/utilization: 1 From 0b4574a13965993b2c5e2bfd85824329ac68088a Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:39:36 +0400 Subject: [PATCH 544/863] feat(manifests): move time sync back to builtins --- .../failure-config-start-later-end.yml | 22 +++++++++++++------ .../failure-missing-global-config.yml | 22 +++++++++++++------ .../time-sync/success.yml | 22 +++++++++++++------ 3 files changed, 45 insertions(+), 21 deletions(-) rename manifests/examples/{features => builtins}/time-sync/failure-config-start-later-end.yml (61%) rename manifests/examples/{features => builtins}/time-sync/failure-missing-global-config.yml (57%) rename manifests/examples/{features => builtins}/time-sync/success.yml (58%) diff --git a/manifests/examples/features/time-sync/failure-config-start-later-end.yml b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml similarity index 61% rename from manifests/examples/features/time-sync/failure-config-start-later-end.yml rename to manifests/examples/builtins/time-sync/failure-config-start-later-end.yml index b2132db37..ffed32274 100644 --- a/manifests/examples/features/time-sync/failure-config-start-later-end.yml +++ b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml @@ -1,16 +1,24 @@ name: time-sync description: failure with `global-config.start-time` being later than `global-config.end-time` tags: -'time-sync': - start-time: '2023-12-12T00:01:00.000Z' - end-time: '2023-12-12T00:00:00.000Z' - interval: 5 - allow-padding: true initialize: - plugins: {} + output: + - yaml + plugins: + 'time-sync': + method: TimeSync + path: "builtin" + global-config: + start-time: '2023-12-12T00:01:00.000Z' + end-time: '2023-12-12T00:00:00.000Z' + interval: 5 + allow-padding: true tree: children: child: + pipeline: + compute: + - time-sync inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 @@ -23,4 +31,4 @@ tree: energy-cpu: 0.001 - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 - energy-cpu: 0.001 + energy-cpu: 0.001 \ No newline at end of file diff --git a/manifests/examples/features/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml similarity index 57% rename from manifests/examples/features/time-sync/failure-missing-global-config.yml rename to manifests/examples/builtins/time-sync/failure-missing-global-config.yml index 948aa0bb5..c5715a26a 100644 --- a/manifests/examples/features/time-sync/failure-missing-global-config.yml +++ b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml @@ -1,16 +1,24 @@ name: time-sync description: missing global config tags: -'time-sync': - # start-time: '2023-12-12T00:00:00.000Z' - # end-time: '2023-12-12T00:01:00.000Z' - # interval: 5 - # allow-padding: true initialize: - plugins: {} + output: + - yaml + plugins: + 'time-sync': + method: TimeSync + path: "builtin" + global-config: + # start-time: '2023-12-12T00:00:00.000Z' + # end-time: '2023-12-12T00:01:00.000Z' + # interval: 5 + # allow-padding: true tree: children: child: + pipeline: + compute: + - time-sync inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 3 @@ -23,4 +31,4 @@ tree: energy-cpu: 0.001 - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 - energy-cpu: 0.001 + energy-cpu: 0.001 \ No newline at end of file diff --git a/manifests/examples/features/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml similarity index 58% rename from manifests/examples/features/time-sync/success.yml rename to manifests/examples/builtins/time-sync/success.yml index 27a903c50..f32d885a2 100644 --- a/manifests/examples/features/time-sync/success.yml +++ b/manifests/examples/builtins/time-sync/success.yml @@ -1,16 +1,24 @@ name: time-sync description: successful path tags: -'time-sync': - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true initialize: - plugins: {} + output: + - yaml + plugins: + 'time-sync': + method: TimeSync + path: "builtin" + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true tree: children: child: + pipeline: + compute: + - time-sync inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 @@ -23,4 +31,4 @@ tree: energy-cpu: 0.001 - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 - energy-cpu: 0.001 + energy-cpu: 0.001 \ No newline at end of file From faf2ecf9a08af9bb9dc292d053b5cb55aef1842c Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:40:22 +0400 Subject: [PATCH 545/863] feat(manifests): init if diff outputs as a sample --- .../pipeline-with-aggregate.yaml | 985 +++++++++++++++ .../outputs-if-diff/pipeline-with-mocks.yaml | 1074 +++++++++++++++++ 2 files changed, 2059 insertions(+) create mode 100644 manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml create mode 100644 manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml new file mode 100644 index 000000000..e227dd7ef --- /dev/null +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -0,0 +1,985 @@ +name: pipeline-with-aggregate +description: a full pipeline with the aggregate feature enabled +tags: null +aggregation: + metrics: + carbon: + method: sum + type: both +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + 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-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-aggregate.yml -o + manifests/outputs/pipelines/pipeline-with-aggregate-1.yaml + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-31T12:41:31.920Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.16' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 10 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 5 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 15 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 30 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: 14 + requests: 14 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 2880 + device/expected-lifespan: 170294400 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.3205 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000007048611111111113 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.0056388888888888895 + carbon: 0.005649016996448503 + sci: 0.000403501214032036 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 9.571428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2880 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.30975 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006675347222222222 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005340277777777777 + carbon: 0.005350405885337391 + sci: 0.0005589976298113692 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 8.428571428571429 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 759.2594285714285 + time-reserved: 2880 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.0000064887152777777775 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.005190972222222222 + carbon: 0.0052011003297818366 + sci: 0.0006170797001436077 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.005190972222222222 + carbon: 0.005201100329781837 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 + requests: 3 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 153.312 + time-reserved: 2160.2 + device/expected-lifespan: 9460800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.22425 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000003893229166666667 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.0031145833333333334 + carbon: 0.003120660197869102 + sci: 0.0010402200659563674 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.04532668505834602 + child-2: + pipeline: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 150 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 110 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 180 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 22.8 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 220 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 2759.6159999999995 + time-reserved: 2880 + device/expected-lifespan: 170294400 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.41509999999999997 + cpu-wattage: 94.57999999999998 + cpu-wattage-times-duration: 258.9 + cpu-energy-raw: 0.00007191666666666668 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000008989583333333334 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007191666666666666 + carbon: 0.007201794774226282 + sci: 0.00003273543079193765 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 29.6 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 92.85714285714285 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1182.6925714285712 + time-reserved: 2880 + device/expected-lifespan: 72983314.28571428 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.48819999999999997 + cpu-wattage: 46.98428571428572 + cpu-wattage-times-duration: 308.35 + cpu-energy-raw: 0.00008565277777777778 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000010706597222222223 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008565277777777778 + carbon: 0.008575405885337391 + sci: 0.00009235052491901808 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 30.6 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 59.14285714285714 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 759.2594285714285 + time-reserved: 2880 + device/expected-lifespan: 46853485.71428572 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.49894999999999995 + cpu-wattage: 31.31738095238095 + cpu-wattage-times-duration: 306.2 + cpu-energy-raw: 0.00008505555555555556 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000010631944444444445 + carbon-embodied: 0.000010128107559614407 + carbon-operational: 0.008505555555555556 + carbon: 0.00851568366311517 + sci: 0.0001439849894729618 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 255.51999999999998 + time-reserved: 2880 + device/expected-lifespan: 15768000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + carbon-embodied: 0.000010128107559614409 + carbon-operational: 0.007878472222222222 + carbon: 0.007888600329781836 + sci: 0.0002629533443260612 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 19.8 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 18 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 153.312 + time-reserved: 2160.2 + device/expected-lifespan: 9460800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.34035000000000004 + cpu-wattage: 5.6725 + cpu-wattage-times-duration: 170.175 + cpu-energy-raw: 0.00004727083333333333 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000005908854166666666 + carbon-embodied: 0.000006076864535768645 + carbon-operational: 0.004727083333333333 + carbon: 0.0047331601978691015 + sci: 0.00026295334432606117 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 0.8 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 0 + time-reserved: 1 + device/expected-lifespan: 0 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + carbon-embodied: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.06846904616945712 + outputs: + - carbon: 0.012850811770674785 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.013925811770674782 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.013716783992897007 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.013089700659563674 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.007853820395738204 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.11379573122780316 diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml new file mode 100644 index 000000000..39d7fef1b --- /dev/null +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -0,0 +1,1074 @@ +name: pipeline-with-mocks +description: a full pipeline seeded with data from mock-observations feature +tags: null +aggregation: + metrics: + carbon: + method: sum + type: both +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + global-config: + timestamp-from: 2023-12-12T00:00 + timestamp-to: 2023-12-12T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + randint: + cpu/utilization: + min: 1 + max: 99 + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: none + interpolate: + path: builtin + method: Interpolation + 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-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: sum + wattage-times-duration: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + parameter-metadata: + inputs: + cpu-wattage: + unit: kWh + description: Energy used by the CPU + aggregation-method: sum + duration: + unit: seconds + description: Duration of the observation + aggregation-method: sum + outputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + wattage-to-energy-kwh: + path: builtin + method: Divide + global-config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + global-config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + parameter-metadata: + inputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: sum + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: none + outputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + global-config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum + sum-carbon: + path: builtin + method: Sum + global-config: + input-parameters: + - carbon-operational + - carbon-embodied + output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: sum + carbon-embodied: + unit: gCO2eq + description: Embodied carbon footprint + aggregation-method: sum + outputs: + carbon: + unit: gCO2eq + description: Total carbon footprint + aggregation-method: sum + sci: + path: builtin + method: Sci + global-config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: sum + outputs: + sci: + unit: none + description: Scientific Carbon Intensity + aggregation-method: none + time-sync: + path: builtin + method: TimeSync + global-config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + parameter-metadata: + inputs: + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: avg + outputs: + synced-time: + unit: none + description: Synced time + aggregation-method: none + group-by: + path: builtin + method: GroupBy + parameter-metadata: + inputs: + group: + unit: none + description: Group by fields + aggregation-method: none + outputs: + grouped-data: + unit: none + description: Grouped data + aggregation-method: none +execution: + command: >- + /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-mocks.yml -o + manifests/outputs/pipelines/pipeline-with-mocks-update + environment: + if-version: 0.5.0 + os: macOS + os-version: '14.5' + node-version: 18.14.2 + date-time: 2024-07-30T05:35:42.937Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.16' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + - mock-observations + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 30 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 40 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 50 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:05.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:10.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:15.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:20.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:25.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:30.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:35.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:40.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:45.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:50.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:55.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: '*' + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.000010128107559614409 + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:01:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: '*' + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 25.552 + time-reserved: 3600 + device/expected-lifespan: 1576800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: 0.0000020256215119228817 + carbon-operational: '*' + carbon: '*' + sci: '*' + aggregated: + carbon: '*' + child-2: + pipeline: + - mock-observations + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + config: + group-by: + group: + - cloud/region + - cloud/instance-type + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 40 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 50 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 60 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 127.75999999999999 + time-reserved: 2880 + device/expected-lifespan: 7884000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cpu/utilization: '*' + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 25.552 + time-reserved: 3600 + device/expected-lifespan: 1576800 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: '*' + cpu-wattage: '*' + cpu-wattage-times-duration: '*' + cpu-energy-raw: '*' + vcpu-ratio: 8 + cpu-energy-kwh: '*' + carbon-embodied: '*' + carbon-operational: '*' + carbon: '*' + sci: '*' + aggregated: + carbon: '*' + outputs: + - carbon: '*' + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: '*' + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: '*' From 753a3613f3467018e4f82aaf3b8e04eba9437506 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:41:18 +0400 Subject: [PATCH 546/863] feat(manifests): convert bugs to phased exec --- .../bugs/aggregation-error-wrong-metric.yaml | 61 +++++++++---------- .../bugs/input-error-missing-duration.yaml | 4 +- ...observations-failure-duration-is-zero.yaml | 6 +- .../bugs/pipeline-error-naming-mismatch.yaml | 4 +- .../pipeline-error-uninitialized-plugin.yaml | 6 +- .../outputs/bugs/pipeline-ordering-error.yaml | 15 +++-- .../sci-embodied-missing-resources-total.yaml | 3 +- 7 files changed, 47 insertions(+), 52 deletions(-) diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index ebf55ad73..313834f76 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -88,9 +88,6 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - group-by: - path: builtin - method: GroupBy execution: status: fail command: >- @@ -142,21 +139,20 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -192,21 +188,20 @@ tree: requests: 100 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml index 310a7d0ae..1006c1c0c 100644 --- a/manifests/outputs/bugs/input-error-missing-duration.yaml +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -41,7 +41,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -76,7 +75,8 @@ tree: defaults: cpu/thermal-design-power: 100 pipeline: - - interpolate + compute: + - interpolate inputs: - timestamp: 2023-07-06T00:00 cpu/utilization: 20 diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml index 56ed12cee..d137975b5 100644 --- a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -44,7 +44,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -70,10 +69,11 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: "RangeError: Maximum call stack size exceeded" + error: "InputValidationError: \"duration\" parameter is number must be greater than 0. Error code: too_small." tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: null diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml index aaf987300..fef0fa246 100644 --- a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -41,7 +41,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -76,7 +75,8 @@ tree: defaults: cpu/thermal-design-power: 100 pipeline: - - wrong-name + compute: + - wrong-name inputs: - timestamp: 2023-07-06T00:00 duration: 1 diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml index 1fd747ce9..7a0060013 100644 --- a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -41,7 +41,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -76,8 +75,9 @@ tree: defaults: cpu/thermal-design-power: 100 pipeline: - - interpolate - - multiply + compute: + - interpolate + - multiply inputs: - timestamp: 2023-07-06T00:00 duration: 1 diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml index 5a47d8d3f..d1bd27d27 100644 --- a/manifests/outputs/bugs/pipeline-ordering-error.yaml +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -78,7 +78,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -111,13 +110,13 @@ tree: children: child-1: pipeline: - - interpolate - - correct-cpu-energy-for-vcpu-ratio - - calculate-vcpu-ratio - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - config: null + compute: + - interpolate + - correct-cpu-energy-for-vcpu-ratio + - calculate-vcpu-ratio + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml index 5c93301e2..486947ebd 100644 --- a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml +++ b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml @@ -60,7 +60,8 @@ tree: children: child: pipeline: - - sci-embodied + compute: + - sci-embodied defaults: device/emissions-embodied: 1533.12 time-reserved: 3600 From d9c4c94fabedf8065bb0cc205473a51d9e9bd93e Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:41:54 +0400 Subject: [PATCH 547/863] feat(manifests): convert builtins to phased exec --- .../failure-invalid-config-input-param.yaml | 6 +- .../failure-output-param-is-null.yaml | 6 +- .../outputs/builtins/coefficient/success.yaml | 3 - .../failure-invalid-instance-type.yaml | 4 +- .../failure-missing-cloud-vendor.yaml | 4 +- .../csv-lookup/cloud-metadata/success.yaml | 4 +- .../failure-missing-column.yaml | 3 +- .../failure-missing-output.yaml | 4 +- .../region-metadata/success-renaming.yaml | 4 +- .../csv-lookup/region-metadata/success.yaml | 4 +- .../failure-missing-input-param.yaml | 5 +- ...ailure-unsupported-physical-processor.yaml | 4 +- .../csv-lookup/tdp-finder/success.yaml | 4 +- .../failure-invalid-config-denominator.yaml | 6 +- .../divide/failure-missing-numerator.yaml | 4 +- .../success-denominator-equal-zero.yaml | 8 +- .../outputs/builtins/divide/success.yaml | 8 +- .../outputs/builtins/exponent/success.yaml | 6 +- .../groupby/failure-invalid-config-group.yaml | 94 ----- .../failure-missing-cloud-instance-type.yaml | 93 ----- .../builtins/interpolation/interpolation.yaml | 4 +- .../builtins/interpolation/success.yaml | 4 +- .../failure-invalid-config-cpu-range.yaml | 4 +- ...lure-invalid-memory-utilization-range.yaml | 4 +- .../failure-missing-timestamp-from-param.yaml | 4 +- .../builtins/mock-observations/success.yaml | 366 +++++++++++------- .../failure-input-parameter-is-missing.yaml | 6 +- .../success-with-multiple-inputs.yaml | 6 +- .../outputs/builtins/multiply/success.yaml | 6 +- .../regex/failure-missing-input-param.yaml | 6 +- .../failure-not-matching-with-regex.yaml | 74 ---- manifests/outputs/builtins/regex/success.yaml | 9 +- ...ailure-invalid-default-emission-value.yaml | 4 +- .../failure-missing-expected-lifespan.yaml | 4 +- .../builtins/sci-embodied/success.yaml | 4 +- .../sci/failure-invalid-config-value.yaml | 4 +- .../sci/failure-missing-input-param.yaml | 4 +- .../sci/{success.yml.yaml => success.yaml} | 5 +- .../shell/failure-invalid-command.yaml | 4 +- manifests/outputs/builtins/shell/success.yaml | 4 +- .../outputs/builtins/subtract/success.yaml | 6 +- .../sum/failure-missing-input-param.yaml | 6 +- .../sum/failure-missing-output-param.yaml | 6 +- manifests/outputs/builtins/sum/success.yaml | 6 +- .../failure-config-start-later-end.yaml | 4 +- .../outputs/builtins/time-sync/success.yaml | 5 +- 46 files changed, 304 insertions(+), 529 deletions(-) delete mode 100644 manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml delete mode 100644 manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml delete mode 100644 manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml rename manifests/outputs/builtins/sci/{success.yml.yaml => success.yaml} (98%) diff --git a/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml index 78af0bab9..7b6051dce 100644 --- a/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml +++ b/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,9 +61,8 @@ tree: children: child: pipeline: - - coefficient - config: - sum: null + compute: + - coefficient inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml index 91e6d064e..847e984e7 100644 --- a/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,9 +61,8 @@ tree: children: child: pipeline: - - coefficient - config: - sum: null + compute: + - coefficient inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/coefficient/success.yaml b/manifests/outputs/builtins/coefficient/success.yaml index c560d0411..14a235709 100644 --- a/manifests/outputs/builtins/coefficient/success.yaml +++ b/manifests/outputs/builtins/coefficient/success.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,8 +59,6 @@ tree: child: pipeline: - coefficient - config: - sum: null inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index d1a5f2cfb..6945e6012 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -66,8 +66,8 @@ tree: children: child: pipeline: - - cloud-metadata - config: null + compute: + - cloud-metadata inputs: - timestamp: 2023-07-06T00:00 cloud/vendor: aws diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 79a4960a5..333d9e1ce 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -66,8 +66,8 @@ tree: children: child: pipeline: - - cloud-metadata - config: null + compute: + - cloud-metadata inputs: - timestamp: 2023-07-06T00:00 duration: 100 diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml index 098a0d1c6..37fab5816 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml @@ -62,8 +62,8 @@ tree: children: child: pipeline: - - cloud-metadata - config: null + compute: + - cloud-metadata inputs: - timestamp: 2023-07-06T00:00 cloud/vendor: aws diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml index 4db0b6b2f..842080a77 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -66,7 +66,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml index bdaa3b6ad..32ca690d9 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -32,7 +32,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -65,7 +64,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml index e7e04b535..2f6f23dcf 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml @@ -33,7 +33,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -64,7 +63,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml index e8d31f661..f8bd9fdba 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml @@ -31,7 +31,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,7 +61,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml index f842a3756..ce268cd02 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -32,7 +32,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -65,8 +64,8 @@ tree: children: child: pipeline: - - tdp-finder - config: null + compute: + - tdp-finder inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml index 7ccf90ff6..28dc0b1a0 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -65,8 +65,8 @@ tree: children: child: pipeline: - - tdp-finder - config: null + compute: + - tdp-finder inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml index 249d2d3f4..f085664ff 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml @@ -61,8 +61,8 @@ tree: children: child: pipeline: - - tdp-finder - config: null + compute: + - tdp-finder inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml index 8b98a5a27..b1149c505 100644 --- a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml +++ b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,9 +61,8 @@ tree: children: child: pipeline: - - divide - config: - divide: null + compute: + - divide inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml index 41ac4b1ea..6c714bf18 100644 --- a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -61,7 +60,8 @@ tree: children: child: pipeline: - - divide + compute: + - divide config: divide: null defaults: diff --git a/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml index 2384df53b..25033c32c 100644 --- a/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml +++ b/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml @@ -39,7 +39,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -70,10 +69,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide - config: - divide: null + compute: + - cloud-metadata + - divide defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/outputs/builtins/divide/success.yaml b/manifests/outputs/builtins/divide/success.yaml index 3e43a85de..f7bab8b04 100644 --- a/manifests/outputs/builtins/divide/success.yaml +++ b/manifests/outputs/builtins/divide/success.yaml @@ -39,7 +39,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -70,10 +69,9 @@ tree: children: child: pipeline: - - cloud-metadata - - divide - config: - divide: null + compute: + - cloud-metadata + - divide defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/outputs/builtins/exponent/success.yaml b/manifests/outputs/builtins/exponent/success.yaml index 7ad94e5bc..8586b57f6 100644 --- a/manifests/outputs/builtins/exponent/success.yaml +++ b/manifests/outputs/builtins/exponent/success.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -59,9 +58,8 @@ tree: children: child: pipeline: - - exponent - config: - exponent: null + compute: + - exponent inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml b/manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml deleted file mode 100644 index 22506aa2e..000000000 --- a/manifests/outputs/builtins/groupby/failure-invalid-config-group.yaml +++ /dev/null @@ -1,94 +0,0 @@ -name: groupby -description: failure when `config->group-by->group` is not an array -initialize: - plugins: - group-by: - path: builtin - method: GroupBy -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/groupby/failure-invalid-config-group.yml -o - manifests/outputs/plugins/groupby/failure-invalid-config-group - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T19:11:23.166Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - InputValidationError: "group" parameter is expected array, received string. - Error code: invalid_type. -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: cloud/region - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 diff --git a/manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml b/manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml deleted file mode 100644 index e6b2ea8ea..000000000 --- a/manifests/outputs/builtins/groupby/failure-missing-cloud-instance-type.yaml +++ /dev/null @@ -1,93 +0,0 @@ -name: groupby -description: null -initialize: - plugins: - group-by: - path: builtin - method: GroupBy -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type.yml -o - manifests/outputs/plugins/groupby/failure-missing-cloud-instance-type - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T19:10:00.820Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: "InvalidGroupingError: Invalid group cloud/instance-type." -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - cloud/instance-type - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/region: uk-west - cpu/utilization: 1 diff --git a/manifests/outputs/builtins/interpolation/interpolation.yaml b/manifests/outputs/builtins/interpolation/interpolation.yaml index 8eff7b1f1..2569b5eb4 100644 --- a/manifests/outputs/builtins/interpolation/interpolation.yaml +++ b/manifests/outputs/builtins/interpolation/interpolation.yaml @@ -38,7 +38,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -69,7 +68,8 @@ tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/interpolation/success.yaml b/manifests/outputs/builtins/interpolation/success.yaml index cbfc92011..80def13d9 100644 --- a/manifests/outputs/builtins/interpolation/success.yaml +++ b/manifests/outputs/builtins/interpolation/success.yaml @@ -38,7 +38,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -69,7 +68,8 @@ tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml index fda4ddba7..272d9940e 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -47,7 +47,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -80,5 +79,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: null diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml index cfb073fc6..e7c7e6180 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -45,7 +45,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -78,5 +77,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: null diff --git a/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml index 184e86230..86f4afd9e 100644 --- a/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -44,7 +44,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -77,5 +76,6 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: null diff --git a/manifests/outputs/builtins/mock-observations/success.yaml b/manifests/outputs/builtins/mock-observations/success.yaml index e92b933bf..e0be992de 100644 --- a/manifests/outputs/builtins/mock-observations/success.yaml +++ b/manifests/outputs/builtins/mock-observations/success.yaml @@ -27,37 +27,26 @@ initialize: execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/mock-observations/success.yml -o - manifests/outputs/plugins/mock-observations/success + /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + manifests/examples/builtins/mock-observations/success.yml -o + manifests/outputs/builtins/mock-observations/success environment: - if-version: 0.4.0 + if-version: 0.5.0 os: macOS - os-version: "13.2" + os-version: '14.5' node-version: 18.14.2 - date-time: 2024-07-02T19:15:43.108Z (UTC) + date-time: 2024-08-02T15:04:18.262Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.16' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -77,210 +66,293 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: child: pipeline: - - mock-observations - inputs: null - outputs: - - timestamp: "2023-07-06T00:00:00.000Z" - - timestamp: "2023-07-06T00:00:00.000Z" + observe: + - mock-observations + inputs: + - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 81 - memory/utilization: 63 - - timestamp: "2023-07-06T00:01:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" + cpu/utilization: 3 + memory/utilization: 91 + - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 92 - memory/utilization: 63 - - timestamp: "2023-07-06T00:02:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" + cpu/utilization: 82 + memory/utilization: 79 + - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 63 - memory/utilization: 95 - - timestamp: "2023-07-06T00:03:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" + cpu/utilization: 74 + memory/utilization: 18 + - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 37 - memory/utilization: 13 - - timestamp: "2023-07-06T00:04:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" + cpu/utilization: 61 + memory/utilization: 90 + - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 28 - memory/utilization: 50 - - timestamp: "2023-07-06T00:05:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" + cpu/utilization: 67 + memory/utilization: 67 + - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 98 - memory/utilization: 29 - - timestamp: "2023-07-06T00:06:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" + cpu/utilization: 27 + memory/utilization: 63 + - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 10 - memory/utilization: 93 - - timestamp: "2023-07-06T00:07:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" + cpu/utilization: 14 + memory/utilization: 97 + - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 84 - memory/utilization: 37 - - timestamp: "2023-07-06T00:08:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" + cpu/utilization: 6 + memory/utilization: 64 + - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 10 - memory/utilization: 30 - - timestamp: "2023-07-06T00:09:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" + cpu/utilization: 60 + memory/utilization: 87 + - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 50 - memory/utilization: 10 - - timestamp: "2023-07-06T00:00:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:00:00.000Z" + cpu/utilization: 71 + memory/utilization: 12 + - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 97 + cpu/utilization: 27 + memory/utilization: 48 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 30 memory/utilization: 89 - - timestamp: "2023-07-06T00:01:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" + - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 61 - memory/utilization: 83 - - timestamp: "2023-07-06T00:02:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" + cpu/utilization: 33 + memory/utilization: 42 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 29 + memory/utilization: 51 + - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 86 - memory/utilization: 52 - - timestamp: "2023-07-06T00:03:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" + cpu/utilization: 13 + memory/utilization: 77 + - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 17 - memory/utilization: 60 - - timestamp: "2023-07-06T00:04:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" + cpu/utilization: 75 + memory/utilization: 37 + - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 53 - memory/utilization: 84 - - timestamp: "2023-07-06T00:05:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" + cpu/utilization: 90 + memory/utilization: 5 + - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 38 - memory/utilization: 58 - - timestamp: "2023-07-06T00:06:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" + cpu/utilization: 26 + memory/utilization: 4 + - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 4 + cpu/utilization: 16 memory/utilization: 39 - - timestamp: "2023-07-06T00:07:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 26 + memory/utilization: 43 + outputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 3 + memory/utilization: 91 + - timestamp: '2023-07-06T00:01:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 82 + memory/utilization: 79 + - timestamp: '2023-07-06T00:02:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 74 + memory/utilization: 18 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 61 + memory/utilization: 90 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 67 + memory/utilization: 67 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 27 + memory/utilization: 63 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 14 + memory/utilization: 97 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 6 + memory/utilization: 64 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 60 + memory/utilization: 87 + - timestamp: '2023-07-06T00:09:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 71 + memory/utilization: 12 + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 27 + memory/utilization: 48 + - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 89 - memory/utilization: 52 - - timestamp: "2023-07-06T00:08:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" + cpu/utilization: 30 + memory/utilization: 89 + - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 38 - memory/utilization: 16 - - timestamp: "2023-07-06T00:09:00.000Z" - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" + cpu/utilization: 33 + memory/utilization: 42 + - timestamp: '2023-07-06T00:03:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 29 + memory/utilization: 51 + - timestamp: '2023-07-06T00:04:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 13 + memory/utilization: 77 + - timestamp: '2023-07-06T00:05:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 75 + memory/utilization: 37 + - timestamp: '2023-07-06T00:06:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 90 + memory/utilization: 5 + - timestamp: '2023-07-06T00:07:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 26 + memory/utilization: 4 + - timestamp: '2023-07-06T00:08:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 16 + memory/utilization: 39 + - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" + cpu/utilization: 26 + memory/utilization: 43 diff --git a/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml index 8c12556fb..80738e80c 100644 --- a/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml +++ b/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml @@ -30,7 +30,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -63,9 +62,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: null + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml index b9b2470c3..359e25a06 100644 --- a/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml +++ b/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,9 +59,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: null + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/multiply/success.yaml b/manifests/outputs/builtins/multiply/success.yaml index c2925f183..1f93a9140 100644 --- a/manifests/outputs/builtins/multiply/success.yaml +++ b/manifests/outputs/builtins/multiply/success.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,9 +59,8 @@ tree: children: child: pipeline: - - multiply - config: - sum: null + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/regex/failure-missing-input-param.yaml b/manifests/outputs/builtins/regex/failure-missing-input-param.yaml index 5ea08772c..cd578218f 100644 --- a/manifests/outputs/builtins/regex/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/regex/failure-missing-input-param.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,9 +61,8 @@ tree: children: child: pipeline: - - regex - config: - regex: null + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml deleted file mode 100644 index d07bc0484..000000000 --- a/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: regex -description: physical processor doesn't match the regex expression -tags: null -initialize: - plugins: - regex: - method: Regex - path: builtin - global-config: - parameter: physical-processor - match: ^ - output: cpu/name -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/regex/failure-not-matching-with-regex.yml -o - manifests/outputs/plugins/regex/failure-not-matching-with-regex - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T20:24:39.241Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - RegexMismatchError: `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` does - not match the /^/ regex expression -tree: - children: - child: - pipeline: - - regex - config: - regex: null - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - physical-processor: >- - 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 diff --git a/manifests/outputs/builtins/regex/success.yaml b/manifests/outputs/builtins/regex/success.yaml index 745e3cf71..22988eead 100644 --- a/manifests/outputs/builtins/regex/success.yaml +++ b/manifests/outputs/builtins/regex/success.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -59,9 +58,8 @@ tree: children: child: pipeline: - - regex - config: - regex: null + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 @@ -75,5 +73,4 @@ tree: 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 cpu/name: >- - Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® - E5-2673 v4 2.3 GHz, + Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz, Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz diff --git a/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml index b1784d516..f6af79041 100644 --- a/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml +++ b/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -61,7 +60,8 @@ tree: children: child: pipeline: - - sci-embodied + compute: + - sci-embodied defaults: device/emissions-embodied: fail time-reserved: 3600 diff --git a/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml index 5959d2b21..43f22163e 100644 --- a/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml +++ b/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml @@ -25,7 +25,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -58,7 +57,8 @@ tree: children: child: pipeline: - - sci-embodied + compute: + - sci-embodied defaults: device/emissions-embodied: 1533.12 time-reserved: 3600 diff --git a/manifests/outputs/builtins/sci-embodied/success.yaml b/manifests/outputs/builtins/sci-embodied/success.yaml index f7c4e8dc0..e91ab9212 100644 --- a/manifests/outputs/builtins/sci-embodied/success.yaml +++ b/manifests/outputs/builtins/sci-embodied/success.yaml @@ -24,7 +24,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -55,7 +54,8 @@ tree: children: child: pipeline: - - sci-embodied + compute: + - sci-embodied defaults: device/emissions-embodied: 1533.12 time-reserved: 3600 diff --git a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml index 463a855da..384fe14b1 100644 --- a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml +++ b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml @@ -26,7 +26,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -57,7 +56,8 @@ tree: children: child: pipeline: - - sci + compute: + - sci config: sci: functional-unit: 999 diff --git a/manifests/outputs/builtins/sci/failure-missing-input-param.yaml b/manifests/outputs/builtins/sci/failure-missing-input-param.yaml index 0aed8267c..b0fbce2f8 100644 --- a/manifests/outputs/builtins/sci/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/sci/failure-missing-input-param.yaml @@ -28,7 +28,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -61,7 +60,8 @@ tree: children: child: pipeline: - - sci + compute: + - sci inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/sci/success.yml.yaml b/manifests/outputs/builtins/sci/success.yaml similarity index 98% rename from manifests/outputs/builtins/sci/success.yml.yaml rename to manifests/outputs/builtins/sci/success.yaml index e08d7e27e..9f36fc9bd 100644 --- a/manifests/outputs/builtins/sci/success.yml.yaml +++ b/manifests/outputs/builtins/sci/success.yaml @@ -26,7 +26,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -57,8 +56,8 @@ tree: children: child: pipeline: - - sci - config: null + compute: + - sci inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/shell/failure-invalid-command.yaml b/manifests/outputs/builtins/shell/failure-invalid-command.yaml index ad11fecad..97d8bb6af 100644 --- a/manifests/outputs/builtins/shell/failure-invalid-command.yaml +++ b/manifests/outputs/builtins/shell/failure-invalid-command.yaml @@ -27,7 +27,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,7 +59,8 @@ tree: children: child: pipeline: - - shell + compute: + - shell inputs: - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 diff --git a/manifests/outputs/builtins/shell/success.yaml b/manifests/outputs/builtins/shell/success.yaml index 0c53a27aa..b85cbfb95 100644 --- a/manifests/outputs/builtins/shell/success.yaml +++ b/manifests/outputs/builtins/shell/success.yaml @@ -26,7 +26,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -57,7 +56,8 @@ tree: children: child: pipeline: - - shell + compute: + - shell inputs: - timestamp: "2023-11-02T10:35:31.820Z" duration: 3600 diff --git a/manifests/outputs/builtins/subtract/success.yaml b/manifests/outputs/builtins/subtract/success.yaml index ebf2197c5..5eb0a7bd3 100644 --- a/manifests/outputs/builtins/subtract/success.yaml +++ b/manifests/outputs/builtins/subtract/success.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,9 +59,8 @@ tree: children: child: pipeline: - - subtract - config: - subtract: null + compute: + - subtract inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/sum/failure-missing-input-param.yaml b/manifests/outputs/builtins/sum/failure-missing-input-param.yaml index 85838df45..e2aaf8158 100644 --- a/manifests/outputs/builtins/sum/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/sum/failure-missing-input-param.yaml @@ -30,7 +30,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -63,9 +62,8 @@ tree: children: child: pipeline: - - sum - config: - sum: null + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/sum/failure-missing-output-param.yaml b/manifests/outputs/builtins/sum/failure-missing-output-param.yaml index 624bf3fdf..d7a4d9302 100644 --- a/manifests/outputs/builtins/sum/failure-missing-output-param.yaml +++ b/manifests/outputs/builtins/sum/failure-missing-output-param.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -62,9 +61,8 @@ tree: children: child: pipeline: - - sum - config: - sum: null + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/sum/success.yaml b/manifests/outputs/builtins/sum/success.yaml index 77b0a3f2d..6b5b4d973 100644 --- a/manifests/outputs/builtins/sum/success.yaml +++ b/manifests/outputs/builtins/sum/success.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,9 +59,8 @@ tree: children: child: pipeline: - - sum - config: - sum: null + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml index 81a430414..bb5ae79fb 100644 --- a/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml +++ b/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml @@ -62,8 +62,8 @@ tree: children: child: pipeline: - - time-sync - config: null + compute: + - time-sync inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 diff --git a/manifests/outputs/builtins/time-sync/success.yaml b/manifests/outputs/builtins/time-sync/success.yaml index 17e1a71d1..3ed64a0e3 100644 --- a/manifests/outputs/builtins/time-sync/success.yaml +++ b/manifests/outputs/builtins/time-sync/success.yaml @@ -29,7 +29,6 @@ execution: - "@commitlint/cli@18.6.0" - "@commitlint/config-conventional@18.6.0" - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - "@types/jest@29.5.8" - "@types/js-yaml@4.0.9" @@ -60,8 +59,8 @@ tree: children: child: pipeline: - - time-sync - config: null + compute: + - time-sync inputs: - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 From 7cbcf86be6a9004f17785d2d139258c1a8f015af Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Fri, 2 Aug 2024 19:48:56 +0400 Subject: [PATCH 548/863] feat(manifests): convert mockobs success to phased exec --- .../builtins/mock-observations/success.yaml | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/manifests/outputs/builtins/mock-observations/success.yaml b/manifests/outputs/builtins/mock-observations/success.yaml index e0be992de..bcc5ee034 100644 --- a/manifests/outputs/builtins/mock-observations/success.yaml +++ b/manifests/outputs/builtins/mock-observations/success.yaml @@ -80,279 +80,279 @@ tree: cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 3 - memory/utilization: 91 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 82 - memory/utilization: 79 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 74 - memory/utilization: 18 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 61 - memory/utilization: 90 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 67 - memory/utilization: 67 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 27 - memory/utilization: 63 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 14 - memory/utilization: 97 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 6 - memory/utilization: 64 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 60 - memory/utilization: 87 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 71 - memory/utilization: 12 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 27 - memory/utilization: 48 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 30 - memory/utilization: 89 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 33 - memory/utilization: 42 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 29 - memory/utilization: 51 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 13 - memory/utilization: 77 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 75 - memory/utilization: 37 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 90 - memory/utilization: 5 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 26 - memory/utilization: 4 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 16 - memory/utilization: 39 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 26 - memory/utilization: 43 + cpu/utilization: '*' + memory/utilization: '*' outputs: - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 3 - memory/utilization: 91 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 82 - memory/utilization: 79 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 74 - memory/utilization: 18 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 61 - memory/utilization: 90 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 67 - memory/utilization: 67 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 27 - memory/utilization: 63 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 14 - memory/utilization: 97 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 6 - memory/utilization: 64 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 60 - memory/utilization: 87 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: 71 - memory/utilization: 12 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 27 - memory/utilization: 48 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 30 - memory/utilization: 89 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 33 - memory/utilization: 42 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 29 - memory/utilization: 51 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 13 - memory/utilization: 77 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 75 - memory/utilization: 37 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 90 - memory/utilization: 5 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 26 - memory/utilization: 4 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 16 - memory/utilization: 39 + cpu/utilization: '*' + memory/utilization: '*' - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: 26 - memory/utilization: 43 + cpu/utilization: '*' + memory/utilization: '*' From bec7f95a8af8af26e07fe21bdeed371c58784754 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 20:12:47 +0400 Subject: [PATCH 549/863] Update manifests/examples/builtins/time-sync/success.yml Signed-off-by: Narek Hovhannisyan --- manifests/examples/builtins/time-sync/success.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/examples/builtins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml index f32d885a2..8aac13740 100644 --- a/manifests/examples/builtins/time-sync/success.yml +++ b/manifests/examples/builtins/time-sync/success.yml @@ -31,4 +31,4 @@ tree: energy-cpu: 0.001 - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 - energy-cpu: 0.001 \ No newline at end of file + energy-cpu: 0.001 From 78b6bab9385f4e3d19f001ea3569dba41ea21825 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 20:14:24 +0400 Subject: [PATCH 550/863] revert(types): drop type sync types from compute --- src/if-run/types/compute.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index da31b2635..6777bf553 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -13,13 +13,6 @@ export type PhasedPipeline = { compute?: string[]; }; -type TimeSyncConfig = { - 'start-time': string; - 'end-time': string; - interval: number; - 'allow-padding': boolean; -}; - export type ComputeParams = { pluginStorage: PluginStorageInterface; context: Context; @@ -29,7 +22,6 @@ export type ComputeParams = { observe?: Boolean; regroup?: Boolean; compute?: Boolean; - timeSync?: TimeSyncConfig | undefined | null; }; export type Node = { From ed0eb9c10b5b4c7e10f36aa467692c83521d80c3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 20:15:53 +0400 Subject: [PATCH 551/863] revert(util): drop type sync from manifest validation --- src/common/util/validations.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index f1c8812ab..95d9efeff 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -81,15 +81,6 @@ export const manifestSchema = z.object({ }) .optional() .nullable(), - 'time-sync': z - .object({ - 'start-time': z.string(), - 'end-time': z.string(), - interval: z.number().gt(0), - 'allow-padding': z.boolean(), - 'parameter-metadata': parameterMetadataSchema, - }) - .optional(), initialize: z.object({ plugins: z.record( z.string(), From ca7ccc6b9549969be9a2906549eb13b6194d6210 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 2 Aug 2024 20:17:24 +0400 Subject: [PATCH 552/863] revert(src): drop time sync check from if-run index --- src/if-run/index.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index cd9e714d4..9b8d86f6c 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -53,13 +53,8 @@ const impactEngine = async () => { observe, regroup, compute: computeFlag, - timeSync: context['time-sync'], }); - if (context['time-sync']) { - delete context.initialize.plugins['time-sync']; - } - const aggregatedTree = aggregate(computedTree, context.aggregation); envManifest.explainer && (context.explain = explain()); From f5f8b9bfaa6741dc4f2ce093599b804737805c03 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 20:42:11 +0400 Subject: [PATCH 553/863] 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 554/863] 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 555/863] 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 556/863] 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 557/863] 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 7f1f1bc64b5a32302475f5275b35fa08cc9ea170 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 2 Aug 2024 21:04:34 +0400 Subject: [PATCH 558/863] fix(util): fix package name --- src/if-env/util/npm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-env/util/npm.ts b/src/if-env/util/npm.ts index f029bcdf2..f02898399 100644 --- a/src/if-env/util/npm.ts +++ b/src/if-env/util/npm.ts @@ -122,7 +122,7 @@ export const updatePackageJsonProperties = async ( const parsedPackageJsonContent = JSON.parse(packageJsonContent); const properties = { - name: 'if-environment', + name: packageJson.name || 'if-environment', description: packageJson.description, author: packageJson.author, bugs: packageJson.bugs, From bf2e26cc246383881bd1718b99808c60d560529a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 14:19:57 +0400 Subject: [PATCH 559/863] fix(util): add missed new line at the end of package.json --- src/if-env/util/npm.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-env/util/npm.ts b/src/if-env/util/npm.ts index f02898399..c5f272255 100644 --- a/src/if-env/util/npm.ts +++ b/src/if-env/util/npm.ts @@ -79,6 +79,7 @@ export const updatePackageJsonDependencies = async ( packageJsonPath, JSON.stringify(parsedPackageJson, null, 2) ); + await fs.appendFile(packageJsonPath, '\n'); }; /** From 5dc924c0e975f1aeaff4d0abb5fcbe28d884591a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 14:24:02 +0400 Subject: [PATCH 560/863] test(mocks): add mock function for fs.appendFunction --- src/__mocks__/fs/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 0f37a4291..323c7693a 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -81,6 +81,11 @@ export const writeFile = async (pathToFile: string, content: string) => { } } else if (pathToFile.includes('package.json-npm')) { const updatedPath = pathToFile.replace('-npm', ''); + // try { + // await fsAsync.appendFile(updatedPath, '\n'); + // } catch (error) { + // console.log('---error', error); + // } const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); expect(content).toBe(fileContent); @@ -108,6 +113,9 @@ export const writeFile = async (pathToFile: string, content: string) => { } }; +export const appendFile = (file: string, appendContent: string) => + `${file}${appendContent}`; + export const stat = async (filePath: string) => { if (filePath === 'true') { return true; From 7d106933d680560b4de5a749b9c7a008521a2d63 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 16:40:20 +0400 Subject: [PATCH 561/863] test(mocks): remove unneseccary comment --- src/__mocks__/fs/index.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 323c7693a..1f0ce0b7f 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -81,11 +81,6 @@ export const writeFile = async (pathToFile: string, content: string) => { } } else if (pathToFile.includes('package.json-npm')) { const updatedPath = pathToFile.replace('-npm', ''); - // try { - // await fsAsync.appendFile(updatedPath, '\n'); - // } catch (error) { - // console.log('---error', error); - // } const fileContent = await fsAsync.readFile(updatedPath, 'utf8'); expect(content).toBe(fileContent); From 96d5aeb229c8528a37b1bf1055c082982fb42176 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:03:21 +0400 Subject: [PATCH 562/863] docs(builtins): update plugins readme file to be relevant to phased execution --- src/if-run/builtins/README.md | 224 ++---------------- src/if-run/builtins/coefficient/README.md | 5 +- src/if-run/builtins/copy-param/README.md | 3 +- src/if-run/builtins/csv-lookup/README.md | 3 +- src/if-run/builtins/divide/README.md | 5 +- src/if-run/builtins/exponent/README.md | 5 +- src/if-run/builtins/interpolation/README.md | 6 +- .../builtins/mock-observations/README.md | 5 +- src/if-run/builtins/multiply/README.md | 5 +- src/if-run/builtins/regex/README.md | 5 +- src/if-run/builtins/sci-embodied/README.md | 3 +- src/if-run/builtins/sci/README.md | 4 +- src/if-run/builtins/shell/README.md | 6 +- src/if-run/builtins/subtract/README.md | 5 +- src/if-run/builtins/sum/README.md | 5 +- 15 files changed, 50 insertions(+), 239 deletions(-) diff --git a/src/if-run/builtins/README.md b/src/if-run/builtins/README.md index ccacf83e5..e05110887 100644 --- a/src/if-run/builtins/README.md +++ b/src/if-run/builtins/README.md @@ -4,7 +4,6 @@ There are three built-in features of IF: - time-sync - CSV exporter -- groupby On this page, you can find the documentation for each of these three builtins. @@ -242,11 +241,12 @@ tree: children: child: # an advanced grouping node pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync + compute: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync config: teads-curve: cpu/thermal-design-power: 65 @@ -307,20 +307,19 @@ The CSV above is generated from the following yaml. The `carbon` metric is extra ```yaml tree: pipeline: - - mock-observations - - group-by - - cloud-metadata - - time-sync - - watttime - - teads-curve - - operational-carbon + observe: + - mock-observations + regroup: + - cloud/region + - name + compute: + - cloud-metadata + - time-sync + - watttime + - teads-curve + - operational-carbon defaults: grid/carbon-intensity: 500 - config: - group-by: - group: - - cloud/region - - name children: westus3: children: @@ -634,192 +633,3 @@ tree: ### CSV and aggregation The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the _rows_ of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the _columns_ in the CSV representation (this is not _exactly_ accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). - -## Groupby - -Groupby is an IF plugin that reorganizes a tree according to keys provided by the user. This allows users to regroup their observations according to various properties of their application. For example, the following manifest file contains a flat array of observations. This is how you might expect data to arrive from an importer plugin, maybe one that hits a metrics API for a cloud service. - -```yaml -name: if-demo -description: demo pipeline -graph: - children: - my-app: - pipeline: - - group-by - - teads-curve - config: - group-by: - - cloud/region - - instance-type - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-west - cpu-util: 1 -``` - -However, each observation contains an `instance-type` field that varies between observations. There are two instance types being represented in this array of observations. This means there are duplicate entries for the same timestamp in this array. This is the problem that `group-by` solves. You provide `instance-type` as a key to the `group-by` plugin and it extracts the data belonging to the different instances and separates them into independent arrays. The above example would be restructured so that instance types `A1` and `B1` have their own data, as follows: - -```yaml -graph: - children: - my-app: - pipeline: - # - group-by - - teads-curve - config: - group-by: - groups: - - cloud/region - - instance-type - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 1 -``` - -### Using `group-by` - -To use `group-by`, you have to initialize it as a plugin and invoke it in a pipeline. - -The initialization looks as follows: - -```yaml -initialize: -plugins: -group-by: - path: 'builtin' - method: GroupBy -``` - -You then have to provide config defining which keys to group by in each component. This is done at the component level (i.e. not global config). -For example: - -```yaml -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - group: - - cloud/region - - instance-type -``` - -In the example above, the plugin would regroup the input data for the specific component by `cloud/region` and by `instance-type`. - -Assuming the values `A1` and `B1` are found for `instance-type` and the values `uk-east` and `uk-west` are found for `cloud/region`, the result of `group-by` would look similar to the following: - -```yaml -tree: - children: - my-app: - pipeline: - - group-by - config: - group-by: - groups: - - cloud/region - - instance-type - children: - uk-west: - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: A1 - cloud/region: uk-west - cpu-util: 12 - uk-east: - children: - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - instance-type: B1 - cloud/region: uk-east - cpu-util: 1 -``` - -This reorganized data can then be used to feed the rest of a computation pipeline. diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index a80f4e4fb..903a15496 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -97,9 +97,8 @@ tree: children: child: pipeline: - - coefficient - config: - coefficient: + compute: + - coefficient inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 309a83fde..2f76c98da 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -107,7 +107,8 @@ tree: children: child-1: pipeline: - - copy-param + compute: + - copy-param inputs: - timestamp: '2023-12-12T00:00:00.000Z' original: 'hello' diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 31bdcdb17..434e234a2 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -135,7 +135,8 @@ tree: children: child: pipeline: - - cloud-metadata + compute: + - cloud-metadata inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index b17925dff..abb534c8f 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -89,9 +89,8 @@ tree: children: child: pipeline: - - divide - config: - divide: + compute: + - divide inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index b4f4d7d17..fddb55ffa 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -90,9 +90,8 @@ tree: children: child: pipeline: - - exponent - config: - exponent: + compute: + - exponent inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index a6d897f32..243b70e70 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -131,7 +131,8 @@ tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 @@ -159,7 +160,8 @@ tree: children: child: pipeline: - - interpolation + compute: + - interpolation inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 91f418ccb..53bd89924 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -62,7 +62,7 @@ const result = await mockObservations.execute([]); ### manifest Example -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 `mock-observation`: +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 `mock-observation`: ```yaml name: mock-observation-demo @@ -96,7 +96,8 @@ tree: children: child: pipeline: - - mock-observations + observe: + - mock-observations inputs: ``` diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 86a65aecb..dc6cde7c7 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -87,9 +87,8 @@ tree: children: child: pipeline: - - multiply - config: - multiply: + compute: + - multiply inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index d9f382274..2c6a4cd88 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -82,9 +82,8 @@ tree: children: child: pipeline: - - regex - config: - regex: + compute: + - regex inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index ed9c1841e..a4c304c6d 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -102,7 +102,8 @@ tree: children: child: pipeline: - - sci-embodied # duration & config -> embodied + compute: + - sci-embodied # duration & config -> embodied defaults: device/emissions-embodied: 1533.120 # gCO2eq device/expected-lifespan: 3 # 3 years in seconds diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index d0b08c9c5..31b15afed 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -82,8 +82,8 @@ tree: children: child: pipeline: - - sci - config: + compute: + - sci inputs: - timestamp: 2023-07-06T00:00 carbon: 5 diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index 5e529f922..d114adb3b 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -91,7 +91,8 @@ tree: children: child: pipeline: - - sampler + compute: + - sampler inputs: - timestamp: 2023-07-06T00:00 duration: 1 # Secs @@ -117,7 +118,8 @@ tree: children: child: pipeline: - - sampler + compute: + - sampler inputs: - timestamp: 2023-07-06T00:00 duration: 1 # Secs diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 89a186ab3..776526c7e 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -87,9 +87,8 @@ tree: children: child: pipeline: - - subtract - config: - subtract: + compute: + - subtract inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 014111c6c..998c54c11 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -97,9 +97,8 @@ tree: children: child: pipeline: - - sum - config: - sum: + compute: + - sum inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 4e27cde0138c7d63cc94f12a0e57472b6b5acd4e Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:12:07 +0400 Subject: [PATCH 563/863] fix(manifests): update some manifests names --- ...-group.yml => failure-invalid-regroup.yml} | 5 +- ...roup.yaml => failure-invalid-regroup.yaml} | 46 +++++++++---------- 2 files changed, 25 insertions(+), 26 deletions(-) rename manifests/examples/features/regroup/{failure-invalid-config-group.yml => failure-invalid-regroup.yml} (91%) rename manifests/outputs/features/{failure-invalid-config-group.yaml => failure-invalid-regroup.yaml} (64%) diff --git a/manifests/examples/features/regroup/failure-invalid-config-group.yml b/manifests/examples/features/regroup/failure-invalid-regroup.yml similarity index 91% rename from manifests/examples/features/regroup/failure-invalid-config-group.yml rename to manifests/examples/features/regroup/failure-invalid-regroup.yml index 5d331ba05..a121d82b5 100644 --- a/manifests/examples/features/regroup/failure-invalid-config-group.yml +++ b/manifests/examples/features/regroup/failure-invalid-regroup.yml @@ -1,13 +1,12 @@ name: regroup -description: failure when `config->group-by->group` is not an array +description: failure when `regroup` is not an array initialize: plugins: {} tree: children: my-app: pipeline: - regroup: - cloud/region + regroup: cloud/region inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/outputs/features/failure-invalid-config-group.yaml b/manifests/outputs/features/failure-invalid-regroup.yaml similarity index 64% rename from manifests/outputs/features/failure-invalid-config-group.yaml rename to manifests/outputs/features/failure-invalid-regroup.yaml index 1ed31b06d..b3f3e722c 100644 --- a/manifests/outputs/features/failure-invalid-config-group.yaml +++ b/manifests/outputs/features/failure-invalid-regroup.yaml @@ -1,31 +1,31 @@ -name: groupby -description: failure when `config->group-by->group` is not an array +name: regroup +description: failure when `regroup` is not an array initialize: plugins: {} execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/groupby/failure-invalid-config-group.yml -o - manifests/outputs/plugins/groupby/failure-invalid-config-group + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/features/regroup/failure-invalid-regroup.yml -o + manifests/outputs/features/failure-invalid-regroup.yaml environment: - if-version: 0.4.0 + if-version: 0.5.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T19:11:23.166Z (UTC) + os-version: 13.6.7 + node-version: 18.20.0 + date-time: 2024-08-05T14:53:00.560Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.16' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -34,6 +34,7 @@ execution: - fixpack@4.0.0 - gts@5.2.0 - husky@8.0.3 + - if-eco-ci-plugin@v0.0.1 extraneous -> file:../../if-eco-ci-plugin - jest@29.7.0 - js-yaml@4.1.0 - lint-staged@15.2.2 @@ -45,7 +46,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- InputValidationError: "groups" parameter is expected array, received string. Error code: invalid_type. @@ -53,8 +54,7 @@ tree: children: my-app: pipeline: - regroup: - cloud/region + regroup: cloud/region inputs: - timestamp: 2023-07-06T00:00 duration: 300 From 83a0778e5b03f97bb74835970646cc1089091821 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:26:16 +0400 Subject: [PATCH 564/863] test(mocks): update mock manifest example --- src/__mocks__/fs/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 0f37a4291..bb13a39b8 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -52,8 +52,9 @@ cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,g tree: children: front-end: - pipeline: - - boavizta-cpu + pipeline: + compute: + - boavizta-cpu config: boavizta-cpu: core-units: 24 From b7f433ae246a71f64e87d4295ed46a8341c3adf3 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:27:48 +0400 Subject: [PATCH 565/863] test(mocks): update mock-manifest.yaml --- src/__mocks__/mock-manifest.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml index 64e00e301..a69009d1e 100644 --- a/src/__mocks__/mock-manifest.yaml +++ b/src/__mocks__/mock-manifest.yaml @@ -57,7 +57,8 @@ tree: children: child: pipeline: - - memory-energy-from-memory-util + compute: + - memory-energy-from-memory-util config: null inputs: - timestamp: 2023-12-12T00:00:00.000Z From 949a34a2e15f186071062df93385d2d9588e4790 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:29:35 +0400 Subject: [PATCH 566/863] fix(manifests): remove group-by from plugins --- .../features/regroup/failure-missing-cloud-instance-type.yml | 3 --- manifests/examples/features/regroup/success.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml index 0b02593fd..8b8b44faf 100644 --- a/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml +++ b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml @@ -2,9 +2,6 @@ name: regroup description: initialize: plugins: - group-by: - path: "builtin" - method: GroupBy tree: children: my-app: diff --git a/manifests/examples/features/regroup/success.yml b/manifests/examples/features/regroup/success.yml index 4677e8edb..6863dc0d6 100644 --- a/manifests/examples/features/regroup/success.yml +++ b/manifests/examples/features/regroup/success.yml @@ -2,9 +2,6 @@ name: regroup description: successful path initialize: plugins: - group-by: - path: "builtin" - method: GroupBy tree: children: my-app: From 557de44184059c53bd53b82b79cc428e133bbabd Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:31:10 +0400 Subject: [PATCH 567/863] fix(config): update if-env template manifest --- src/if-env/config/env-template.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/if-env/config/env-template.yml b/src/if-env/config/env-template.yml index ba64c88dc..dc801cbc1 100644 --- a/src/if-env/config/env-template.yml +++ b/src/if-env/config/env-template.yml @@ -14,7 +14,8 @@ tree: children: # add a chile for each distinct component you want to measure child: pipeline: # the pipeline is an ordered list of plugins you want to execute - - memory-energy-from-memory-util # must match the name in initialize! + compute: + - memory-energy-from-memory-util # must match the name in initialize! config: # any plugin specific, node-level config inputs: - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string From 5c592489ec3501b7300d0dd890af041f84f0849a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 5 Aug 2024 19:32:59 +0400 Subject: [PATCH 568/863] docs(doc): update migration guide readme file --- Refactor-migration-guide.md | 70 ++++++++++--------------------------- 1 file changed, 18 insertions(+), 52 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index f8da3d8b8..e29a80d0e 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -125,24 +125,23 @@ There have also been some changes to the structure of manifest files. Some of th - **Node level config** - We have also introduced the concept of node-level config. This is designed for pluin configuration that might vary between components in the tree. For example, for each child in the tree you might wish to use the `groupby` plugin to group the outputs according to a different set of keys. + We have also introduced the concept of node-level config. This is designed for pluin configuration that might vary between components in the tree. For example, for each child in the tree you might wish to use the `regroup` feature to group the outputs according to a different set of keys. ```yaml tree: children: child-1: pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - config: - group-by: - group: - - region - - cloud/instance-type + compute: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync + - sci + regroup: + - region + - cloud/instance-type ``` - **Defaults** @@ -156,12 +155,13 @@ There have also been some changes to the structure of manifest files. Some of th children: child-1: pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci + compute: + - teads-curve + - sci-e + - sci-embodied + - sci-o + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -215,40 +215,6 @@ aggregation: type: 'both' ``` -### Groupby - -Groupby allows you to regroup your outputs according to keys you define. For example, maybe you want to group your outputs by region (show me all the outputs for applications run in `uk-south` etc). Groupby _is_ a plugin that needs to be initialized in the manifest. - -You can initialize the plugin as follows: - -```yaml -initialize: - plugins: - 'group-by': - path: builtin - method: GroupBy -``` - -Then you configure groupby for each component in the node level config. In the following example we will regroup the outputs by the `region`: - -```yaml -tree: - children: - child-1: - pipeline: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - group-by - - sci - config: - group-by: - group: - - region -``` - ### Exhaust We have introduced `exhaust` as an IF feature. This is a wrapper around export plugins and it allows community contributors to create plugins for exporting to different formats. From 7e6f61b122baf66b56d84dab26756548739aaff7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 6 Aug 2024 10:57:31 +0400 Subject: [PATCH 569/863] feat(.github): brake down worflow to multiple jobs --- .github/workflows/release-commit.yml | 38 +++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-commit.yml b/.github/workflows/release-commit.yml index efcf8726e..8ffa665f7 100644 --- a/.github/workflows/release-commit.yml +++ b/.github/workflows/release-commit.yml @@ -8,7 +8,7 @@ env: PRE_RELEASE: ${{ github.event.release.prerelease}} jobs: - release-commit-pr: + unit-tests: runs-on: ubuntu-latest steps: - name: Checkout code @@ -28,9 +28,45 @@ jobs: - name: Run unit tests run: npm test + integration-tests: + runs-on: ubuntu-latest + needs: unit-tests + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + run: npm ci + - name: Run integration tests run: npm run if-check -- -d manifests/outputs + publish: + runs-on: ubuntu-latest + needs: integration-tests + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + registry-url: https://registry.npmjs.org/ + + - name: Install dependencies + run: npm ci + - name: Initialize git user email run: git config --global user.email "${{ vars.RELEASE_USER_EMAIL }}" From c5814ef54640ec4ae78af3d161c1fa93192e5925 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Tue, 6 Aug 2024 11:16:32 +0400 Subject: [PATCH 570/863] fix(manifests): convert if diff outputs to phased exec --- .../pipeline-with-aggregate.yaml | 62 +++++++++-------- .../outputs-if-diff/pipeline-with-mocks.yaml | 66 +++++++++---------- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml index e227dd7ef..ee14e4e4a 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -237,22 +237,21 @@ tree: children: child-1: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -590,22 +589,21 @@ tree: carbon: 0.04532668505834602 child-2: pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index 39d7fef1b..a050da896 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -324,23 +324,22 @@ tree: children: child-1: pipeline: - - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - instance-type + regroup: + - cloud/region + - instance-type + compute: + - mock-observations + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -678,23 +677,22 @@ tree: carbon: '*' child-2: pipeline: - - mock-observations - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - config: - group-by: - group: - - cloud/region - - cloud/instance-type + regroup: + - cloud/region + - instance-type + compute: + - mock-observations + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 From 90e7fe3bbb4a755f3a8d64675b1dd4670d345b32 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Tue, 6 Aug 2024 11:31:11 +0400 Subject: [PATCH 571/863] fix(manifests): convert nesting output to phased exec --- manifests/outputs/pipelines/nesting.yaml | 69 ++++++++++++------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 83ed612d5..5e26ae900 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -609,17 +609,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 @@ -976,17 +977,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 @@ -1341,17 +1343,18 @@ tree: vcpus-allocated: 1 vcpus-total: 8 pipeline: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci inputs: - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 From 0e753d0ad2b71421dbfb4da9bd4d4679bc1a5533 Mon Sep 17 00:00:00 2001 From: MariamKhalatova Date: Tue, 6 Aug 2024 15:43:23 +0400 Subject: [PATCH 572/863] fix(manifests): move mock observations to observe --- .../pipelines/outputs-if-diff/pipeline-with-mocks.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index a050da896..983e7a638 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -324,11 +324,12 @@ tree: children: child-1: pipeline: + observe: + - mock-observations regroup: - cloud/region - instance-type compute: - - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration @@ -677,11 +678,12 @@ tree: carbon: '*' child-2: pipeline: + observe: + - mock-observations regroup: - cloud/region - instance-type compute: - - mock-observations - interpolate - cpu-factor-to-wattage - wattage-times-duration @@ -692,7 +694,7 @@ tree: - operational-carbon - sum-carbon - time-sync - - sci + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 From 237f44b709ac683444281a5c0e7909278eae6fd9 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 18:10:40 +0400 Subject: [PATCH 573/863] fix(config): update `REGROUP_ERROR` message --- src/if-run/config/strings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 24835f8ed..e5e6e449b 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -24,8 +24,7 @@ export const STRINGS = { METRIC_MISSING: (metric: string, index: number) => `Aggregation metric ${metric} is not found in inputs[${index}].`, INVALID_GROUP_KEY: (key: string) => `Invalid group ${key}.`, - REGROUP_ERROR: - 'Regroup phase is not an array or should contain at least one key.', + REGROUP_ERROR: 'not an array or should contain at least one key', INVALID_EXHAUST_PLUGIN: (pluginName: string) => `Invalid exhaust plugin: ${pluginName}.`, UNKNOWN_PARAM: (name: string) => From a6abeed714f2845c5bc7304047a845fd3b4af7f1 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 18:12:20 +0400 Subject: [PATCH 574/863] fix(lib): fix regroup validation --- src/if-run/lib/regroup.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index eba87a4d0..affd51307 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -44,12 +44,13 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { /** * Validates groups array. */ - const validateGroups = (groups: string[]) => { - const inputData = {groups}; + const validateGroups = (regroup: string[]) => { + const inputData = {regroup}; const validationSchema = z.record( z.string(), - z.array(z.string()).min(1, REGROUP_ERROR) + z.array(z.string(), {message: REGROUP_ERROR}).min(1) ); + validate(validationSchema, inputData); return groups; From 98bdee7bebb696ec242ee5dbba6f630ce857e95f Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 18:14:15 +0400 Subject: [PATCH 575/863] test(lib): update error messages --- src/__tests__/if-run/lib/regroup.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/regroup.test.ts b/src/__tests__/if-run/lib/regroup.test.ts index 9f0b373ff..67ff72e53 100644 --- a/src/__tests__/if-run/lib/regroup.test.ts +++ b/src/__tests__/if-run/lib/regroup.test.ts @@ -86,7 +86,7 @@ describe('lib/regroup: ', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( new InputValidationError( - '"groups" parameter is required. Error code: invalid_type.' + '"regroup" parameter is not an array or should contain at least one key. Error code: invalid_type.' ) ); } @@ -135,7 +135,7 @@ describe('lib/regroup: ', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( new InputValidationError( - '"groups" parameter is regroup phase is not an array or should contain at least one key.. Error code: too_small.' + '"regroup" parameter is array must contain at least 1 element(s). Error code: too_small.' ) ); } From 9fcdcbf873572f94fa4cb2277c21c35680a5ba25 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:07:41 +0400 Subject: [PATCH 576/863] fix(manifests): remove config from manifests --- .../coefficient/failure-invalid-config-input-param.yml | 2 -- .../builtins/coefficient/failure-output-param-is-null.yaml | 2 -- manifests/examples/builtins/coefficient/success.yml | 2 -- .../cloud-metadata/failure-invalid-instance-type.yaml | 1 - .../csv-lookup/cloud-metadata/failure-invalid-vendor.yaml | 1 - .../cloud-metadata/failure-missing-cloud-vendor.yml | 1 - .../examples/builtins/csv-lookup/cloud-metadata/success.yml | 1 - .../csv-lookup/tdp-finder/failure-missing-input-param.yml | 1 - .../tdp-finder/failure-unsupported-physical-processor.yml | 1 - .../examples/builtins/csv-lookup/tdp-finder/success.yml | 1 - .../builtins/divide/failure-denominator-equal-zero.yml | 2 -- .../builtins/divide/failure-invalid-config-denominator.yml | 2 -- .../examples/builtins/divide/failure-missing-numerator.yml | 2 -- .../examples/builtins/sci/failure-invalid-config-value.yml | 5 ++--- .../outputs/builtins/divide/failure-missing-numerator.yaml | 2 -- .../outputs/builtins/sci/failure-invalid-config-value.yaml | 5 ++--- manifests/outputs/pipelines/pipeline-teads-sci.yaml | 1 - 17 files changed, 4 insertions(+), 28 deletions(-) diff --git a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml index 5d497b948..55f9f0b64 100644 --- a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml +++ b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml @@ -16,8 +16,6 @@ tree: pipeline: compute: - coefficient - config: - sum: inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml index 1ef932df0..ce722c9dd 100644 --- a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml @@ -16,8 +16,6 @@ tree: pipeline: compute: - coefficient - config: - sum: inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml index 69dd764eb..31e75a235 100644 --- a/manifests/examples/builtins/coefficient/success.yml +++ b/manifests/examples/builtins/coefficient/success.yml @@ -16,8 +16,6 @@ tree: pipeline: compute: - coefficient - config: - sum: inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index 21f9769b4..6a6e2201e 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -18,7 +18,6 @@ tree: pipeline: compute: - cloud-metadata - config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred cloud/vendor: aws diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index c9fbb8296..5098c7a95 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -18,7 +18,6 @@ tree: pipeline: compute: - cloud-metadata - config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred cloud/vendor: gcp diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index 62de6150d..3c7d9d55d 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -18,7 +18,6 @@ tree: pipeline: compute: - cloud-metadata - config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred #cloud/vendor: aws diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml index 84e10112b..e11db823f 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -18,7 +18,6 @@ tree: pipeline: compute: - cloud-metadata - config: inputs: - timestamp: 2023-07-06T00:00 # [KEYWORD] [NO-SUBFIELDS] time when measurement occurred cloud/vendor: aws diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml index 991bdbb8b..03791996a 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -17,7 +17,6 @@ tree: pipeline: compute: - tdp-finder - config: inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml index 3d433d6b2..db0459d56 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -17,7 +17,6 @@ tree: pipeline: compute: - tdp-finder - config: inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml index a04288e0c..b60869399 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -17,7 +17,6 @@ tree: pipeline: compute: - tdp-finder - config: inputs: - timestamp: 2023-07-06T00:00 duration: 300 diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index 96d627aee..c3a4d216d 100644 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -26,8 +26,6 @@ tree: compute: - cloud-metadata - divide - config: - divide: defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index fef8a1a7c..712e1205c 100644 --- a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -26,8 +26,6 @@ tree: compute: - cloud-metadata - divide - config: - divide: defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/examples/builtins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml index 5645f0ecf..59b604582 100644 --- a/manifests/examples/builtins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -26,8 +26,6 @@ tree: compute: - cloud-metadata - divide - config: - divide: defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/examples/builtins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml index 5882111dd..2d51dbe66 100644 --- a/manifests/examples/builtins/sci/failure-invalid-config-value.yml +++ b/manifests/examples/builtins/sci/failure-invalid-config-value.yml @@ -15,9 +15,8 @@ tree: pipeline: compute: - sci - config: - sci: - functional-unit: 999 # factor to convert per time to per f.unit + defaults: + functional-unit: 999 # factor to convert per time to per f.unit inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml index 6c714bf18..235b3395a 100644 --- a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml @@ -62,8 +62,6 @@ tree: pipeline: compute: - divide - config: - divide: null defaults: cloud/vendor: aws cloud/instance-type: m5n.large diff --git a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml index 384fe14b1..c8f34a4e4 100644 --- a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml +++ b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml @@ -58,9 +58,8 @@ tree: pipeline: compute: - sci - config: - sci: - functional-unit: 999 + defaults: + functional-unit: 999 inputs: - timestamp: 2023-07-06T00:00 duration: 3600 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index 1c2a9d005..05e28edd4 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -142,7 +142,6 @@ tree: - operational-carbon - sum-carbon - sci - config: null defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 From fb5622950b468e0dc127b3122c340b68224b7a94 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:10:08 +0400 Subject: [PATCH 577/863] test(mocks): remove config from mocked files --- src/__mocks__/builtins/export-yaml.ts | 2 -- src/__mocks__/fs/index.ts | 7 +++---- src/__mocks__/mock-manifest.yaml | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/__mocks__/builtins/export-yaml.ts b/src/__mocks__/builtins/export-yaml.ts index 85f54e966..b323de7b5 100644 --- a/src/__mocks__/builtins/export-yaml.ts +++ b/src/__mocks__/builtins/export-yaml.ts @@ -6,7 +6,6 @@ export const tree = { children: { 'child-1': { pipeline: ['teads-curve', 'sum', 'sci-embodied', 'sci-o', 'sci'], - config: null, defaults: { 'cpu/thermal-design-power': 100, 'grid/carbon-intensity': 800, @@ -55,7 +54,6 @@ export const tree = { }, 'child-2': { pipeline: ['teads-curve', 'sum', 'sci-embodied', 'sci-o', 'sci'], - config: null, defaults: { 'cpu/thermal-design-power': 100, 'grid/carbon-intensity': 800, diff --git a/src/__mocks__/fs/index.ts b/src/__mocks__/fs/index.ts index 491123143..7acaf9f20 100644 --- a/src/__mocks__/fs/index.ts +++ b/src/__mocks__/fs/index.ts @@ -55,10 +55,9 @@ cpu-cores-available,cpu-cores-utilized,cpu-manufacturer,cpu-model-name,cpu-tdp,g pipeline: compute: - boavizta-cpu - config: - boavizta-cpu: - core-units: 24 - processor: Intel® Core™ i7-1185G7 + defaults: + core-units: 24 + processor: Intel® Core™ i7-1185G7 inputs: - timestamp: 2023-07-06T00:00 duration: 3600 # Secs diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml index a69009d1e..549b2c14f 100644 --- a/src/__mocks__/mock-manifest.yaml +++ b/src/__mocks__/mock-manifest.yaml @@ -59,7 +59,6 @@ tree: pipeline: compute: - memory-energy-from-memory-util - config: null inputs: - timestamp: 2023-12-12T00:00:00.000Z duration: 3600 From d1fb8d74d8498d972d1690125b46e738bf80435d Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:17:35 +0400 Subject: [PATCH 578/863] test(lib): update comupte test --- src/__tests__/if-run/lib/compute.test.ts | 25 ------------------------ 1 file changed, 25 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index 912793381..4663d461b 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -252,31 +252,6 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - - it('computes simple tree with node config and execute plugin.', async () => { - const tree = { - children: { - mockChild: { - pipeline: { - compute: ['mock'], - }, - config: { - 'cpu/name': 'Intel CPU', - }, - inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, - ], - }, - }, - }; - const response = await compute(tree, paramsExecute); - const expectedResult = mockExecutePlugin().execute( - tree.children.mockChild.inputs - ); - - expect(response.children.mockChild.outputs).toEqual(expectedResult); - }); }); it('computes simple tree with observe plugin.', async () => { From 0c34bcc953dd39cded51591bf9dd59e2cd522e16 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:19:53 +0400 Subject: [PATCH 579/863] fix(config): remove config from if-env template --- src/if-env/config/env-template.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/if-env/config/env-template.yml b/src/if-env/config/env-template.yml index dc801cbc1..ec412c47b 100644 --- a/src/if-env/config/env-template.yml +++ b/src/if-env/config/env-template.yml @@ -6,7 +6,7 @@ initialize: memory-energy-from-memory-util: # you can name this any way you like! method: Coefficient # the name of the function exported from the plugin path: "builtin" # the import path - global-config: # anmy config required by the plugin + global-config: # any config required by the plugin input-parameter: "memory/utilization" coefficient: 0.0001 #kwH/GB output-parameter: "memory/energy" @@ -16,7 +16,6 @@ tree: pipeline: # the pipeline is an ordered list of plugins you want to execute compute: - memory-energy-from-memory-util # must match the name in initialize! - config: # any plugin specific, node-level config inputs: - timestamp: 2023-12-12T00:00:00.000Z # ISO 8061 string duration: 3600 # units of seconds From 73331916030db8221eb056c07569bfd242997b4c Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:23:21 +0400 Subject: [PATCH 580/863] docs(builtins): remove config from builtins doc example --- src/if-run/builtins/README.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/if-run/builtins/README.md b/src/if-run/builtins/README.md index e05110887..a2b1a8c81 100644 --- a/src/if-run/builtins/README.md +++ b/src/if-run/builtins/README.md @@ -222,8 +222,8 @@ initialize: method: TeadsCurve path: '@grnsft/if-unofficial-plugins' sci-e: - method: SciE - path: '@grnsft/if-plugins' + method: SciEmbodied + path: 'builtin' sci-embodied: path: 'builtin' method: SciEmbodied @@ -237,6 +237,7 @@ initialize: start-time: '2023-12-12T00:00:00.000Z' # ISO timestamp end-time: '2023-12-12T00:01:00.000Z' # ISO timestamp interval: 5 # seconds + allow-padding: true tree: children: child: # an advanced grouping node @@ -247,19 +248,16 @@ tree: - sci-embodied - sci-o - time-sync - config: - teads-curve: - cpu/thermal-design-power: 65 - sci-embodied: - device/emissions-embodied: 251000 # gCO2eq - time-reserved: 3600 # 1 hour in s - device/expected-lifespan: 126144000 # 4 years in seconds - resources-reserved: 1 - resources-total: 1 - sci-o: - grid/carbon-intensity: 457 # gCO2/kwh children: child-1: + defaults: + device/emissions-embodied: 251000 # gCO2eq + time-reserved: 3600 # 1 hour in s + device/expected-lifespan: 126144000 # 4 years in seconds + resources-reserved: 1 + resources-total: 1 + grid/carbon-intensity: 457 # gCO2/kwh + cpu/thermal-design-power: 65 inputs: - timestamp: '2023-12-12T00:00:00.000Z' duration: 10 @@ -269,6 +267,7 @@ tree: requests: 300 - timestamp: '2023-12-12T00:00:10.000Z' duration: 10 + cpu/thermal-design-power: 65 cpu/utilization: 20 carbon: 200 energy: 200 From 1e4f86fadcb1dc9c9a7e51b53a6553a6b3e1f44d Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:28:20 +0400 Subject: [PATCH 581/863] docs(doc): remove node config description section --- Refactor-migration-guide.md | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index e29a80d0e..481eb2a7c 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -123,27 +123,6 @@ There have also been some changes to the structure of manifest files. Some of th allow-padding: true ``` -- **Node level config** - - We have also introduced the concept of node-level config. This is designed for pluin configuration that might vary between components in the tree. For example, for each child in the tree you might wish to use the `regroup` feature to group the outputs according to a different set of keys. - - ```yaml - tree: - children: - child-1: - pipeline: - compute: - - teads-curve - - sci-e - - sci-embodied - - sci-o - - time-sync - - sci - regroup: - - region - - cloud/instance-type - ``` - - **Defaults** We have also introduced the concept of `defaults`. This is a section in each component's definition that can be used to provide fallbacks for missing input data. For example, perhaps you have a value arriving from an external API that should be present in every observation in your inputs array, but for soem reason the API fails to deliver a value for some timestamps. In this case, IF would fallback to the value provided for that metric in the `defaults` section of the manifest for that component. @@ -229,10 +208,7 @@ Instead of the old class-based model, plugins are now functions. They conform to ```ts export type PluginInterface = { - execute: ( - inputs: PluginParams[], - config?: Record - ) => PluginParams[]; + execute: (inputs: PluginParams[]) => PluginParams[]; metadata: { kind: string; }; From d64182f3a991828476453b1052071f9f91c54217 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:29:52 +0400 Subject: [PATCH 582/863] feat(config): add `CONFIG_WARN` string --- src/if-run/config/strings.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 24835f8ed..e93fea11f 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -108,4 +108,10 @@ ${error}`, MISSING_GLOBAL_CONFIG: 'Global config is not provided.', MISSING_INPUT_DATA: (param: string) => `${param} is missing from the input array, or has nullish value.`, + CONFIG_WARN: (plugins: string, isMore: boolean) => + `You have included node-level config in your manifest to support \`${plugins}\` plugin${ + isMore ? 's' : '' + }. IF no longer supports node-level config. \`${plugins}\` plugin${ + isMore ? 's' : '' + } should be refactored to accept all its config from global config or input data.`, }; From d5d66aea7e870ef01d99d676e2c18d8f061c5d17 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:38:18 +0400 Subject: [PATCH 583/863] fix(types): remove config from types --- src/if-run/types/compute.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index 6777bf553..53c6bdb78 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -3,10 +3,6 @@ import {PluginParams} from '@grnsft/if-core/types'; import {PluginStorageInterface} from './plugin-storage'; import {Context} from '../../common/types/manifest'; -export type NodeConfig = { - [key: string]: Record; -}; - export type PhasedPipeline = { observe?: string[]; regroup?: string[]; @@ -17,7 +13,6 @@ export type ComputeParams = { pluginStorage: PluginStorageInterface; context: Context; pipeline?: PhasedPipeline; - config?: NodeConfig; defaults?: PluginParams; observe?: Boolean; regroup?: Boolean; @@ -27,7 +22,6 @@ export type ComputeParams = { export type Node = { children?: any; pipeline?: PhasedPipeline; - config?: NodeConfig; defaults?: PluginParams; inputs?: PluginParams[]; outputs?: PluginParams[]; From abf2214f61273fa23fbff1fd86303c1f6fe4e0c3 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 6 Aug 2024 19:40:45 +0400 Subject: [PATCH 584/863] feat(lib): remove config and add warning message if persists in the manifest --- src/if-run/lib/compute.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 41a153448..ff882d887 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -3,15 +3,17 @@ import {PluginParams} from '@grnsft/if-core/types'; import {Regroup} from './regroup'; import {addExplainData} from './explain'; -import {mergeObjects} from '../util/helpers'; import {debugLogger} from '../../common/util/debug-logger'; +import {logger} from '../../common/util/logger'; + +import {mergeObjects} from '../util/helpers'; import {STRINGS} from '../config/strings'; import {ComputeParams, Node, PhasedPipeline} from '../types/compute'; import {isExecute} from '../types/interface'; -const {MERGING_DEFAULTS_WITH_INPUT_DATA} = STRINGS; +const {MERGING_DEFAULTS_WITH_INPUT_DATA, CONFIG_WARN} = STRINGS; /** * Traverses all child nodes based on children grouping. @@ -60,16 +62,16 @@ const mergeDefaults = ( */ const computeNode = async (node: Node, params: ComputeParams): Promise => { const pipeline = node.pipeline || (params.pipeline as PhasedPipeline); - const config = node.config || params.config; const defaults = node.defaults || params.defaults; const noFlags = !params.observe && !params.regroup && !params.compute; + warnIfConfigProvided(node); + if (node.children) { return traverse(node.children, { ...params, pipeline, defaults, - config, }); } @@ -84,10 +86,9 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { while (pipelineCopy.observe.length !== 0) { const pluginName = pipelineCopy.observe.shift() as string; const plugin = params.pluginStorage.get(pluginName); - const nodeConfig = config && config[pluginName]; if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); + inputStorage = await plugin.execute(inputStorage); node.inputs = inputStorage; if (params.context.explainer) { @@ -118,7 +119,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { regroup: undefined, }, defaults, - config, }); } @@ -129,10 +129,9 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { while (pipelineCopy.compute.length !== 0) { const pluginName = pipelineCopy.compute.shift() as string; const plugin = params.pluginStorage.get(pluginName); - const nodeConfig = config && config[pluginName]; if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); + inputStorage = await plugin.execute(inputStorage); node.outputs = inputStorage; debugLogger.setExecutingPluginName(); } @@ -140,6 +139,19 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { } }; +/** + * Warns if the `config` is provided in the manifest. + */ +const warnIfConfigProvided = (node: any) => { + if ('config' in node) { + const plugins = Object.keys(node.config); + const joinedPlugins = plugins.join(', '); + const isMore = plugins.length > 1; + + logger.warn(CONFIG_WARN(joinedPlugins, isMore)); + } +}; + /** * Creates copy of existing tree, then applies computing strategy. */ From d6731517a2e734e4b6131e6da438e050091576f2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 7 Aug 2024 10:23:34 +0400 Subject: [PATCH 585/863] feat(config): add EMPTY_PIPELINE to strings --- src/if-run/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 24835f8ed..deb7d0052 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -58,6 +58,8 @@ Note that for the '--output' option you also need to define the output type in y PREPARING_OUTPUT_DATA: 'Preparing output data', EXPORTING_TO_YAML_FILE: (savepath: string) => `Exporting to yaml file: ${savepath}`, + EMPTY_PIPELINE: `You've using an old style manifest. Please update for phased execution. More information can be found here: +https://if.greensoftware.foundation/major-concepts/manifest-file`, /** Exhaust messages */ OUTPUT_REQUIRED: 'Output path is required, please make sure output is configured properly.', From 4f6dc3d6112b721041115fc0ca2f824da1ba535b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 7 Aug 2024 10:28:00 +0400 Subject: [PATCH 586/863] feat(lib): add empty pipeline message --- src/if-run/lib/compute.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 41a153448..27426bbc6 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -5,13 +5,14 @@ import {addExplainData} from './explain'; import {mergeObjects} from '../util/helpers'; import {debugLogger} from '../../common/util/debug-logger'; +import {logger} from '../../common/util/logger'; import {STRINGS} from '../config/strings'; import {ComputeParams, Node, PhasedPipeline} from '../types/compute'; import {isExecute} from '../types/interface'; -const {MERGING_DEFAULTS_WITH_INPUT_DATA} = STRINGS; +const {MERGING_DEFAULTS_WITH_INPUT_DATA, EMPTY_PIPELINE} = STRINGS; /** * Traverses all child nodes based on children grouping. @@ -77,6 +78,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { inputStorage = mergeDefaults(inputStorage, defaults); const pipelineCopy = structuredClone(pipeline) || {}; + if (Object.keys(pipelineCopy).length === 0) { + logger.warn(EMPTY_PIPELINE); + } + /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. */ From 8c41f70d3db843ed91af8a92db6305699e304ac2 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 17:52:29 +0400 Subject: [PATCH 587/863] fix(manifests): remove `method` from aggregation section --- manifests/examples/pipelines/nesting.yml | 26 +- .../pipeline-with-aggregate.yaml | 18 +- .../outputs-if-diff/pipeline-with-mocks.yaml | 655 +++++++++--------- .../pipelines/pipeline-with-aggregate.yml | 9 +- .../pipelines/pipeline-with-mocks.yml | 3 +- .../bugs/aggregation-error-wrong-metric.yaml | 3 +- .../aggregate-failure-invalid-metrics.yaml | 3 +- ...gate-failure-missing-metric-in-inputs.yaml | 3 +- .../features/aggregate-horizontal.yaml | 9 +- .../outputs/features/aggregate-vertical.yaml | 9 +- manifests/outputs/features/aggregate.yaml | 9 +- manifests/outputs/pipelines/nesting.yaml | 234 ++++--- 12 files changed, 519 insertions(+), 462 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index 185c715e0..baf12a688 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -6,8 +6,7 @@ tags: category: on-premise aggregation: metrics: - "carbon": - method: sum + - carbon type: "both" initialize: plugins: @@ -139,6 +138,21 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + description: Operational carbon footprint + unit: gCO2eq + aggregation-method: sum + carbon-embodied: + description: Embodied carbon footprint + unit: gCO2eq + aggregation-method: sum + outputs: + carbon: + description: Total carbon footprint + unit: gCO2eq + aggregation-method: sum time-sync: method: TimeSync path: "builtin" @@ -169,10 +183,10 @@ initialize: unit: seconds description: time reserved for a component aggregation-method: avg - network/energy: - description: 'Energy consumed by the Network of the component' - unit: 'kWh' - aggregation-method: 'sum' + network/energy: + description: "Energy consumed by the Network of the component" + unit: "kWh" + aggregation-method: "sum" tree: children: child-0: diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml index ee14e4e4a..c1f92da04 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -3,8 +3,7 @@ description: a full pipeline with the aggregate feature enabled tags: null aggregation: metrics: - carbon: - method: sum + - carbon type: both initialize: plugins: @@ -159,6 +158,21 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + description: Operational carbon footprint + unit: gCO2eq + aggregation-method: sum + carbon-embodied: + description: Embodied carbon footprint + unit: gCO2eq + aggregation-method: sum + outputs: + carbon: + description: Total carbon footprint + unit: gCO2eq + aggregation-method: sum time-sync: path: builtin method: TimeSync diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index 983e7a638..77496bf23 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -3,8 +3,7 @@ description: a full pipeline seeded with data from mock-observations feature tags: null aggregation: metrics: - carbon: - method: sum + - carbon type: both initialize: plugins: @@ -52,7 +51,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -247,8 +246,8 @@ initialize: path: builtin method: TimeSync global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true parameter-metadata: @@ -285,20 +284,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-30T05:35:42.937Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.16" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -340,7 +339,7 @@ tree: - operational-carbon - sum-carbon - time-sync - - sci + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -350,36 +349,36 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 10 requests: 30 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west requests: 40 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west requests: 30 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 requests: 50 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -388,21 +387,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:05.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:05.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -411,21 +410,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:10.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:10.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -434,21 +433,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:15.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:15.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -457,21 +456,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:20.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:20.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -480,21 +479,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:25.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:25.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -503,21 +502,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:30.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:30.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -526,21 +525,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:35.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:35.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -549,21 +548,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:40.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:40.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -572,21 +571,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:45.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:45.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -595,21 +594,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:50.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:50.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -618,21 +617,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:55.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:55.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" requests: 2.5 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 @@ -641,21 +640,21 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.000010128107559614409 - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:01:00.000Z' + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:01:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 - cpu/utilization: '*' + cpu/utilization: "*" requests: 0.5 cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -664,18 +663,18 @@ tree: device/expected-lifespan: 1576800 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' + cpu-energy-kwh: "*" carbon-embodied: 0.0000020256215119228817 - carbon-operational: '*' - carbon: '*' - sci: '*' + carbon-operational: "*" + carbon: "*" + sci: "*" aggregated: - carbon: '*' + carbon: "*" child-2: pipeline: observe: @@ -694,7 +693,7 @@ tree: - operational-carbon - sum-carbon - time-sync - - sci + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -704,34 +703,34 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 cpu/utilization: 30 cloud/instance-type: A1 cloud/region: uk-west requests: 30 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 28 cloud/instance-type: A1 cloud/region: uk-west requests: 40 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 40 cloud/instance-type: A1 cloud/region: uk-west requests: 50 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west requests: 60 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -742,19 +741,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:05.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -765,19 +764,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:10.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -788,19 +787,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:15.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -811,19 +810,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:20.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -834,19 +833,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:25.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -857,19 +856,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:30.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -880,19 +879,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:35.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -903,19 +902,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:40.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -926,19 +925,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:45.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -949,19 +948,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:50.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -972,19 +971,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:00:55.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 2.5 @@ -995,19 +994,19 @@ tree: device/expected-lifespan: 7884000 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' - - timestamp: '2023-12-12T00:01:00.000Z' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west requests: 0.5 @@ -1018,57 +1017,57 @@ tree: device/expected-lifespan: 1576800 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" vcpu-ratio: 8 - cpu-energy-kwh: '*' - carbon-embodied: '*' - carbon-operational: '*' - carbon: '*' - sci: '*' + cpu-energy-kwh: "*" + carbon-embodied: "*" + carbon-operational: "*" + carbon: "*" + sci: "*" aggregated: - carbon: '*' + carbon: "*" outputs: - - carbon: '*' - timestamp: '2023-12-12T00:00:00.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:00.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:05.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:10.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:15.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:20.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:25.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:30.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:35.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:40.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:45.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:50.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:00:55.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - - carbon: '*' - timestamp: '2023-12-12T00:01:00.000Z' + - carbon: "*" + timestamp: "2023-12-12T00:01:00.000Z" duration: 1 aggregated: - carbon: '*' + carbon: "*" diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index dd4dffa1c..184820228 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -3,8 +3,7 @@ description: a full pipeline with the aggregate feature enabled tags: aggregation: metrics: - "carbon": - method: sum + - carbon type: "both" initialize: plugins: @@ -145,6 +144,12 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon + parameter-metadata: + outputs: + carbon: + unit: gCO2eq + description: product of carbon + aggregation-method: sum "time-sync": method: TimeSync path: "builtin" diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 58933b171..fc6f81cb0 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -3,8 +3,7 @@ description: a full pipeline seeded with data from mock-observations feature tags: aggregation: metrics: - "carbon": - method: sum + - carbon type: "both" initialize: plugins: diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index 313834f76..92f85c0d7 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -5,8 +5,7 @@ description: >- tags: null aggregation: metrics: - "dummy-param": - method: sum + - dummy-param type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index 11e7f5865..aef8ef6c5 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -2,8 +2,7 @@ name: Aggregation description: Fails with invalid metric. aggregation: metrics: - "test": - method: sum + - test type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 0e308d509..2dfc9fe80 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -2,8 +2,7 @@ name: Aggregation description: Fails with missing metric in inputs. aggregation: metrics: - "cpu/utilization": - method: sum + - cpu/utilization type: both initialize: plugins: diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index 0fef8d756..d595d5bdb 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -2,8 +2,7 @@ name: Aggregation description: Apply `horizontal` aggregation aggregation: metrics: - "cpu/utilization": - method: avg + - cpu/utilization type: horizontal initialize: plugins: @@ -18,6 +17,12 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index dfd604c73..9213522af 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -2,8 +2,7 @@ name: Aggregation description: Apply `vertical` aggregation aggregation: metrics: - "cpu/utilization": - method: avg + - cpu/utilization type: vertical initialize: plugins: @@ -18,6 +17,12 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index 79736b9c0..cb9ed29dc 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -2,8 +2,7 @@ name: Aggregation description: Apply both `horizontal` and `vertical` aggregations aggregation: metrics: - "cpu/utilization": - method: avg + - cpu/utilization type: both initialize: plugins: @@ -18,6 +17,12 @@ initialize: output: - cpu-cores-utilized - vcpus-allocated + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 5e26ae900..792f41243 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -6,8 +6,7 @@ tags: category: on-premise aggregation: metrics: - carbon: - method: sum + - carbon type: both initialize: plugins: @@ -21,7 +20,7 @@ initialize: - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -153,12 +152,27 @@ initialize: - carbon-operational - carbon-embodied output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + description: Operational carbon footprint + unit: gCO2eq + aggregation-method: sum + carbon-embodied: + description: Embodied carbon footprint + unit: gCO2eq + aggregation-method: sum + outputs: + carbon: + description: Total carbon footprint + unit: gCO2eq + aggregation-method: sum time-sync: path: builtin method: TimeSync global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true parameter-metadata: @@ -196,20 +210,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-31T13:17:29.944Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.16" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -256,28 +270,28 @@ tree: - time-sync - sci inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 60 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 70 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -285,7 +299,7 @@ tree: network/energy: 0.000001 requests: 55 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -309,7 +323,7 @@ tree: carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00006983123919278518 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -333,7 +347,7 @@ tree: carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0001028924208718729 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -357,7 +371,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0001544881286073813 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -381,7 +395,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -405,7 +419,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -429,7 +443,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -453,7 +467,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -477,7 +491,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -501,7 +515,7 @@ tree: carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0005673927632489276 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -525,7 +539,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -549,7 +563,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -573,7 +587,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west @@ -622,28 +636,28 @@ tree: - time-sync - sci inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 10 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 90 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 30 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -651,7 +665,7 @@ tree: network/energy: 0.000001 requests: 22 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -675,7 +689,7 @@ tree: carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.0000834568468401579 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -699,7 +713,7 @@ tree: carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.00015224732194049487 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -723,7 +737,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.000363108733129716 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -747,7 +761,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -771,7 +785,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -795,7 +809,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -819,7 +833,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -843,7 +857,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -867,7 +881,7 @@ tree: carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0014184819081223194 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -891,7 +905,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -915,7 +929,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -939,7 +953,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west @@ -990,28 +1004,28 @@ tree: - time-sync - sci inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 65 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 80 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -1019,7 +1033,7 @@ tree: network/energy: 0.000001 requests: 40 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -1043,7 +1057,7 @@ tree: carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00006709275922444067 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -1067,7 +1081,7 @@ tree: carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0000911261343001502 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -1091,7 +1105,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.00014075142645028166 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1115,7 +1129,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1139,7 +1153,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1163,7 +1177,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1187,7 +1201,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1211,7 +1225,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1235,7 +1249,7 @@ tree: carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0007801650494672755 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1259,7 +1273,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1283,7 +1297,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1307,7 +1321,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west @@ -1356,28 +1370,28 @@ tree: - time-sync - sci inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 50 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 60 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -1385,7 +1399,7 @@ tree: network/energy: 0.000001 requests: 40 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -1409,7 +1423,7 @@ tree: carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00007603846045436609 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -1433,7 +1447,7 @@ tree: carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.00012081561676568304 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -1457,7 +1471,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0001832602465191587 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1481,7 +1495,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1505,7 +1519,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1529,7 +1543,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1553,7 +1567,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1577,7 +1591,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1601,7 +1615,7 @@ tree: carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0007801650494672755 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1625,7 +1639,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1649,7 +1663,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1673,7 +1687,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west @@ -1701,85 +1715,85 @@ tree: carbon: 0.04652112950279046 outputs: - carbon: 0.013686922881785895 - timestamp: '2023-12-12T00:00:00.000Z' + timestamp: "2023-12-12T00:00:00.000Z" duration: 5 - carbon: 0.010700811770674782 - timestamp: '2023-12-12T00:00:05.000Z' + timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - carbon: 0.010402200659563673 - timestamp: '2023-12-12T00:00:10.000Z' + timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - carbon: 0.010402200659563675 - timestamp: '2023-12-12T00:00:15.000Z' + timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - carbon: 0.010402200659563675 - timestamp: '2023-12-12T00:00:20.000Z' + timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - carbon: 0.010402200659563675 - timestamp: '2023-12-12T00:00:25.000Z' + timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - carbon: 0.010402200659563675 - timestamp: '2023-12-12T00:00:30.000Z' + timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - carbon: 0.010402200659563675 - timestamp: '2023-12-12T00:00:35.000Z' + timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - carbon: 0.006241320395738204 - timestamp: '2023-12-12T00:00:40.000Z' + timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' + timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' + timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' + timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:01:00.000Z' + timestamp: "2023-12-12T00:01:00.000Z" duration: 1 aggregated: carbon: 0.09304225900558093 outputs: - carbon: 0.02737384576357179 - timestamp: '2023-12-12T00:00:00.000Z' + timestamp: "2023-12-12T00:00:00.000Z" duration: 5 - carbon: 0.021401623541349564 - timestamp: '2023-12-12T00:00:05.000Z' + timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - carbon: 0.020804401319127346 - timestamp: '2023-12-12T00:00:10.000Z' + timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - carbon: 0.02080440131912735 - timestamp: '2023-12-12T00:00:15.000Z' + timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - carbon: 0.02080440131912735 - timestamp: '2023-12-12T00:00:20.000Z' + timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - carbon: 0.02080440131912735 - timestamp: '2023-12-12T00:00:25.000Z' + timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - carbon: 0.02080440131912735 - timestamp: '2023-12-12T00:00:30.000Z' + timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - carbon: 0.02080440131912735 - timestamp: '2023-12-12T00:00:35.000Z' + timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - carbon: 0.012482640791476408 - timestamp: '2023-12-12T00:00:40.000Z' + timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' + timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' + timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' + timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:01:00.000Z' + timestamp: "2023-12-12T00:01:00.000Z" duration: 1 aggregated: carbon: 0.18608451801116185 From 45821add239ffafc626b66290a85395bc6d30088 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:18:53 +0400 Subject: [PATCH 588/863] fix(util): update manifest schema --- src/common/util/validations.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 95d9efeff..5cdbec5db 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -3,10 +3,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../if-run/config'; -import { - AGGREGATION_METHODS, - AGGREGATION_TYPES, -} from '../../if-run/types/aggregation'; +import {AGGREGATION_TYPES} from '../../if-run/types/aggregation'; const {ManifestValidationError, InputValidationError} = ERRORS; const {VALIDATING_MANIFEST} = STRINGS; @@ -72,11 +69,7 @@ export const manifestSchema = z.object({ explain: z.record(z.string(), z.any()).optional(), aggregation: z .object({ - metrics: z.record( - z.object({ - method: z.enum(AGGREGATION_METHODS), - }) - ), + metrics: z.array(z.string()), type: z.enum(AGGREGATION_TYPES), }) .optional() From 719a239e1cea887935420046e03616cb84ced525 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:23:52 +0400 Subject: [PATCH 589/863] fix(lib): update aggregation logic without `method` --- src/if-run/lib/aggregate.ts | 21 +++++++++++++-------- src/if-run/lib/initialize.ts | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 508117bb3..b80d0048a 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -5,7 +5,7 @@ import {logger} from '../../common/util/logger'; import { AggregationParams, AggregationParamsSure, - AggregationParamsWithoutType, + AggregationMetricsWithMethod, } from '../../common/types/manifest'; import {aggregateInputsIntoOne} from '../util/aggregation-helper'; @@ -39,7 +39,7 @@ const getIthElementsFromChildren = (children: any, i: number) => { * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. */ -const temporalAggregation = (node: any, metrics: AggregationMetric) => { +const temporalAggregation = (node: any, metrics: AggregationMetric[]) => { const outputs: PluginParams[] = []; const values: any = Object.values(node.children); @@ -63,7 +63,9 @@ const temporalAggregation = (node: any, metrics: AggregationMetric) => { * 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them. */ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { - const metrics = aggregationParams!.metrics; + const metrics: AggregationMetric[] = aggregationParams!.metrics.map( + metric => ({[metric]: 'none'}) + ); const type = aggregationParams!.type; if (node.children) { @@ -108,12 +110,12 @@ export const aggregate = (tree: any, aggregationParams: AggregationParams) => { * Gets or stores aggregation metrics. */ export const storeAggregationMetrics = ( - aggregationParams?: AggregationParamsWithoutType + aggregationMetrics?: AggregationMetricsWithMethod ) => { - if (aggregationParams?.metrics) { + if (aggregationMetrics) { metricManager.metrics = { ...metricManager.metrics, - ...aggregationParams?.metrics, + ...aggregationMetrics, }; } @@ -146,8 +148,11 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); const aggregationMetricsStorage = storeAggregationMetrics(); - if (aggregationMetricsStorage && `${unitName}` in aggregationMetricsStorage) { - return aggregationMetricsStorage[unitName].method; + if ( + aggregationMetricsStorage && + Object.keys(aggregationMetricsStorage).includes(unitName) + ) { + return aggregationMetricsStorage[unitName]; } memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index f047be117..181e88d15 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -118,7 +118,7 @@ export const initialize = async ( Object.keys(parameters).forEach(key => { storeAggregationMetrics({ - metrics: {[key]: {method: parameters[key]['aggregation-method']}}, + [key]: parameters[key]['aggregation-method'], }); }); From 6eeba6583e891e08c35ea9bb44bf5c860ceef024 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:24:55 +0400 Subject: [PATCH 590/863] fix(util): update aggregation logic --- src/if-run/util/aggregation-helper.ts | 29 +++++---------------------- src/if-run/util/helpers.ts | 7 +++---- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index 87d3e15fc..10b1a0bdd 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -7,40 +7,21 @@ import {AggregationMetric, AggregationResult} from '../types/aggregation'; import {getAggregationMethod} from '../lib/aggregate'; -const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; -const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; +const {MissingAggregationParamError} = ERRORS; +const {METRIC_MISSING} = STRINGS; const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; -/** - * Validates metrics array before applying aggregator. - * If aggregation method is `none`, then throws error. - */ -const checkIfMetricsAreValid = (metrics: AggregationMetric) => { - Object.keys(metrics).forEach(metric => { - const method = metrics[metric].method; - - if (method === 'none') { - throw new InvalidAggregationMethodError( - INVALID_AGGREGATION_METHOD(metric) - ); - } - }); -}; - /** * Aggregates child node level metrics. Validates if metric aggregation type is `none`, then rejects with error. * Appends aggregation additional params to metrics. Otherwise iterates over inputs by aggregating per given `metrics`. */ export const aggregateInputsIntoOne = ( inputs: PluginParams[], - metrics: AggregationMetric, + metrics: AggregationMetric[], isTemporal?: boolean ) => { - checkIfMetricsAreValid(metrics); - const extendedMetrics = [ - ...Object.keys(metrics), - ...AGGREGATION_ADDITIONAL_PARAMS, - ]; + const metricsKeys: string[] = metrics.map(metric => Object.keys(metric)[0]); + const extendedMetrics = [...metricsKeys, ...AGGREGATION_ADDITIONAL_PARAMS]; return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts index da50f22f4..2939022e2 100644 --- a/src/if-run/util/helpers.ts +++ b/src/if-run/util/helpers.ts @@ -62,10 +62,9 @@ export const storeAggregationMethods = ( const {'aggregation-method': aggregationMethod} = parameterMetadata; if (aggregationMethod) { - const metrics = { - [parameterName]: {method: aggregationMethod}, - }; - storeAggregationMetrics({metrics}); + const metrics = {[parameterName]: aggregationMethod}; + + storeAggregationMetrics(metrics); } } ); From 914b8eb8cd1b91f0797d355c9df0aa3f7d92068a Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:26:13 +0400 Subject: [PATCH 591/863] fix(types): update aggregation types --- src/common/types/manifest.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index c28fe7194..1efab523d 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -1,5 +1,7 @@ import {z} from 'zod'; +import {AggregationMethodTypes} from '../../if-run/types/aggregation'; + import {manifestSchema} from '../util/validations'; export type Manifest = z.infer; @@ -9,10 +11,9 @@ export type GlobalPlugins = Manifest['initialize']['plugins']; export type PluginOptions = GlobalPlugins[string]; export type AggregationParams = Manifest['aggregation']; -export type AggregationParamsWithoutType = Omit< - Exclude, - 'type' ->; +export type AggregationMetricsWithMethod = { + [key: string]: AggregationMethodTypes; +}; export type AggregationParamsSure = Extract; From c69949718f867c005371de1d52132be46d32a550 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:27:05 +0400 Subject: [PATCH 592/863] fix(types): update aggregation types --- src/if-run/types/aggregation.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts index a7e895da4..c3b143a1f 100644 --- a/src/if-run/types/aggregation.ts +++ b/src/if-run/types/aggregation.ts @@ -3,7 +3,5 @@ export type AggregationResult = Record; export const AGGREGATION_TYPES = ['horizontal', 'vertical', 'both'] as const; export const AGGREGATION_METHODS = ['sum', 'avg', 'none'] as const; -export type AggregationMetric = Record< - string, - {method: 'sum' | 'avg' | 'none'} ->; +export type AggregationMethodTypes = 'sum' | 'avg' | 'none'; +export type AggregationMetric = Record; From be28ccdadd3e7304e9add7416f48a4e6da87be4e Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:28:49 +0400 Subject: [PATCH 593/863] fix(src): fix adding aggregation metric into storage --- src/if-run/index.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 9b8d86f6c..6d9f61a78 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -12,6 +12,8 @@ import {compute} from './lib/compute'; import {exhaust} from './lib/exhaust'; import {explain} from './lib/explain'; +import {AGGREGATION_METHODS} from './types/aggregation'; + import {parseIfRunProcessArgs} from './util/args'; import {andHandle} from './util/helpers'; @@ -43,7 +45,13 @@ const impactEngine = async () => { const {tree, ...context} = validateManifest(envManifest); if (context.aggregation) { - storeAggregationMetrics({metrics: context.aggregation?.metrics}); + const convertMetrics = context.aggregation?.metrics.map( + (metric: string) => ({ + [metric]: AGGREGATION_METHODS[2], + }) + ); + + storeAggregationMetrics(...convertMetrics); } const pluginStorage = await initialize(context); From 1612a6293e843b2fd7e8bae461f91c8a565c0e50 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:29:44 +0400 Subject: [PATCH 594/863] test(src): update tests accroding to changes --- .../if-run/builtins/time-sync.test.ts | 23 +++++--- src/__tests__/if-run/lib/aggregate.test.ts | 16 ++--- .../if-run/util/aggregation-helper.test.ts | 59 +++++++------------ src/__tests__/if-run/util/helpers.test.ts | 12 +--- 4 files changed, 48 insertions(+), 62 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 314ed06d4..38621e12f 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -7,6 +7,7 @@ import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {TimeSync} from '../../../if-run/builtins/time-sync'; import {STRINGS} from '../../../if-run/config'; +import {AGGREGATION_METHODS} from '../../../if-run/types/aggregation'; Settings.defaultZone = 'utc'; const { @@ -56,16 +57,18 @@ jest.mock('luxon', () => { describe('builtins/time-sync:', () => { beforeAll(() => { const metricStorage: AggregationParams = { - metrics: { - carbon: {method: 'sum'}, - 'cpu/utilization': {method: 'sum'}, - 'time-reserved': {method: 'avg'}, - 'resources-total': {method: 'none'}, - }, + metrics: [ + 'carbon', + 'cpu/utilization', + 'time-reserved', + 'resources-total', + ], type: 'horizontal', }; - - storeAggregationMetrics(metricStorage); + const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ + [metric]: AGGREGATION_METHODS[2], + })); + storeAggregationMetrics(...convertedMetrics); }); describe('time-sync: ', () => { @@ -472,6 +475,7 @@ describe('execute(): ', () => { interval: 1, 'allow-padding': true, }; + storeAggregationMetrics({carbon: 'sum'}); const timeModel = TimeSync(basicConfig, parametersMetadata); @@ -586,6 +590,8 @@ describe('execute(): ', () => { interval: 5, 'allow-padding': true, }; + storeAggregationMetrics({'time-reserved': 'avg'}); + storeAggregationMetrics({'resources-total': 'sum'}); const timeModel = TimeSync(basicConfig, parametersMetadata); @@ -659,6 +665,7 @@ describe('execute(): ', () => { interval: 5, 'allow-padding': true, }; + storeAggregationMetrics({'resources-total': 'none'}); const timeModel = TimeSync(basicConfig, parametersMetadata); diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index 36bbc0d1f..00d9c6d0e 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -6,17 +6,19 @@ import { aggregate, storeAggregationMetrics, } from '../../../if-run/lib/aggregate'; +import {AGGREGATION_METHODS} from '../../../if-run/types/aggregation'; describe('lib/aggregate: ', () => { beforeAll(() => { const metricStorage: AggregationParams = { - metrics: { - carbon: {method: 'sum'}, - }, + metrics: ['carbon'], type: 'horizontal', }; + const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ + [metric]: AGGREGATION_METHODS[2], + })); - storeAggregationMetrics(metricStorage); + storeAggregationMetrics(...convertedMetrics); }); describe('aggregate(): ', () => { @@ -60,7 +62,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: {carbon: {method: 'sum'}}, + metrics: ['carbon'], type: 'horizontal', }); const expectedAggregated = { @@ -108,7 +110,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: {carbon: {method: 'sum'}}, + metrics: ['carbon'], type: 'vertical', }); const expectedOutputs = [ @@ -169,7 +171,7 @@ describe('lib/aggregate: ', () => { }; const aggregatedTree = aggregate(tree, { - metrics: {carbon: {method: 'sum'}}, + metrics: ['carbon'], type: 'both', }); diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index df8a74d9b..f83536f39 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -4,52 +4,33 @@ import {PluginParams} from '@grnsft/if-core/types'; import {AggregationParams} from '../../../common/types/manifest'; import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; -import {AggregationMetric} from '../../../if-run/types/aggregation'; +import { + AGGREGATION_METHODS, + AggregationMetric, +} from '../../../if-run/types/aggregation'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; -const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS; -const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS; +const {MissingAggregationParamError} = ERRORS; +const {METRIC_MISSING} = STRINGS; describe('util/aggregation-helper: ', () => { beforeAll(() => { const metricStorage: AggregationParams = { - metrics: { - carbon: {method: 'sum'}, - 'cpu/number-cores': {method: 'none'}, - 'cpu/utilization': {method: 'sum'}, - }, + metrics: ['carbon', 'cpu/number-cores', 'cpu/utilization'], type: 'horizontal', }; - - storeAggregationMetrics(metricStorage); + const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ + [metric]: AGGREGATION_METHODS[2], + })); + storeAggregationMetrics(...convertedMetrics); }); describe('aggregateInputsIntoOne(): ', () => { - it('throws error if aggregation method is none.', () => { - const inputs: PluginParams[] = []; - const metrics: AggregationMetric = {'cpu/number-cores': {method: 'none'}}; - const isTemporal = false; - - expect.assertions(2); - - try { - aggregateInputsIntoOne(inputs, metrics, isTemporal); - } catch (error) { - expect(error).toBeInstanceOf(InvalidAggregationMethodError); - - if (error instanceof InvalidAggregationMethodError) { - expect(error.message).toEqual( - INVALID_AGGREGATION_METHOD('cpu/number-cores') - ); - } - } - }); - it('throws error if aggregation criteria is not found in input.', () => { const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; - const metrics: AggregationMetric = {'cpu/utilization': {method: 'sum'}}; + const metrics: AggregationMetric[] = [{'cpu/utilization': 'sum'}]; const isTemporal = false; expect.assertions(2); @@ -70,7 +51,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric = {carbon: {method: 'sum'}}; + const metrics: AggregationMetric[] = [{carbon: 'sum'}]; const isTemporal = true; const expectedValue = { @@ -87,7 +68,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric = {carbon: {method: 'sum'}}; + const metrics: AggregationMetric[] = [{carbon: 'sum'}]; const isTemporal = false; const expectedValue = { @@ -99,18 +80,20 @@ describe('util/aggregation-helper: ', () => { it('calculates average of metrics.', () => { const metricStorage: AggregationParams = { - metrics: { - 'cpu/utilization': {method: 'avg'}, - }, + metrics: ['cpu/utilization'], type: 'horizontal', }; + const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ + [metric]: AGGREGATION_METHODS[2], + })); + storeAggregationMetrics(...convertedMetrics); + storeAggregationMetrics({'cpu/utilization': 'avg'}); - storeAggregationMetrics(metricStorage); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, 'cpu/utilization': 10}, {timestamp: '', duration: 10, 'cpu/utilization': 90}, ]; - const metrics: AggregationMetric = {'cpu/utilization': {method: 'avg'}}; + const metrics: AggregationMetric[] = [{'cpu/utilization': 'avg'}]; const isTemporal = false; const expectedValue = { diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts index c694c0a9a..796f6b201 100644 --- a/src/__tests__/if-run/util/helpers.test.ts +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -242,19 +242,13 @@ describe('if-run/util/helpers: ', () => { expect(storeAggregationMetrics).toHaveBeenCalledTimes(3); expect(storeAggregationMetrics).toHaveBeenNthCalledWith(1, { - metrics: { - carbon: {method: 'sum'}, - }, + carbon: 'sum', }); expect(storeAggregationMetrics).toHaveBeenNthCalledWith(2, { - metrics: { - cpu: {method: 'avg'}, - }, + cpu: 'avg', }); expect(storeAggregationMetrics).toHaveBeenNthCalledWith(3, { - metrics: { - carbon: {method: 'none'}, - }, + carbon: 'none', }); }); From 27fce36762d13ecbaafab9233fa91f45ed89f593 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 19:32:39 +0400 Subject: [PATCH 595/863] fix(doc): update aggregation part in the doc --- Refactor-migration-guide.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index e29a80d0e..95283c841 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -199,9 +199,7 @@ The aggregate plugin aggregates data in two ways: first it condenses individual This is a builtin feature of IF, meaning it does not have to be initialized as a plugin. Instead, you just have to include a short config block in the top of the manifest file. There are two pieces of information required: -- `metrics`: which metrics do you want to aggregate? Every metric you provide here must exist in the output array. - - - `method`: the aggregation method for the specied metric +- `metrics`: which metrics do you want to aggregate? Every metric you provide here must exist in the output array and be described in the `parameter-metadata` of the plugin. - `type`: the options are `horizontal`, `vertical` or both. Horizontal aggregation is the type that condenses each time series into a single summary value. Vertical aggregation is aggregated across components. @@ -210,8 +208,7 @@ Here's what the config block should look like: ```yaml aggregation: metrics: - 'carbon': - method: 'sum' + - carbon type: 'both' ``` From 20df97f8a230e1645d8d91edaff30afeb409f374 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 20:17:45 +0400 Subject: [PATCH 596/863] fix(doc): add missing `aggregation-method` --- src/if-run/builtins/sum/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 998c54c11..14ad1c336 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -86,13 +86,16 @@ 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 tree: children: child: From 86f79f1540bd480688579b0f4b646f735d478315 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 7 Aug 2024 20:24:32 +0400 Subject: [PATCH 597/863] fix(builtins): merge `parameter-metdata` if there is harcoded data --- src/if-run/builtins/sci-embodied/index.ts | 67 ++++++++++++----------- src/if-run/builtins/sci/index.ts | 28 ++++++---- src/if-run/builtins/time-sync.ts | 26 +++++---- 3 files changed, 67 insertions(+), 54 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index e8b69cd2b..b304d4ae1 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,6 +1,7 @@ import {z} from 'zod'; import { ExecutePlugin, + ParameterMetadata, PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; @@ -16,37 +17,41 @@ export const SciEmbodied = ( ): ExecutePlugin => { const metadata = { kind: 'execute', - inputs: parametersMetadata?.inputs || { - 'device/emissions-embodied': { - description: 'total embodied emissions of some component', - unit: 'gCO2e', - 'aggregation-method': 'sum', - }, - 'device/expected-lifespan': { - description: 'Total Expected Lifespan of the Component in Seconds', - unit: 'seconds', - 'aggregation-method': 'sum', - }, - 'resources-reserved': { - description: 'resources reserved for an application', - unit: 'count', - 'aggregation-method': 'none', - }, - 'resources-total': { - description: 'total resources available', - unit: 'count', - 'aggregation-method': 'none', - }, - 'vcpus-allocated': { - description: 'number of vcpus allocated to particular resource', - unit: 'count', - 'aggregation-method': 'none', - }, - 'vcpus-total': { - description: 'total number of vcpus available on a particular resource', - unit: 'count', - 'aggregation-method': 'none', - }, + inputs: { + ...({ + 'device/emissions-embodied': { + description: 'total embodied emissions of some component', + unit: 'gCO2e', + 'aggregation-method': 'sum', + }, + 'device/expected-lifespan': { + description: 'Total Expected Lifespan of the Component in Seconds', + unit: 'seconds', + 'aggregation-method': 'sum', + }, + 'resources-reserved': { + description: 'resources reserved for an application', + unit: 'count', + 'aggregation-method': 'none', + }, + 'resources-total': { + description: 'total resources available', + unit: 'count', + 'aggregation-method': 'none', + }, + 'vcpus-allocated': { + description: 'number of vcpus allocated to particular resource', + unit: 'count', + 'aggregation-method': 'none', + }, + 'vcpus-total': { + description: + 'total number of vcpus available on a particular resource', + unit: 'count', + 'aggregation-method': 'none', + }, + } as ParameterMetadata), + ...parametersMetadata?.inputs, }, outputs: parametersMetadata?.outputs || { 'carbon-embodied': { diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 70608fe84..1106f3725 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -5,6 +5,7 @@ import { PluginParams, ConfigParams, PluginParametersMetadata, + ParameterMetadata, } from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; @@ -25,18 +26,21 @@ export const Sci = ( ): ExecutePlugin => { const metadata = { kind: 'execute', - inputs: parametersMetadata?.inputs || { - carbon: { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - 'aggregation-method': 'sum', - }, - 'functional-unit': { - description: - 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', - unit: 'none', - 'aggregation-method': 'sum', - }, + inputs: { + ...({ + carbon: { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + 'aggregation-method': 'sum', + }, + 'functional-unit': { + description: + 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', + unit: 'none', + 'aggregation-method': 'sum', + }, + } as ParameterMetadata), + ...parametersMetadata?.inputs, }, outputs: parametersMetadata?.outputs || { sci: { diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync.ts index e9f4ee1bc..6619c2ff0 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync.ts @@ -10,6 +10,7 @@ import { TimeNormalizerConfig, TimeParams, PluginParametersMetadata, + ParameterMetadata, } from '@grnsft/if-core/types'; import {validate} from '../../common/util/validations'; @@ -57,17 +58,20 @@ export const TimeSync = ( ): ExecutePlugin => { const metadata = { kind: 'execute', - inputs: parametersMetadata?.inputs || { - timestamp: { - description: 'refers to the time of occurrence of the input', - unit: 'RFC3339', - 'aggregation-method': 'none', - }, - duration: { - description: 'refers to the duration of the input', - unit: 'seconds', - 'aggregation-method': 'sum', - }, + inputs: { + ...({ + timestamp: { + description: 'refers to the time of occurrence of the input', + unit: 'RFC3339', + 'aggregation-method': 'none', + }, + duration: { + description: 'refers to the duration of the input', + unit: 'seconds', + 'aggregation-method': 'sum', + }, + } as ParameterMetadata), + ...parametersMetadata?.inputs, }, outputs: parametersMetadata?.outputs, }; From 5729b2b1f80103b0410435b8fe6bb2dbc4ebb7aa Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 11:26:39 +0400 Subject: [PATCH 598/863] fix(config): add `output` flag --- src/if-merge/config/config.ts | 66 ++++++++++++++++++---------------- src/if-merge/config/strings.ts | 2 +- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/if-merge/config/config.ts b/src/if-merge/config/config.ts index d4c3059ad..81ee6baff 100644 --- a/src/if-merge/config/config.ts +++ b/src/if-merge/config/config.ts @@ -7,35 +7,39 @@ import {IFMergeArgs} from '../types/process-args'; const {DISCLAIMER_MESSAGE} = STRINGS; export const CONFIG = { - IF_MERGE: { - ARGS: { - manifests: { - type: String, - multiple: true, - alias: 'm', - description: '[path to the manifests files]', - }, - name: { - type: String, - optional: true, - alias: 'n', - description: '[name of the merged manifest]', - }, - description: { - type: String, - optional: true, - alias: 'd', - description: '[decription of the merged manifest]', - }, - } as unknown as ArgumentConfig, - HELP: { - helpArg: 'help', - headerContentSections: [ - {header: 'Impact Framework', content: 'IF-Merge Helpful keywords:'}, - ], - footerContentSections: [ - {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, - ], - } as ParseOptions, - }, + ARGS: { + manifests: { + type: String, + multiple: true, + alias: 'm', + description: '[path to the manifests files]', + }, + output: { + type: String, + optional: true, + alias: 'o', + description: '[path to the merged output file]', + }, + name: { + type: String, + optional: true, + alias: 'n', + description: '[name of the merged manifest]', + }, + description: { + type: String, + optional: true, + alias: 'd', + description: '[decription of the merged manifest]', + }, + } as unknown as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Merge Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, }; diff --git a/src/if-merge/config/strings.ts b/src/if-merge/config/strings.ts index aa224b0ba..ed3e824fb 100644 --- a/src/if-merge/config/strings.ts +++ b/src/if-merge/config/strings.ts @@ -1,6 +1,6 @@ export const STRINGS = { MERGING: 'Merging...', - SUCCESS_MESSAGE: 'Manifests are merged successfully!', + SUCCESS_MESSAGE: '\nManifests are merged successfully!', MANIFEST_IS_NOT_YAML: (path: string) => `The \`${path}\` is not in yaml format.`, }; From 902a810177fd0b4d0e36a6370644240025f64ed9 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 11:27:43 +0400 Subject: [PATCH 599/863] fix(types): add `output` into IFMergeArgs type --- src/if-merge/types/process-args.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-merge/types/process-args.ts b/src/if-merge/types/process-args.ts index f34b65e8b..8fa28e365 100644 --- a/src/if-merge/types/process-args.ts +++ b/src/if-merge/types/process-args.ts @@ -1,5 +1,6 @@ export interface IFMergeArgs { manifests: string[]; + output?: string; name?: string; description?: string; } From 7efa83702cb5a8fcae606999e382e3088fa61de1 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 11:35:41 +0400 Subject: [PATCH 600/863] fix(util): update logic to print result if the `output` is not provided --- src/if-merge/util/args.ts | 11 ++++++----- src/if-merge/util/helpers.ts | 31 +++++++++---------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/if-merge/util/args.ts b/src/if-merge/util/args.ts index 98e28738f..9aba9d21c 100644 --- a/src/if-merge/util/args.ts +++ b/src/if-merge/util/args.ts @@ -12,7 +12,7 @@ import {IFMergeArgs} from '../types/process-args'; import {CONFIG, STRINGS} from '../config'; const {ParseCliParamsError, InvalidDirectoryError, CliSourceFileError} = ERRORS; -const {IF_MERGE} = CONFIG; +const {ARGS, HELP} = CONFIG; const {MANIFEST_IS_NOT_YAML} = STRINGS; const {MANIFEST_NOT_FOUND, DIRECTORY_NOT_FOUND} = COMMON_STRINGS; @@ -21,7 +21,7 @@ const {MANIFEST_NOT_FOUND, DIRECTORY_NOT_FOUND} = COMMON_STRINGS; */ const validateAndParseIfMergeArgs = () => { try { - return parse(IF_MERGE.ARGS, IF_MERGE.HELP); + return parse(ARGS, HELP); } catch (error) { if (error instanceof Error) { throw new ParseCliParamsError(error.message); @@ -35,7 +35,7 @@ const validateAndParseIfMergeArgs = () => { * Checks if the `manifests` command is provided and they are valid manifests files or a folder. */ export const parseIfMergeArgs = async () => { - const {manifests, name, description} = validateAndParseIfMergeArgs(); + const {manifests, output, name, description} = validateAndParseIfMergeArgs(); const manifestsWithFullPath = []; @@ -45,7 +45,7 @@ export const parseIfMergeArgs = async () => { throw new InvalidDirectoryError(DIRECTORY_NOT_FOUND); } - return {manifests, name, description}; + return {manifests, output, name, description}; } for await (const manifest of manifests) { @@ -65,5 +65,6 @@ export const parseIfMergeArgs = async () => { manifestsWithFullPath.push(response); } } - return {manifests: manifestsWithFullPath, name, description}; + + return {manifests: manifestsWithFullPath, output, name, description}; }; diff --git a/src/if-merge/util/helpers.ts b/src/if-merge/util/helpers.ts index 362791a6f..bd2d46d36 100644 --- a/src/if-merge/util/helpers.ts +++ b/src/if-merge/util/helpers.ts @@ -1,24 +1,19 @@ -import * as path from 'path'; - import {getFileName, getYamlFiles} from '../../common/util/fs'; import {Context} from '../../common/types/manifest'; import {load} from '../../common/lib/load'; -import {ExportYaml} from '../../if-run/builtins/export-yaml'; - +import {exhaust} from '../../if-run/lib/exhaust'; import {IFMergeArgs} from '../types/process-args'; /** * Merges the given manifests in the one file. */ export const mergeManifests = async (mergeArgs: IFMergeArgs) => { - const {manifests: commandManifests, name, description} = mergeArgs; + const {manifests: commandManifests, output, name, description} = mergeArgs; let manifests = commandManifests; - let manifestPath = process.env.CURRENT_DIR || process.cwd(); if (commandManifests.length === 1) { manifests = await getYamlFiles(commandManifests[0]); - manifestPath = commandManifests[0]; } const context = { name: name || 'if-merge', @@ -27,9 +22,8 @@ export const mergeManifests = async (mergeArgs: IFMergeArgs) => { initialize: {plugins: {}}, }; const tree = await mergeManifestsData(manifests, context); - const outputPath = getOutputPath(name, manifestPath); - await saveMergedManifest(tree, context, outputPath); + await saveMergedManifest(tree, context, output); }; /** @@ -58,24 +52,17 @@ const mergeManifestsData = async (manifests: string[], context: Context) => { return tree; }; -/** - * Gets output path. - */ -const getOutputPath = (name: string | undefined, manifestPath: string) => { - const manifestName = `${(name || 'merged-manifest').replace(' ', '-')}.yaml`; - - return path.join(manifestPath, manifestName); -}; - /** * Saves the merged manifest in the `merged-manifest.yaml` file. */ const saveMergedManifest = async ( tree: any, context: Context, - outputPath: string + outputPath: string | undefined ) => { - const exportYaml = ExportYaml(); - - await exportYaml.execute(tree, context, outputPath); + const output = { + outputPath, + noOutput: false, + }; + await exhaust(tree, context, output); }; From ec1693b97db312193c4b68f7fc657f7ac5bde01e Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 11:37:28 +0400 Subject: [PATCH 601/863] test(util): update tests --- src/__tests__/if-merge/util/helpers.test.ts | 34 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index db52a2a84..1f4c0609f 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -39,9 +39,9 @@ jest.mock('../../../if-run/builtins/export-yaml', () => ({ if (process.env.CONTEXT !== 'default-name-description') { expectedContext.name = 'mock name'; expectedContext.description = 'mock description'; - expect(outputPath).toBe('mock-dir/mock-name.yaml'); + expect(outputPath).toBe('mock-outputPath'); } else { - expect(outputPath).toBe('mock-dir/merged-manifest.yaml'); + expect(outputPath).toBe('mock-outputPath'); } expect(context).toEqual(expectedContext); @@ -50,9 +50,16 @@ jest.mock('../../../if-run/builtins/export-yaml', () => ({ })); describe('if-merge/util/helpers: ', () => { + const consopleSpy = jest.spyOn(global.console, 'log'); + + beforeEach(() => { + consopleSpy.mockReset(); + }); + describe('mergeManifests(): ', () => { const mockCommandArgs = { manifests: ['manifest1.yaml', 'manifest2.yaml'], + output: 'mock-outputPath', name: 'mock name', description: 'mock description', }; @@ -128,9 +135,27 @@ describe('if-merge/util/helpers: ', () => { expect(load).toHaveBeenCalledTimes(2); }); + it('successfully prints merged manifests when the `output` is not provided.', async () => { + (getFileName as jest.Mock).mockImplementation(file => + file.replace('.yaml', '') + ); + (load as jest.Mock).mockResolvedValue({rawManifest: mockRawManifest}); + + const mockCommandArgs = { + manifests: ['manifest1.yaml', 'manifest2.yaml'], + name: 'mock name', + description: 'mock description', + }; + await mergeManifests(mockCommandArgs); + + expect.assertions(1); + expect(consopleSpy).toHaveBeenCalledTimes(1); + }); + it('gets YAML files when there is only one manifest.', async () => { const singleManifestArgs = { manifests: ['mock-dir'], + output: 'mock-outputPath', name: 'mock name', description: 'mock description', }; @@ -153,7 +178,10 @@ describe('if-merge/util/helpers: ', () => { it('uses default values for name and description if not provided.', async () => { process.env.CONTEXT = 'default-name-description'; - const defaultArgs = {manifests: ['manifest1.yaml', 'manifest2.yaml']}; + const defaultArgs = { + manifests: ['manifest1.yaml', 'manifest2.yaml'], + output: 'mock-outputPath', + }; (getFileName as jest.Mock).mockImplementation(file => file.replace('.yaml', '') From 1b8d5f1bf3b9b14c5e56d0471def0de17172f4ed Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 14:22:45 +0400 Subject: [PATCH 602/863] Update src/if-run/config/strings.ts Co-authored-by: Manushak Keramyan Signed-off-by: Narek Hovhannisyan --- src/if-run/config/strings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index deb7d0052..f09dc349e 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -58,7 +58,7 @@ Note that for the '--output' option you also need to define the output type in y PREPARING_OUTPUT_DATA: 'Preparing output data', EXPORTING_TO_YAML_FILE: (savepath: string) => `Exporting to yaml file: ${savepath}`, - EMPTY_PIPELINE: `You've using an old style manifest. Please update for phased execution. More information can be found here: + EMPTY_PIPELINE: `You're using an old style manifest. Please update for phased execution. More information can be found here: https://if.greensoftware.foundation/major-concepts/manifest-file`, /** Exhaust messages */ OUTPUT_REQUIRED: From dd24689b7949eb7c327eae2c9cd15cbd1b606b91 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 14:49:32 +0400 Subject: [PATCH 603/863] fix(util): compose unique name for tree children --- src/if-merge/util/helpers.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/if-merge/util/helpers.ts b/src/if-merge/util/helpers.ts index bd2d46d36..db713974d 100644 --- a/src/if-merge/util/helpers.ts +++ b/src/if-merge/util/helpers.ts @@ -1,3 +1,5 @@ +import * as path from 'path'; + import {getFileName, getYamlFiles} from '../../common/util/fs'; import {Context} from '../../common/types/manifest'; import {load} from '../../common/lib/load'; @@ -35,6 +37,8 @@ const mergeManifestsData = async (manifests: string[], context: Context) => { for await (const manifest of manifests) { const manifestName = getFileName(manifest); const {rawManifest} = await load(manifest); + const parentDir = path.basename(path.dirname(manifest)); + const uniqueName = `${parentDir}-${manifestName}`; context.tags = Object.assign({}, context.tags, rawManifest.tags); context.initialize.plugins = { @@ -43,7 +47,7 @@ const mergeManifestsData = async (manifests: string[], context: Context) => { }; Object.keys(rawManifest.tree.children).forEach(child => { - tree.children[`${child}-${manifestName}`] = { + tree.children[`${child}-${uniqueName}`] = { ...rawManifest.tree.children[child], }; }); From f2fe4893603f9d03dc62afaed6da1ba479900bd7 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 17:01:21 +0400 Subject: [PATCH 604/863] fix(builtins): remove wrong hard coded parameter metadata --- src/if-run/builtins/coefficient/index.ts | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 13764bf0c..177eeece3 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -20,20 +20,8 @@ export const Coefficient = ( ): ExecutePlugin => { const metadata = { kind: 'execute', - inputs: parametersMetadata?.inputs || { - carbon: { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - 'aggregation-method': 'sum', - }, - }, - outputs: parametersMetadata?.outputs || { - 'carbon-product': { - description: 'a product of cabon property and the coefficient', - unit: 'gCO2e', - 'aggregation-method': 'sum', - }, - }, + inputs: parametersMetadata?.inputs, + outputs: parametersMetadata?.outputs, }; /** From 29f29163687d53ae037d95493a742108980af089 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:14:23 +0400 Subject: [PATCH 605/863] fix(lib): do more advanced checking on pipeline --- src/if-run/lib/compute.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 27426bbc6..710e15373 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -78,7 +78,13 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { inputStorage = mergeDefaults(inputStorage, defaults); const pipelineCopy = structuredClone(pipeline) || {}; - if (Object.keys(pipelineCopy).length === 0) { + /** Checks if pipeline is not an array or empty object. */ + if ( + Array.isArray(pipelineCopy) || + (typeof pipelineCopy === 'object' && + pipelineCopy !== null && + Object.keys(pipelineCopy).length === 0) + ) { logger.warn(EMPTY_PIPELINE); } From 340c07edb8b5956abb6d3279b1e46f2965f9f7af Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:46:58 +0400 Subject: [PATCH 606/863] feat(builtins): move time-sync to appropriate folder --- src/if-run/builtins/{ => time-sync}/README.md | 368 ------------------ .../{time-sync.ts => time-sync/index.ts} | 19 +- 2 files changed, 14 insertions(+), 373 deletions(-) rename src/if-run/builtins/{ => time-sync}/README.md (50%) rename src/if-run/builtins/{time-sync.ts => time-sync/index.ts} (97%) diff --git a/src/if-run/builtins/README.md b/src/if-run/builtins/time-sync/README.md similarity index 50% rename from src/if-run/builtins/README.md rename to src/if-run/builtins/time-sync/README.md index e05110887..335866546 100644 --- a/src/if-run/builtins/README.md +++ b/src/if-run/builtins/time-sync/README.md @@ -1,12 +1,3 @@ -# IF builtins - -There are three built-in features of IF: - -- time-sync -- CSV exporter - -On this page, you can find the documentation for each of these three builtins. - ## Time-sync Time sync standardizes the start time, end time and temporal resolution of all output data across an entire tree. @@ -274,362 +265,3 @@ tree: energy: 200 requests: 380 ``` - -## CSV Exporter - -IF supports exporting data to CSV files. This provides users with a data format that enables visualization and data analysis using standard data analysis tools. - -### CLI command - -Then, you must select the metric you want to export to CSV. The name of that metric must be added to the savepath provided to the `--output` command in the CLI, after a hashtag. - -For example, to export the `carbon` data from your tree to a CSV file: - -```sh -if-run --manifest example.yml --output example#carbon -``` - -This will save a CSV file called `example.csv`. The contents will look similar to the following: - -| | | | | | -| ---------------------------------------------- | ---------------- | ---------------------------- | ---------------------------- | ---------------------------- | -| **Path** | **Aggregated** | **2024-03-05T00:00:00.000Z** | **2024-03-05T00:05:00.000Z** | **2024-03-05T00:10:00.000Z** | -| tree.carbon | 425.289232008725 | 17.9269877157543 | 8.9024388783018 | 45.6021901509012 | -| tree.children.westus3.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | -| tree.children.westus3.children.server-1.carbon | 104.696836722878 | 3.59973803197887 | 3.47438149032372 | 6.91318436533634 | -| tree.children.france.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | -| tree.children.france.children.server-2.carbon | 320.592395285847 | 14.3272496837754 | 5.42805738797808 | 38.6890057855649 | - -### Comparing CSV to Yaml - -The CSV above is generated from the following yaml. The `carbon` metric is extracted and added to the CSV. Otherwise, the CSV is an exact representation of the following yaml tree. You can see that the CSV representation is _much_ easier to understand than the full yaml tree: - -```yaml -tree: - pipeline: - observe: - - mock-observations - regroup: - - cloud/region - - name - compute: - - cloud-metadata - - time-sync - - watttime - - teads-curve - - operational-carbon - defaults: - grid/carbon-intensity: 500 - children: - westus3: - children: - server-1: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 66 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 4 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 54 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 19 - grid/carbon-intensity: 500 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 65.78 - grid/carbon-intensity: 369.4947514218548 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.018934842060004835 - carbon: 6.996324760173567 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 3.986666666666667 - grid/carbon-intensity: 369.38452029076234 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.004545546617763956 - carbon: 1.6790545568620359 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 53.82 - grid/carbon-intensity: 372.58122309244305 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.017357893372978016 - carbon: 6.467225143212361 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-1 - cloud/instance-type: Standard_E64_v3 - cloud/region: westus3 - cloud/vendor: azure - cpu/utilization: 18.936666666666667 - grid/carbon-intensity: 434.20042537311633 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: CAISO - cloud/region-em-zone-id: US-CAL-CISO - cloud/region-wt-id: CAISO_NORTH - cloud/region-location: US West (N. California) - cloud/region-geolocation: 34.0497,-118.1326 - geolocation: 34.0497,-118.1326 - cpu/energy: 0.010385485956624245 - carbon: 4.5093824200727735 - aggregated: - carbon: 19.651986880320734 - outputs: - - carbon: 6.996324760173567 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 1.6790545568620359 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 6.467225143212361 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 4.5093824200727735 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 19.651986880320734 - france: - children: - server-2: - inputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 15 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 78 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 16 - grid/carbon-intensity: 500 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 6 - grid/carbon-intensity: 500 - outputs: - - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 14.95 - grid/carbon-intensity: 1719.1647205176753 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.00905914075141129 - carbon: 15.574155178030272 - - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 77.74 - grid/carbon-intensity: 1719.0544893865829 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.020379266251888902 - carbon: 35.0330691407141 - - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 15.946666666666667 - grid/carbon-intensity: 1718.8707708347622 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.009405866514354337 - carbon: 16.16746902589712 - - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - name: server-2 - cloud/instance-type: Standard_E64_v3 - cloud/region: france - cloud/vendor: azure - cpu/utilization: 5.98 - grid/carbon-intensity: 1718.6686804277592 - vcpus-allocated: 64 - vcpus-total: 64 - memory-available: 432 - physical-processor: >- - Intel® Xeon® Platinum 8370C,Intel® Xeon® Platinum 8272CL,Intel® - Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-2673 v4 2.3 GHz - cpu/thermal-design-power: 269.1 - cloud/region-cfe: France - cloud/region-em-zone-id: FR - cloud/region-wt-id: FR - cloud/region-location: Paris - cloud/region-geolocation: 48.8567,2.3522 - geolocation: 48.8567,2.3522 - cpu/energy: 0.0054492484351820105 - carbon: 9.365452617417297 - aggregated: - carbon: 76.1401459620588 - outputs: - - carbon: 15.574155178030272 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 35.0330691407141 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 16.16746902589712 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 9.365452617417297 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 76.1401459620588 - outputs: - - carbon: 22.57047993820384 - timestamp: '2024-03-05T00:00:00.000Z' - duration: 300 - - carbon: 36.71212369757613 - timestamp: '2024-03-05T00:05:00.000Z' - duration: 300 - - carbon: 22.63469416910948 - timestamp: '2024-03-05T00:10:00.000Z' - duration: 300 - - carbon: 13.87483503749007 - timestamp: '2024-03-05T00:15:00.000Z' - duration: 300 - aggregated: - carbon: 95.79213284237952 -``` - -### CSV and aggregation - -The CSV representation of the output data is helpful for intuiting how the aggregation procedure works. What we refer to as "horizontal" aggregation is really an aggregation of the _rows_ of the CSV. You can replicate the IF aggregation function by summing the cells in each row of the CSV. Similarly, what we refer to as "vertical" aggregation can be replicated by summing the _columns_ in the CSV representation (this is not _exactly_ accurate because you have to skip summing both parent nodes and their children, both of which are represented in the CSV, but it is true conceptually). diff --git a/src/if-run/builtins/time-sync.ts b/src/if-run/builtins/time-sync/index.ts similarity index 97% rename from src/if-run/builtins/time-sync.ts rename to src/if-run/builtins/time-sync/index.ts index e9f4ee1bc..ad46e8eba 100644 --- a/src/if-run/builtins/time-sync.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -12,10 +12,10 @@ import { PluginParametersMetadata, } from '@grnsft/if-core/types'; -import {validate} from '../../common/util/validations'; +import {validate} from '../../../common/util/validations'; -import {STRINGS} from '../config'; -import {getAggregationMethod} from '../lib/aggregate'; +import {STRINGS} from '../../config'; +import {getAggregationMethod} from '../../lib/aggregate'; Settings.defaultZone = 'utc'; @@ -346,8 +346,7 @@ export const TimeSync = ( const metrics = Object.keys(input); metrics.forEach(metric => { - const method = getAggregationMethod(metric); - acc[metric] = acc[metric] ?? 0; + let method = getAggregationMethod(metric); if (metric === 'timestamp') { acc[metric] = inputs[0][metric]; @@ -355,6 +354,16 @@ export const TimeSync = ( return; } + if (metric === 'duration') { + method = 'sum'; + } + + if (!method) { + return; + } + + acc[metric] = acc[metric] ?? 0; + if (method === 'sum') { acc[metric] += input[metric]; From 42d6a77b0b95fa4ffef5c08530e8857d3f957269 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:49:57 +0400 Subject: [PATCH 607/863] feat(util): omit aggregation param if method is not found --- src/if-run/util/aggregation-helper.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index 10b1a0bdd..e8fe63de5 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -35,12 +35,18 @@ export const aggregateInputsIntoOne = ( acc[metric] = input[metric]; } } else { + const method = getAggregationMethod(metric); + + if (!method) { + return acc; + } + acc[metric] = acc[metric] ?? 0; acc[metric] += parseFloat(input[metric]); /** Checks for the last iteration. */ if (index === inputs.length - 1) { - if (getAggregationMethod(metric) === 'avg') { + if (method === 'avg') { acc[metric] /= inputs.length; } } From 2c2feff8589a9cdc427d02e30b82197b7f5dbfd7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:50:28 +0400 Subject: [PATCH 608/863] feat(lib): return undefined if no aggregation method is present --- src/if-run/lib/aggregate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index b80d0048a..508d7df25 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -157,5 +157,5 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - return 'sum'; + return undefined; }; From fdfc3f58c5619d1e0a94251da3ca480bf0c590ee Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:51:26 +0400 Subject: [PATCH 609/863] feat(config): update omitting message --- src/if-run/config/strings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index e5e6e449b..da86657b8 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -28,7 +28,7 @@ export const STRINGS = { INVALID_EXHAUST_PLUGIN: (pluginName: string) => `Invalid exhaust plugin: ${pluginName}.`, UNKNOWN_PARAM: (name: string) => - `Unknown parameter: ${name}. Using 'sum' aggregation method.`, + `Unknown parameter: ${name}. Omitting from the output.`, NOT_INITALIZED_PLUGIN: (name: string) => `Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`, NO_OUTPUT: ` From 125c0f06dc222488bdc731f76a32b9cf1a9c0be7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:52:13 +0400 Subject: [PATCH 610/863] test(builtins): fix time sync --- src/__tests__/if-run/builtins/time-sync.test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 38621e12f..a9fa13cd1 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -456,12 +456,10 @@ describe('execute(): ', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 1, - 'cpu/utilization': 10, }, { timestamp: '2023-12-12T00:00:01.000Z', duration: 1, - 'cpu/utilization': 10, }, ]; @@ -566,17 +564,14 @@ describe('execute(): ', () => { }, ]); - /**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, }, ]; From fa404ad5df142c58faaad72ce70b0bd034601bc9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 18:53:26 +0400 Subject: [PATCH 611/863] feat(manifests): update pipeline with aggregate --- .../pipelines/pipeline-with-aggregate.yml | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index 184820228..6f7822ad7 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -158,33 +158,6 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: none - time-reserved: - unit: seconds - description: time reserved for a component - aggregation-method: avg - outputs: - synced-time: - unit: none - description: Synced time - aggregation-method: none tree: children: child-1: From 50dfb9e1f19beb5f189125849634487ab38bd61c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 8 Aug 2024 20:15:29 +0400 Subject: [PATCH 612/863] fix(manifests): remove groupBy from pipeline --- .../outputs-if-diff/pipeline-with-mocks.yaml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index 77496bf23..c86d6fec1 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -261,20 +261,6 @@ initialize: unit: none description: Synced time aggregation-method: none - group-by: - path: builtin - method: GroupBy - parameter-metadata: - inputs: - group: - unit: none - description: Group by fields - aggregation-method: none - outputs: - grouped-data: - unit: none - description: Grouped data - aggregation-method: none execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node @@ -327,7 +313,7 @@ tree: - mock-observations regroup: - cloud/region - - instance-type + - cloud/instance-type compute: - interpolate - cpu-factor-to-wattage @@ -681,7 +667,7 @@ tree: - mock-observations regroup: - cloud/region - - instance-type + - cloud/instance-type compute: - interpolate - cpu-factor-to-wattage From 3f439eabbe757143a3b3fe8533bdb0cf3243962a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 8 Aug 2024 21:05:36 +0400 Subject: [PATCH 613/863] fix(manifests): update outputs --- manifests/outputs/bugs/aggregation-error-wrong-metric.yaml | 3 +-- manifests/outputs/builtins/time-sync/success.yaml | 6 ++++++ manifests/outputs/features/failure-invalid-regroup.yaml | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index 92f85c0d7..ed4c00385 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -132,8 +132,7 @@ execution: - winston@3.11.0 - zod@3.22.4 error: >- - MissingAggregationParamError: Aggregation metric dummy-param is not found in - inputs[0]. + MissingInputDataError: `functional-unit` value is missing from input data or it is not a positive integer tree: children: child-1: diff --git a/manifests/outputs/builtins/time-sync/success.yaml b/manifests/outputs/builtins/time-sync/success.yaml index 3ed64a0e3..7b1d6bbb8 100644 --- a/manifests/outputs/builtins/time-sync/success.yaml +++ b/manifests/outputs/builtins/time-sync/success.yaml @@ -11,6 +11,12 @@ initialize: end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true + parameter-metadata: + outputs: + energy-cpu: + unit: KWH + description: energy + aggregation-method: sum execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/features/failure-invalid-regroup.yaml b/manifests/outputs/features/failure-invalid-regroup.yaml index b3f3e722c..2a39ac9c8 100644 --- a/manifests/outputs/features/failure-invalid-regroup.yaml +++ b/manifests/outputs/features/failure-invalid-regroup.yaml @@ -48,8 +48,7 @@ execution: - winston@3.11.0 - zod@3.23.8 error: >- - InputValidationError: "groups" parameter is expected array, received string. - Error code: invalid_type. + InputValidationError: "regroup" parameter is not an array or should contain at least one key. Error code: invalid_type. tree: children: my-app: From e03b42c1e640fd66adf4a9dcb5e082153e2fbf59 Mon Sep 17 00:00:00 2001 From: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:46:31 +0100 Subject: [PATCH 614/863] Update index.ts Signed-off-by: Joseph Cook <33655003+jmcook1186@users.noreply.github.com> --- src/if-run/builtins/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-run/builtins/index.ts b/src/if-run/builtins/index.ts index 736e38d8d..774533baf 100644 --- a/src/if-run/builtins/index.ts +++ b/src/if-run/builtins/index.ts @@ -14,4 +14,3 @@ export {Regex} from './regex'; export {Copy} from './copy-param'; export {TimeConverter} from './time-converter'; export {TimeSync} from './time-sync'; - From 523f94fa472d5f87ea124651f9aabffee9e18bf4 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 9 Aug 2024 13:18:03 +0400 Subject: [PATCH 615/863] fix(lib): add explain logic into compute phase --- src/if-run/lib/compute.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 710e15373..b4e0371d9 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -145,6 +145,14 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { if (isExecute(plugin)) { inputStorage = await plugin.execute(inputStorage, nodeConfig); node.outputs = inputStorage; + + if (params.context.explainer) { + addExplainData({ + pluginName, + metadata: plugin.metadata, + pluginData: params.context.initialize!.plugins[pluginName], + }); + } debugLogger.setExecutingPluginName(); } } From feefc60bb6b9dc2b0765b422180c3d162fe4f1f9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 9 Aug 2024 13:24:45 +0400 Subject: [PATCH 616/863] fix(lib): do not append outputs on observe --- src/if-run/lib/compute.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 710e15373..8d7568bbf 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -108,8 +108,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { pluginData: params.context.initialize!.plugins[pluginName], }); } - - node.outputs = inputStorage; } } } From fa379a51627bc97aead66d96d4ea4b0eadf1ca05 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 16:43:17 +0400 Subject: [PATCH 617/863] 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 618/863] 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 619/863] 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 620/863] 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 621/863] 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 622/863] 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, }, ]); From 86083c1f224ff73b828443ebdddee26ff81437dd Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 18:06:57 +0400 Subject: [PATCH 623/863] fix(src): get back config and add todo comment to remove after some time --- src/if-run/lib/compute.ts | 9 +++++++-- src/if-run/types/compute.ts | 9 +++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index ff882d887..51bd3e2ad 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -62,6 +62,7 @@ const mergeDefaults = ( */ const computeNode = async (node: Node, params: ComputeParams): Promise => { const pipeline = node.pipeline || (params.pipeline as PhasedPipeline); + const config = node.config || params.config; const defaults = node.defaults || params.defaults; const noFlags = !params.observe && !params.regroup && !params.compute; @@ -72,6 +73,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ...params, pipeline, defaults, + config, }); } @@ -86,9 +88,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { while (pipelineCopy.observe.length !== 0) { const pluginName = pipelineCopy.observe.shift() as string; const plugin = params.pluginStorage.get(pluginName); + const nodeConfig = config && config[pluginName]; if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage); + inputStorage = await plugin.execute(inputStorage, nodeConfig); node.inputs = inputStorage; if (params.context.explainer) { @@ -119,6 +122,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { regroup: undefined, }, defaults, + config, }); } @@ -129,9 +133,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { while (pipelineCopy.compute.length !== 0) { const pluginName = pipelineCopy.compute.shift() as string; const plugin = params.pluginStorage.get(pluginName); + const nodeConfig = config && config[pluginName]; if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage); + inputStorage = await plugin.execute(inputStorage, nodeConfig); node.outputs = inputStorage; debugLogger.setExecutingPluginName(); } diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index 53c6bdb78..56346d390 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -3,6 +3,13 @@ import {PluginParams} from '@grnsft/if-core/types'; import {PluginStorageInterface} from './plugin-storage'; import {Context} from '../../common/types/manifest'; +/** + * @todo: remove NodeConfig after some period + */ +export type NodeConfig = { + [key: string]: Record; +}; + export type PhasedPipeline = { observe?: string[]; regroup?: string[]; @@ -13,6 +20,7 @@ export type ComputeParams = { pluginStorage: PluginStorageInterface; context: Context; pipeline?: PhasedPipeline; + config?: NodeConfig; defaults?: PluginParams; observe?: Boolean; regroup?: Boolean; @@ -22,6 +30,7 @@ export type ComputeParams = { export type Node = { children?: any; pipeline?: PhasedPipeline; + config?: NodeConfig; defaults?: PluginParams; inputs?: PluginParams[]; outputs?: PluginParams[]; From 3566ab1fb82e19153d773104a734d3e51e4ac9cf Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 19:50:37 +0400 Subject: [PATCH 624/863] fix(util): rename `global-config` to config in the manifest schema --- src/common/util/validations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 5cdbec5db..20d1f3952 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -81,7 +81,7 @@ export const manifestSchema = z.object({ .object({ path: z.string(), method: z.string(), - 'global-config': z.record(z.string(), z.any()).optional(), + config: z.record(z.string(), z.any()).optional(), 'parameter-metadata': parameterMetadataSchema, }) .optional() From 09c855ea436bbd5154b532a8ea608c3536f529b8 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 19:53:04 +0400 Subject: [PATCH 625/863] fix(config): rename MISSING_GLOBAL_CONFIG to MISSING_CONFIG --- src/if-run/config/strings.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index b8f639450..92e36712c 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -63,8 +63,7 @@ https://if.greensoftware.foundation/major-concepts/manifest-file`, OUTPUT_REQUIRED: 'Output path is required, please make sure output is configured properly.', /** Plugins messages */ - INVALID_NAME: - '`name` global config parameter is empty or contains all spaces', + INVALID_NAME: '`name` config parameter is empty or contains all spaces', START_LOWER_END: '`start-time` should be lower than `end-time`', TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, @@ -84,7 +83,7 @@ https://if.greensoftware.foundation/major-concepts/manifest-file`, SCI_MISSING_FN_UNIT: (functionalUnit: string) => `'carbon' and ${functionalUnit} should be present in your input data.`, MISSING_FUNCTIONAL_UNIT_CONFIG: - '`functional-unit` should be provided in your global config', + '`functional-unit` should be provided in your config', MISSING_FUNCTIONAL_UNIT_INPUT: '`functional-unit` value is missing from input data or it is not a positive integer', REGEX_MISMATCH: (input: any, match: string) => @@ -106,7 +105,7 @@ ${message}`, ${error}`, ZERO_DIVISION: (moduleName: string, index: number) => `-- SKIPPING -- DivisionByZero: you are attempting to divide by zero in ${moduleName} plugin : inputs[${index}]\n`, - MISSING_GLOBAL_CONFIG: 'Global config is not provided.', + MISSING_CONFIG: 'Config is not provided.', MISSING_INPUT_DATA: (param: string) => `${param} is missing from the input array, or has nullish value.`, CONFIG_WARN: (plugins: string, isMore: boolean) => @@ -114,5 +113,5 @@ ${error}`, isMore ? 's' : '' }. IF no longer supports node-level config. \`${plugins}\` plugin${ isMore ? 's' : '' - } should be refactored to accept all its config from global config or input data.`, + } should be refactored to accept all its config from config or input data.`, }; From 7bdc8850426594a727274572ceba18d3f7b0ef5f Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 19:54:10 +0400 Subject: [PATCH 626/863] fix(lib): rename `global-config` to config --- src/if-run/lib/initialize.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 181e88d15..6c404e227 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -75,7 +75,7 @@ const handModule = (method: string, pluginPath: string) => { }; /** - * Initializes plugin with global config. + * Initializes plugin with config. */ const initPlugin = async ( initPluginParams: PluginOptions @@ -83,7 +83,7 @@ const initPlugin = async ( const { method, path, - 'global-config': globalConfig, + config: config, 'parameter-metadata': parameterMetadata, } = initPluginParams!; @@ -99,7 +99,7 @@ const initPlugin = async ( const plugin = await handModule(method, path); - return plugin(globalConfig, parameterMetadata); + return plugin(config, parameterMetadata); }; /** From cea711a2d4add8756725ccf5ad897a62fcff4cc4 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 19:58:25 +0400 Subject: [PATCH 627/863] fix(builtins): rename `global-config` to config in plugins --- src/if-run/builtins/coefficient/index.ts | 21 ++++----- src/if-run/builtins/copy-param/index.ts | 21 ++++----- src/if-run/builtins/csv-lookup/index.ts | 23 +++++----- src/if-run/builtins/divide/index.ts | 16 +++---- src/if-run/builtins/exponent/index.ts | 15 +++---- src/if-run/builtins/interpolation/index.ts | 43 ++++++++----------- .../helpers/common-generator.ts | 4 +- .../helpers/rand-int-generator.ts | 4 +- .../builtins/mock-observations/index.ts | 10 ++--- src/if-run/builtins/multiply/index.ts | 15 +++---- src/if-run/builtins/regex/index.ts | 16 +++---- src/if-run/builtins/sci/index.ts | 8 ++-- src/if-run/builtins/shell/index.ts | 4 +- src/if-run/builtins/subtract/index.ts | 15 +++---- src/if-run/builtins/sum/index.ts | 21 ++++----- src/if-run/builtins/time-converter/index.ts | 29 ++++++------- src/if-run/builtins/time-sync/index.ts | 12 +++--- 17 files changed, 122 insertions(+), 155 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 177eeece3..d237c9a91 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -12,10 +12,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; export const Coefficient = ( - globalConfig: CoefficientConfig, + config: CoefficientConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -28,7 +28,7 @@ export const Coefficient = ( * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const inputParameter = safeGlobalConfig['input-parameter']; const outputParameter = safeGlobalConfig['output-parameter']; const coefficient = safeGlobalConfig['coefficient']; @@ -66,23 +66,20 @@ export const Coefficient = ( ) => input[inputParameter] * coefficient; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } - const globalConfigSchema = z.object({ + const configSchema = z.object({ coefficient: z.number(), 'input-parameter': z.string().min(1), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; return { diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 7f10bf696..af38b6e7b 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -10,14 +10,14 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_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, + config: Record, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -27,23 +27,20 @@ export const Copy = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } - const globalConfigSchema = z.object({ + const configSchema = z.object({ 'keep-existing': z.boolean(), from: z.string().min(1), to: z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; /** @@ -70,7 +67,7 @@ export const Copy = ( }; const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const keepExisting = safeGlobalConfig['keep-existing'] === true; const from = safeGlobalConfig['from']; const to = safeGlobalConfig['to']; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index e227eaadf..f412a1240 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -20,7 +20,7 @@ const { FILE_READ_FAILED, MISSING_CSV_COLUMN, NO_QUERY_DATA, - MISSING_GLOBAL_CONFIG, + MISSING_CONFIG, } = STRINGS; const { @@ -33,7 +33,7 @@ const { } = ERRORS; export const CSVLookup = ( - globalConfig: any, + config: any, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -191,13 +191,13 @@ export const CSVLookup = ( }; /** - * 1. Validates global config. + * 1. Validates config. * 2. Tries to retrieve given file (with url or local path). * 3. Parses given CSV. * 4. Filters requested information from CSV. */ const execute = async (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const {filepath, query, output} = safeGlobalConfig; const file = await retrieveFile(filepath); @@ -227,14 +227,14 @@ export const CSVLookup = ( }; /** - * Checks for `filepath`, `query` and `output` fields in global config. + * Checks for `filepath`, `query` and `output` fields in config. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } - const globalConfigSchema = z.object({ + const configSchema = z.object({ filepath: z.string(), query: z.record(z.string(), z.string()), output: z @@ -243,10 +243,7 @@ export const CSVLookup = ( .or(z.array(z.array(z.string()))), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; return { diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 3d09c130c..31ef613e5 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -12,10 +12,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; +const {MISSING_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; export const Divide = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -28,7 +28,7 @@ export const Divide = ( * Calculate the division of each input parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const {numerator, denominator, output} = safeGlobalConfig; return inputs.map((input, index) => { @@ -46,11 +46,11 @@ export const Divide = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } const schema = z.object({ @@ -59,7 +59,7 @@ export const Divide = ( output: z.string(), }); - return validate>(schema, globalConfig); + return validate>(schema, config); }; /** diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index a821c3a14..aef2faead 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -9,7 +9,7 @@ import { import {validate} from '../../../common/util/validations'; export const Exponent = ( - globalConfig: ExponentConfig, + config: ExponentConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -19,19 +19,16 @@ export const Exponent = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ + const validateConfig = () => { + const configSchema = z.object({ 'input-parameter': z.string().min(1), exponent: z.number(), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; /** @@ -55,7 +52,7 @@ export const Exponent = ( 'input-parameter': inputParameter, exponent, 'output-parameter': outputParameter, - } = validateGlobalConfig(); + } = validateConfig(); return inputs.map(input => { validateSingleInput(input, inputParameter); diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 60fe90e5b..5e3c3e717 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -14,15 +14,11 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; -const { - MISSING_GLOBAL_CONFIG, - X_Y_EQUAL, - ARRAY_LENGTH_NON_EMPTY, - WITHIN_THE_RANGE, -} = STRINGS; +const {MISSING_CONFIG, X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE} = + STRINGS; export const Interpolation = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -68,7 +64,7 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[globalConfig['input-parameter']]; + const parameter = input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; @@ -98,7 +94,7 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[globalConfig['input-parameter']]; + const parameter = input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; const spline: any = new Spline(xPoints, yPoints); @@ -113,7 +109,7 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[globalConfig['input-parameter']]; + const parameter = input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; @@ -133,12 +129,12 @@ export const Interpolation = ( }; /** - * Validates global config parameters. + * Validates config parameters. * Sorts elements of `x` and `y`. */ const validateConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } const schema = z @@ -156,16 +152,11 @@ export const Interpolation = ( message: ARRAY_LENGTH_NON_EMPTY, }); - const defaultMethod = globalConfig.method ?? Method.LINEAR; - const updatedConfig = Object.assign( - {}, - {method: defaultMethod}, - globalConfig, - { - x: sortPoints(globalConfig.x), - y: sortPoints(globalConfig.y), - } - ); + const defaultMethod = config.method ?? Method.LINEAR; + const updatedConfig = Object.assign({}, {method: defaultMethod}, config, { + x: sortPoints(config.x), + y: sortPoints(config.y), + }); return validate>(schema, updatedConfig); }; @@ -179,7 +170,7 @@ export const Interpolation = ( * Validates inputes parameters. */ const validateInput = (input: PluginParams, index: number) => { - const inputParameter = globalConfig['input-parameter']; + const inputParameter = config['input-parameter']; const schema = z .object({ timestamp: z.string().or(z.date()), @@ -188,8 +179,8 @@ export const Interpolation = ( }) .refine( data => - data[inputParameter] >= globalConfig.x[0] && - data[inputParameter] <= globalConfig.x[globalConfig.x.length - 1], + data[inputParameter] >= config.x[0] && + data[inputParameter] <= config.x[config.x.length - 1], { message: WITHIN_THE_RANGE, } diff --git a/src/if-run/builtins/mock-observations/helpers/common-generator.ts b/src/if-run/builtins/mock-observations/helpers/common-generator.ts index 8283cf1bd..be0800eec 100644 --- a/src/if-run/builtins/mock-observations/helpers/common-generator.ts +++ b/src/if-run/builtins/mock-observations/helpers/common-generator.ts @@ -6,7 +6,7 @@ import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; export const CommonGenerator = (config: ConfigParams): Generator => { /** @@ -16,7 +16,7 @@ export const CommonGenerator = (config: ConfigParams): Generator => { */ const validateConfig = (config: object) => { if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + throw new GlobalConfigError(MISSING_CONFIG); } return structuredClone(config); diff --git a/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts index 1cb4d161f..b62c63e3f 100644 --- a/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts @@ -7,7 +7,7 @@ import {Generator} from '../interfaces'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = +const {MISSING_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = STRINGS; export const RandIntGenerator = ( @@ -28,7 +28,7 @@ export const RandIntGenerator = ( const validateConfig = (config: ConfigParams): {min: number; max: number} => { if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + throw new GlobalConfigError(MISSING_CONFIG); } if (!config.min || !config.max) { diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index facc78353..dc4111677 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -16,7 +16,7 @@ import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; export const MockObservations = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -55,9 +55,9 @@ export const MockObservations = ( }; /** - * Validates global config parameters. + * Validates config parameters. */ - const validateGlobalConfig = () => { + const validateConfig = () => { const schema = z.object({ 'timestamp-from': z.string(), 'timestamp-to': z.string(), @@ -69,7 +69,7 @@ export const MockObservations = ( }), }); - return validate>(schema, globalConfig); + return validate>(schema, config); }; /** @@ -82,7 +82,7 @@ export const MockObservations = ( duration, generators, components, - } = validateGlobalConfig(); + } = validateConfig(); const convertedTimestampFrom = DateTime.fromISO(timestampFrom, { zone: 'UTC', }); diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index b51c1a426..5da795c3b 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -9,7 +9,7 @@ import { import {validate} from '../../../common/util/validations'; export const Multiply = ( - globalConfig: MultiplyConfig, + config: MultiplyConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -19,18 +19,15 @@ export const Multiply = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ + const validateConfig = () => { + const configSchema = z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; /** @@ -60,7 +57,7 @@ export const Multiply = ( * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const inputParameters = safeGlobalConfig['input-parameters']; const outputParameter = safeGlobalConfig['output-parameter']; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 0076b6cfe..b48d0264b 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -12,10 +12,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; +const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; export const Regex = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -25,11 +25,11 @@ export const Regex = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } const schema = z.object({ @@ -38,7 +38,7 @@ export const Regex = ( output: z.string(), }); - return validate>(schema, globalConfig); + return validate>(schema, config); }; /** @@ -56,7 +56,7 @@ export const Regex = ( * Executes the regex of the given parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const {parameter: parameter, match, output} = safeGlobalConfig; return inputs.map(input => { diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 1106f3725..8dba4a4fc 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -21,7 +21,7 @@ const { } = STRINGS; export const Sci = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -72,7 +72,7 @@ export const Sci = ( const execute = (inputs: PluginParams[]): PluginParams[] => inputs.map((input, index) => { const safeInput = validateInput(input); - const functionalUnit = input[globalConfig['functional-unit']]; + const functionalUnit = input[config['functional-unit']]; if (functionalUnit === 0) { console.warn(ZERO_DIVISION(Sci.name, index)); @@ -93,7 +93,7 @@ export const Sci = ( * Checks for fields in input. */ const validateInput = (input: PluginParams) => { - const validatedConfig = validateConfig(globalConfig); + const validatedConfig = validateConfig(config); if ( !( @@ -110,7 +110,7 @@ export const Sci = ( duration: z.number().gte(1), }) .refine(allDefined, { - message: SCI_MISSING_FN_UNIT(globalConfig['functional-unit']), + message: SCI_MISSING_FN_UNIT(config['functional-unit']), }); return validate>(schema, input); diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 9abe8363c..9a24f1ee5 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -15,7 +15,7 @@ import {validate} from '../../../common/util/validations'; const {ProcessExecutionError} = ERRORS; export const Shell = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -44,7 +44,7 @@ export const Shell = ( command: z.string(), }); - return validate>(schema, globalConfig); + return validate>(schema, config); }; /** diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 2598ecb8a..75303d80b 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -9,7 +9,7 @@ import { import {validate} from '../../../common/util/validations'; export const Subtract = ( - globalConfig: SubtractConfig, + config: SubtractConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -19,18 +19,15 @@ export const Subtract = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - const globalConfigSchema = z.object({ + const validateConfig = () => { + const configSchema = z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; /** @@ -63,7 +60,7 @@ export const Subtract = ( const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, - } = validateGlobalConfig(); + } = validateConfig(); return inputs.map(input => { validateSingleInput(input, inputParameters); diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index da642dd13..8255080c3 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -12,10 +12,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; export const Sum = ( - globalConfig: SumConfig, + config: SumConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -28,7 +28,7 @@ export const Sum = ( * Calculate the sum of each input-paramters. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const inputParameters = safeGlobalConfig['input-parameters']; const outputParameter = safeGlobalConfig['output-parameter']; @@ -43,22 +43,19 @@ export const Sum = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } - const globalConfigSchema = z.object({ + const configSchema = z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; /** diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index cb25951a9..527e8e146 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -14,10 +14,10 @@ import {STRINGS} from '../../config'; import {TIME_UNITS_IN_SECONDS} from './config'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; export const TimeConverter = ( - globalConfig: ConfigParams, + config: ConfigParams, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -27,7 +27,7 @@ export const TimeConverter = ( }; const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateGlobalConfig(); + const safeGlobalConfig = validateConfig(); const inputParameter = safeGlobalConfig['input-parameter']; const outputParameter = safeGlobalConfig['output-parameter']; @@ -45,13 +45,13 @@ export const TimeConverter = ( * Calculates the energy for given period. */ const calculateEnergy = (input: PluginParams) => { - const originalTimeUnit = globalConfig['original-time-unit']; + const originalTimeUnit = config['original-time-unit']; const originalTimeUnitInSeoncds = TIME_UNITS_IN_SECONDS[originalTimeUnit]; - const energyPerPeriod = input[globalConfig['input-parameter']]; + const energyPerPeriod = input[config['input-parameter']]; const newTimeUnit = - globalConfig['new-time-unit'] === 'duration' + config['new-time-unit'] === 'duration' ? input.duration - : TIME_UNITS_IN_SECONDS[globalConfig['new-time-unit']]; + : TIME_UNITS_IN_SECONDS[config['new-time-unit']]; const result = (energyPerPeriod / originalTimeUnitInSeoncds) * newTimeUnit; return Number(result.toFixed(6)); @@ -70,11 +70,11 @@ export const TimeConverter = ( }; /** - * Checks global config value are valid. + * Checks config value are valid. */ - const validateGlobalConfig = () => { - if (!globalConfig) { - throw new GlobalConfigError(MISSING_GLOBAL_CONFIG); + const validateConfig = () => { + if (!config) { + throw new GlobalConfigError(MISSING_CONFIG); } const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); @@ -84,17 +84,14 @@ export const TimeConverter = ( ] as const; const originalTimeUnitValues = timeUnitsValues as [string, ...string[]]; - const globalConfigSchema = z.object({ + const configSchema = z.object({ 'input-parameter': z.string(), 'original-time-unit': z.enum(originalTimeUnitValues), 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), 'output-parameter': z.string().min(1), }); - return validate>( - globalConfigSchema, - globalConfig - ); + return validate>(configSchema, config); }; return { metadata, diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 27f0aac8e..65b1bd9a8 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -53,7 +53,7 @@ const { * ``` */ export const TimeSync = ( - globalConfig: TimeNormalizerConfig, + config: TimeNormalizerConfig, parametersMetadata: PluginParametersMetadata ): ExecutePlugin => { const metadata = { @@ -80,7 +80,7 @@ export const TimeSync = ( * Take input array and return time-synchronized input array. */ const execute = (inputs: PluginParams[]): PluginParams[] => { - const validatedConfig = validateGlobalConfig(); + const validatedConfig = validateConfig(); const timeParams = { startTime: DateTime.fromISO(validatedConfig['start-time']), endTime: DateTime.fromISO(validatedConfig['end-time']), @@ -191,10 +191,10 @@ export const TimeSync = ( }; /** - * Validates global config parameters. + * Validates config parameters. */ - const validateGlobalConfig = () => { - if (globalConfig === undefined) { + const validateConfig = () => { + if (config === undefined) { throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); } @@ -209,7 +209,7 @@ export const TimeSync = ( message: START_LOWER_END, }); - return validate>(schema, globalConfig); + return validate>(schema, config); }; /** From 37ce72bde546b6cdaa7a24ad2c430ec94abefaf7 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 20:06:30 +0400 Subject: [PATCH 628/863] fix(manifests): rename global-config to config --- .../failure-invalid-config-input-param.yml | 4 +- .../failure-output-param-is-null.yaml | 2 +- .../examples/builtins/coefficient/success.yml | 2 +- .../failure-invalid-instance-type.yaml | 2 +- .../failure-invalid-vendor.yaml | 2 +- .../failure-missing-cloud-vendor.yml | 2 +- .../csv-lookup/cloud-metadata/success.yml | 2 +- .../failure-missing-column.yml | 2 +- .../failure-missing-output.yml | 2 +- .../region-metadata/success-renaming.yml | 2 +- .../csv-lookup/region-metadata/success.yml | 2 +- .../failure-missing-input-param.yml | 2 +- ...failure-unsupported-physical-processor.yml | 2 +- .../csv-lookup/tdp-finder/success.yml | 2 +- .../divide/failure-denominator-equal-zero.yml | 4 +- .../failure-invalid-config-denominator.yml | 6 +- .../divide/failure-missing-numerator.yml | 4 +- .../examples/builtins/divide/success.yml | 4 +- .../examples/builtins/exponent/success.yml | 2 +- .../builtins/interpolation/interpolation.yml | 2 +- .../builtins/interpolation/success.yml | 2 +- .../failure-invalid-config-cpu-range.yml | 4 +- ...ilure-invalid-memory-utilization-range.yml | 2 +- .../failure-missing-timestamp-from-param.yml | 2 +- .../builtins/mock-observations/success.yml | 2 +- .../failure-input-parameter-is-missing.yml | 2 +- .../multiply/success-with-multiple-inputs.yml | 2 +- .../examples/builtins/multiply/success.yml | 2 +- .../regex/failure-missing-input-param.yml | 2 +- .../regex/failure-not-matching-with-regex.yml | 2 +- manifests/examples/builtins/regex/success.yml | 2 +- .../sci/failure-invalid-config-value.yml | 2 +- .../sci/failure-missing-input-param.yml | 2 +- manifests/examples/builtins/sci/success.yml | 2 +- .../shell/failure-invalid-command.yml | 4 +- manifests/examples/builtins/shell/success.yml | 4 +- .../examples/builtins/subtract/success.yml | 2 +- .../sum/failure-missing-input-param.yml | 4 +- .../sum/failure-missing-output-param.yml | 4 +- manifests/examples/builtins/sum/success.yml | 2 +- .../builtins/time-converter/success.yaml | 2 +- .../failure-config-start-later-end.yml | 20 +- .../failure-missing-global-config.yml | 16 +- .../examples/builtins/time-sync/success.yml | 16 +- manifests/examples/pipelines/generics.yml | 16 +- .../examples/pipelines/instance-metadata.yml | 4 +- manifests/examples/pipelines/nesting.yml | 20 +- .../pipeline-with-aggregate.yaml | 144 +++++----- .../outputs-if-diff/pipeline-with-mocks.yaml | 22 +- .../examples/pipelines/pipeline-teads-sci.yml | 26 +- .../pipelines/pipeline-with-aggregate.yml | 20 +- .../pipelines/pipeline-with-mocks.yml | 22 +- manifests/examples/pipelines/scenario-1.yml | 2 +- manifests/examples/pipelines/scenario-2.yml | 4 +- manifests/examples/pipelines/scenario-3.yml | 2 +- manifests/examples/pipelines/scenario-4.yml | 10 +- manifests/examples/pipelines/scenario-5.yml | 6 +- manifests/examples/pipelines/sci.yml | 20 +- manifests/examples/pipelines/teads-curve.yml | 20 +- manifests/examples/pipelines/zeros.yml | 46 +-- .../bugs/aggregation-error-wrong-metric.yaml | 18 +- .../bugs/input-error-missing-duration.yaml | 2 +- ...observations-failure-duration-is-zero.yaml | 4 +- .../bugs/pipeline-error-naming-mismatch.yaml | 2 +- .../pipeline-error-uninitialized-plugin.yaml | 2 +- .../outputs/bugs/pipeline-ordering-error.yaml | 12 +- .../failure-invalid-config-input-param.yaml | 4 +- .../failure-output-param-is-null.yaml | 2 +- .../outputs/builtins/coefficient/success.yaml | 2 +- .../failure-invalid-instance-type.yaml | 2 +- .../failure-missing-cloud-vendor.yaml | 2 +- .../csv-lookup/cloud-metadata/success.yaml | 2 +- .../failure-missing-column.yaml | 2 +- .../failure-missing-output.yaml | 2 +- .../region-metadata/success-renaming.yaml | 2 +- .../csv-lookup/region-metadata/success.yaml | 2 +- .../failure-missing-input-param.yaml | 2 +- ...ailure-unsupported-physical-processor.yaml | 2 +- .../csv-lookup/tdp-finder/success.yaml | 2 +- .../failure-invalid-config-denominator.yaml | 4 +- .../divide/failure-missing-numerator.yaml | 2 +- .../success-denominator-equal-zero.yaml | 4 +- .../outputs/builtins/divide/success.yaml | 4 +- .../outputs/builtins/exponent/success.yaml | 2 +- .../builtins/interpolation/interpolation.yaml | 2 +- .../builtins/interpolation/success.yaml | 2 +- .../failure-invalid-config-cpu-range.yaml | 4 +- ...lure-invalid-memory-utilization-range.yaml | 2 +- .../failure-missing-timestamp-from-param.yaml | 2 +- .../builtins/mock-observations/success.yaml | 264 +++++++++--------- .../failure-input-parameter-is-missing.yaml | 2 +- .../success-with-multiple-inputs.yaml | 2 +- .../outputs/builtins/multiply/success.yaml | 2 +- .../regex/failure-missing-input-param.yaml | 2 +- manifests/outputs/builtins/regex/success.yaml | 2 +- .../sci/failure-missing-input-param.yaml | 2 +- manifests/outputs/builtins/sci/success.yaml | 2 +- .../shell/failure-invalid-command.yaml | 4 +- manifests/outputs/builtins/shell/success.yaml | 2 +- .../outputs/builtins/subtract/success.yaml | 2 +- .../sum/failure-missing-input-param.yaml | 4 +- .../sum/failure-missing-output-param.yaml | 4 +- manifests/outputs/builtins/sum/success.yaml | 2 +- .../failure-config-start-later-end.yaml | 6 +- .../outputs/builtins/time-sync/success.yaml | 2 +- .../aggregate-failure-invalid-metrics.yaml | 2 +- ...gate-failure-missing-metric-in-inputs.yaml | 2 +- .../features/aggregate-horizontal.yaml | 2 +- .../outputs/features/aggregate-vertical.yaml | 2 +- manifests/outputs/features/aggregate.yaml | 2 +- .../pipelines/cloud-metadata-divide.yaml | 4 +- manifests/outputs/pipelines/generics.yaml | 56 ++-- .../outputs/pipelines/instance-metadata.yaml | 28 +- .../outputs/pipelines/mock-obs-time-sync.yaml | 238 ++++++++-------- manifests/outputs/pipelines/nesting.yaml | 20 +- .../outputs/pipelines/pipeline-teads-sci.yaml | 58 ++-- manifests/outputs/pipelines/sci.yaml | 60 ++-- manifests/outputs/pipelines/teads-curve.yaml | 36 +-- manifests/outputs/pipelines/zeros.yaml | 54 ++-- src/__mocks__/builtins/export-yaml.ts | 6 +- src/__mocks__/mock-manifest.yaml | 2 +- 121 files changed, 756 insertions(+), 756 deletions(-) diff --git a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml index 55f9f0b64..17672dcdc 100644 --- a/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml +++ b/manifests/examples/builtins/coefficient/failure-invalid-config-input-param.yml @@ -1,12 +1,12 @@ name: coefficient-demo -description: failure with ivalid `global-config.input-parameter` +description: failure with ivalid `config.input-parameter` tags: initialize: plugins: coefficient: method: Coefficient path: "builtin" - global-config: + config: input-parameter: 4 coefficient: 3 output-parameter: "carbon-product" diff --git a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml index ce722c9dd..1a790e205 100644 --- a/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/examples/builtins/coefficient/failure-output-param-is-null.yaml @@ -6,7 +6,7 @@ initialize: coefficient: method: Coefficient path: "builtin" - global-config: + config: input-parameter: "carbon" coefficient: 3 output-parameter: diff --git a/manifests/examples/builtins/coefficient/success.yml b/manifests/examples/builtins/coefficient/success.yml index 31e75a235..227f556e4 100644 --- a/manifests/examples/builtins/coefficient/success.yml +++ b/manifests/examples/builtins/coefficient/success.yml @@ -6,7 +6,7 @@ initialize: coefficient: method: Coefficient path: "builtin" - global-config: + config: input-parameter: "carbon" coefficient: 3 output-parameter: "carbon-product" diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index 6a6e2201e..60709dced 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 5098c7a95..17deabf22 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index 3c7d9d55d..aece37d5f 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml index e11db823f..34a2eae6c 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/success.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml index 5b4e9583b..216836083 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-column.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: "nonexistant" diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index 71417932d..501bde3ce 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: "cloud/provider" diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml index 4c2767a3a..3c9fe7e03 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success-renaming.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: "cloud/provider" diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml index 71417932d..501bde3ce 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/success.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/success.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: "cloud/provider" diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml index 03791996a..070b4f7b0 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yml @@ -6,7 +6,7 @@ initialize: tdp-finder: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: name: physical-processor diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml index db0459d56..4c9401e02 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yml @@ -6,7 +6,7 @@ initialize: tdp-finder: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: name: physical-processor diff --git a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml index b60869399..aab0ae3ef 100644 --- a/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml +++ b/manifests/examples/builtins/csv-lookup/tdp-finder/success.yml @@ -6,7 +6,7 @@ initialize: tdp-finder: method: CSVLookup path: "builtin" - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: name: physical-processor diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml index c3a4d216d..9635af671 100644 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -15,7 +15,7 @@ initialize: divide: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores diff --git a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml index 712e1205c..f43489d72 100644 --- a/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml +++ b/manifests/examples/builtins/divide/failure-invalid-config-denominator.yml @@ -1,12 +1,12 @@ name: divide -description: failure when `global-config.denominator` is string +description: failure when `config.denominator` is string tags: initialize: plugins: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -15,7 +15,7 @@ initialize: divide: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-allocated denominator: "vcpus" output: cpu/number-cores diff --git a/manifests/examples/builtins/divide/failure-missing-numerator.yml b/manifests/examples/builtins/divide/failure-missing-numerator.yml index 59b604582..a50b90d6c 100644 --- a/manifests/examples/builtins/divide/failure-missing-numerator.yml +++ b/manifests/examples/builtins/divide/failure-missing-numerator.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -15,7 +15,7 @@ initialize: divide: method: Divide path: "builtin" - global-config: + config: #numerator: vcpus-allocated denominator: 2 output: cpu/number-cores diff --git a/manifests/examples/builtins/divide/success.yml b/manifests/examples/builtins/divide/success.yml index 32b247a87..10d27bd7f 100644 --- a/manifests/examples/builtins/divide/success.yml +++ b/manifests/examples/builtins/divide/success.yml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -15,7 +15,7 @@ initialize: divide: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores diff --git a/manifests/examples/builtins/exponent/success.yml b/manifests/examples/builtins/exponent/success.yml index 163dd1460..a05692ddb 100644 --- a/manifests/examples/builtins/exponent/success.yml +++ b/manifests/examples/builtins/exponent/success.yml @@ -6,7 +6,7 @@ initialize: exponent: method: Exponent path: "builtin" - global-config: + config: input-parameter: "cpu/energy" exponent: 2 output-parameter: "energy" diff --git a/manifests/examples/builtins/interpolation/interpolation.yml b/manifests/examples/builtins/interpolation/interpolation.yml index 394946467..8f4fc946e 100644 --- a/manifests/examples/builtins/interpolation/interpolation.yml +++ b/manifests/examples/builtins/interpolation/interpolation.yml @@ -6,7 +6,7 @@ initialize: interpolation: method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] diff --git a/manifests/examples/builtins/interpolation/success.yml b/manifests/examples/builtins/interpolation/success.yml index 394946467..8f4fc946e 100644 --- a/manifests/examples/builtins/interpolation/success.yml +++ b/manifests/examples/builtins/interpolation/success.yml @@ -6,7 +6,7 @@ initialize: interpolation: method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml index 472f797fd..d4e44fe22 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-config-cpu-range.yml @@ -1,5 +1,5 @@ name: mock-observation-demo -description: failure with `global-config->generators->randint->cpu/utilization->min` is greater than `max` +description: failure with `config->generators->randint->cpu/utilization->min` is greater than `max` tags: initialize: plugins: @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml index 85e3f566b..b0e2e801f 100644 --- a/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml +++ b/manifests/examples/builtins/mock-observations/failure-invalid-memory-utilization-range.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml index 58545dcec..86078ad31 100644 --- a/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml +++ b/manifests/examples/builtins/mock-observations/failure-missing-timestamp-from-param.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: #timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/examples/builtins/mock-observations/success.yml b/manifests/examples/builtins/mock-observations/success.yml index 5ca2d1942..cb2151fcf 100644 --- a/manifests/examples/builtins/mock-observations/success.yml +++ b/manifests/examples/builtins/mock-observations/success.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml index 988a33fc2..acb59098d 100644 --- a/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml +++ b/manifests/examples/builtins/multiply/failure-input-parameter-is-missing.yml @@ -6,7 +6,7 @@ initialize: multiply: method: Multiply path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy-product" tree: diff --git a/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml index e6e138723..63ac84183 100644 --- a/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml +++ b/manifests/examples/builtins/multiply/success-with-multiple-inputs.yml @@ -6,7 +6,7 @@ initialize: multiply: method: Multiply path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy-product" tree: diff --git a/manifests/examples/builtins/multiply/success.yml b/manifests/examples/builtins/multiply/success.yml index c5d53e046..ee7f8875b 100644 --- a/manifests/examples/builtins/multiply/success.yml +++ b/manifests/examples/builtins/multiply/success.yml @@ -7,7 +7,7 @@ initialize: multiply: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy-product" tree: diff --git a/manifests/examples/builtins/regex/failure-missing-input-param.yml b/manifests/examples/builtins/regex/failure-missing-input-param.yml index 84adc0cb2..95e055eda 100644 --- a/manifests/examples/builtins/regex/failure-missing-input-param.yml +++ b/manifests/examples/builtins/regex/failure-missing-input-param.yml @@ -6,7 +6,7 @@ initialize: regex: method: Regex path: "builtin" - global-config: + config: parameter: physical-processor match: ^(.*), output: cpu/name diff --git a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml index 8341d08e6..bad022d72 100644 --- a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml +++ b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml @@ -6,7 +6,7 @@ initialize: regex: method: Regex path: "builtin" - global-config: + config: parameter: physical-processor match: ^ output: cpu/name diff --git a/manifests/examples/builtins/regex/success.yml b/manifests/examples/builtins/regex/success.yml index 425dd9e67..81a3432f2 100644 --- a/manifests/examples/builtins/regex/success.yml +++ b/manifests/examples/builtins/regex/success.yml @@ -6,7 +6,7 @@ initialize: regex: method: Regex path: "builtin" - global-config: + config: parameter: physical-processor match: ^(.*), output: cpu/name diff --git a/manifests/examples/builtins/sci/failure-invalid-config-value.yml b/manifests/examples/builtins/sci/failure-invalid-config-value.yml index 2d51dbe66..961a28786 100644 --- a/manifests/examples/builtins/sci/failure-invalid-config-value.yml +++ b/manifests/examples/builtins/sci/failure-invalid-config-value.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: Sci path: "builtin" - # global-config: + # config: # functional-unit: 1 minute tree: children: diff --git a/manifests/examples/builtins/sci/failure-missing-input-param.yml b/manifests/examples/builtins/sci/failure-missing-input-param.yml index 0a7677261..efa2d3d96 100644 --- a/manifests/examples/builtins/sci/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sci/failure-missing-input-param.yml @@ -8,7 +8,7 @@ initialize: kind: plugin method: Sci path: "builtin" - global-config: + config: functional-unit: requests tree: children: diff --git a/manifests/examples/builtins/sci/success.yml b/manifests/examples/builtins/sci/success.yml index 85dd19db2..1ed4c72fb 100644 --- a/manifests/examples/builtins/sci/success.yml +++ b/manifests/examples/builtins/sci/success.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: Sci path: "builtin" - global-config: + config: functional-unit: requests tree: children: diff --git a/manifests/examples/builtins/shell/failure-invalid-command.yml b/manifests/examples/builtins/shell/failure-invalid-command.yml index e67aff103..0ced9f6ec 100644 --- a/manifests/examples/builtins/shell/failure-invalid-command.yml +++ b/manifests/examples/builtins/shell/failure-invalid-command.yml @@ -1,12 +1,12 @@ name: shell -description: falure with `global-config.command` being number instead od string +description: falure with `config.command` being number instead od string tags: initialize: plugins: shell: method: Shell path: "builtin" - global-config: + config: command: 1000 tree: children: diff --git a/manifests/examples/builtins/shell/success.yml b/manifests/examples/builtins/shell/success.yml index a26af274d..969e6ae92 100644 --- a/manifests/examples/builtins/shell/success.yml +++ b/manifests/examples/builtins/shell/success.yml @@ -5,8 +5,8 @@ initialize: plugins: shell: method: Shell - path: 'builtin' - global-config: + path: "builtin" + config: command: python3 /usr/local/bin/sampler tree: children: diff --git a/manifests/examples/builtins/subtract/success.yml b/manifests/examples/builtins/subtract/success.yml index 745ceb067..a227f7217 100644 --- a/manifests/examples/builtins/subtract/success.yml +++ b/manifests/examples/builtins/subtract/success.yml @@ -6,7 +6,7 @@ initialize: subtract: method: Subtract path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy/diff" tree: diff --git a/manifests/examples/builtins/sum/failure-missing-input-param.yml b/manifests/examples/builtins/sum/failure-missing-input-param.yml index 1e963b694..a82f8748a 100644 --- a/manifests/examples/builtins/sum/failure-missing-input-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-input-param.yml @@ -1,12 +1,12 @@ name: sum -description: failure with `inputs[0]` misses one of `global-config.input-parameters` +description: failure with `inputs[0]` misses one of `config.input-parameters` tags: initialize: plugins: sum: method: Sum path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy" tree: diff --git a/manifests/examples/builtins/sum/failure-missing-output-param.yml b/manifests/examples/builtins/sum/failure-missing-output-param.yml index 0248bf449..0c8c323cb 100644 --- a/manifests/examples/builtins/sum/failure-missing-output-param.yml +++ b/manifests/examples/builtins/sum/failure-missing-output-param.yml @@ -1,12 +1,12 @@ name: sum -description: missing `output-parameter` in global-config +description: missing `output-parameter` in config tags: initialize: plugins: sum: method: Sum path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] # output-parameter: "energy" tree: diff --git a/manifests/examples/builtins/sum/success.yml b/manifests/examples/builtins/sum/success.yml index 366ae5580..8c30b20b8 100644 --- a/manifests/examples/builtins/sum/success.yml +++ b/manifests/examples/builtins/sum/success.yml @@ -6,7 +6,7 @@ initialize: sum: method: Sum path: "builtin" - global-config: + config: input-parameters: ["cpu/energy", "network/energy"] output-parameter: "energy" tree: diff --git a/manifests/examples/builtins/time-converter/success.yaml b/manifests/examples/builtins/time-converter/success.yaml index 30c5d987e..9245562fa 100644 --- a/manifests/examples/builtins/time-converter/success.yaml +++ b/manifests/examples/builtins/time-converter/success.yaml @@ -6,7 +6,7 @@ initialize: time-converter: method: TimeConverter path: builtin - global-config: + config: input-parameter: "energy-per-year" original-time-unit: "year" new-time-unit: "duration" diff --git a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml index ffed32274..c1ab78855 100644 --- a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml +++ b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml @@ -1,16 +1,16 @@ name: time-sync -description: failure with `global-config.start-time` being later than `global-config.end-time` +description: failure with `config.start-time` being later than `config.end-time` tags: initialize: output: - yaml plugins: - 'time-sync': + "time-sync": method: TimeSync path: "builtin" - global-config: - start-time: '2023-12-12T00:01:00.000Z' - end-time: '2023-12-12T00:00:00.000Z' + config: + start-time: "2023-12-12T00:01:00.000Z" + end-time: "2023-12-12T00:00:00.000Z" interval: 5 allow-padding: true tree: @@ -20,15 +20,15 @@ tree: compute: - time-sync inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 - energy-cpu: 0.001 \ No newline at end of file + energy-cpu: 0.001 diff --git a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml index c5715a26a..2938d3bb1 100644 --- a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml +++ b/manifests/examples/builtins/time-sync/failure-missing-global-config.yml @@ -1,14 +1,14 @@ name: time-sync -description: missing global config +description: missing config tags: initialize: output: - yaml plugins: - 'time-sync': + "time-sync": method: TimeSync path: "builtin" - global-config: + config: # start-time: '2023-12-12T00:00:00.000Z' # end-time: '2023-12-12T00:01:00.000Z' # interval: 5 @@ -20,15 +20,15 @@ tree: compute: - time-sync inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 3 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 - energy-cpu: 0.001 \ No newline at end of file + energy-cpu: 0.001 diff --git a/manifests/examples/builtins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml index 8aac13740..95a94e5d3 100644 --- a/manifests/examples/builtins/time-sync/success.yml +++ b/manifests/examples/builtins/time-sync/success.yml @@ -5,12 +5,12 @@ initialize: output: - yaml plugins: - 'time-sync': + "time-sync": method: TimeSync path: "builtin" - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + config: + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true tree: @@ -20,15 +20,15 @@ tree: compute: - time-sync inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 energy-cpu: 0.001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 energy-cpu: 0.001 diff --git a/manifests/examples/pipelines/generics.yml b/manifests/examples/pipelines/generics.yml index f9a19a6b3..78c254838 100644 --- a/manifests/examples/pipelines/generics.yml +++ b/manifests/examples/pipelines/generics.yml @@ -6,7 +6,7 @@ initialize: "interpolate": method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -15,47 +15,47 @@ initialize: "cpu-factor-to-wattage": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" "wattage-times-duration": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" "wattage-to-energy-kwh": method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw "calculate-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh "coefficient": path: "builtin" method: Coefficient - global-config: + config: input-parameter: cpu-energy-kwh coefficient: 2 output-parameter: energy-doubled "multiply": path: "builtin" method: Multiply - global-config: + config: input-parameters: ["cpu/utilization", "duration"] output-parameter: "cpu-times-duration" tree: diff --git a/manifests/examples/pipelines/instance-metadata.yml b/manifests/examples/pipelines/instance-metadata.yml index 0a64e9ac3..58b4c9613 100644 --- a/manifests/examples/pipelines/instance-metadata.yml +++ b/manifests/examples/pipelines/instance-metadata.yml @@ -6,7 +6,7 @@ initialize: cloud-instance-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv query: @@ -15,7 +15,7 @@ initialize: extract-processor-name: path: builtin method: Regex - global-config: + config: parameter: cpu-model-name match: /^([^,])+/g output: cpu/name diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index baf12a688..631f4db90 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -13,7 +13,7 @@ initialize: "interpolate": method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -33,7 +33,7 @@ initialize: "cpu-factor-to-wattage": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" parameter-metadata: @@ -54,13 +54,13 @@ initialize: "wattage-times-duration": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" "wattage-to-energy-kwh": method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -78,7 +78,7 @@ initialize: "calculate-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -91,7 +91,7 @@ initialize: "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -101,7 +101,7 @@ initialize: "operational-carbon": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" parameter-metadata: @@ -122,7 +122,7 @@ initialize: sci: path: "builtin" method: Sci - global-config: + config: functional-unit: "requests" parameter-metadata: inputs: @@ -133,7 +133,7 @@ initialize: "sum-carbon": path: "builtin" method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -156,7 +156,7 @@ initialize: time-sync: method: TimeSync path: "builtin" - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml index c1f92da04..b9771834f 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -10,14 +10,14 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -38,7 +38,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -61,7 +61,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -69,7 +69,7 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -87,7 +87,7 @@ initialize: calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -109,7 +109,7 @@ initialize: correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -119,7 +119,7 @@ initialize: operational-carbon: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-energy-kwh - grid/carbon-intensity @@ -142,7 +142,7 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: requests parameter-metadata: inputs: @@ -153,7 +153,7 @@ initialize: sum-carbon: path: builtin method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -176,9 +176,9 @@ initialize: time-sync: path: builtin method: TimeSync - global-config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' + config: + start-time: "2023-12-12T00:00:00.000Z" + end-time: "2023-12-12T00:01:00.000Z" interval: 5 allow-padding: true parameter-metadata: @@ -212,20 +212,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-31T12:41:31.920Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.16" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -265,7 +265,7 @@ tree: - operational-carbon - sum-carbon - time-sync - - sci + - sci defaults: cpu/thermal-design-power: 100 grid/carbon-intensity: 800 @@ -275,32 +275,32 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 10 requests: 10 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west requests: 5 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west requests: 15 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 requests: 30 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -323,7 +323,7 @@ tree: carbon-operational: 0.0056388888888888895 carbon: 0.005649016996448503 sci: 0.000403501214032036 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -346,7 +346,7 @@ tree: carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0005589976298113692 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -369,7 +369,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0006170797001436077 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -392,7 +392,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -415,7 +415,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -438,7 +438,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -461,7 +461,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -484,7 +484,7 @@ tree: carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -507,7 +507,7 @@ tree: carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0010402200659563674 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -530,7 +530,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -553,7 +553,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -576,7 +576,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cloud/instance-type: A1 cloud/region: uk-west @@ -627,32 +627,32 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 cpu/utilization: 30 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 28 cloud/instance-type: A1 cloud/region: uk-west requests: 150 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 40 cloud/instance-type: A1 cloud/region: uk-west requests: 110 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west requests: 180 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 5 cpu/utilization: 22.8 cloud/instance-type: A1 @@ -675,7 +675,7 @@ tree: carbon-operational: 0.007191666666666666 carbon: 0.007201794774226282 sci: 0.00003273543079193765 - - timestamp: '2023-12-12T00:00:05.000Z' + - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 cpu/utilization: 29.6 cloud/instance-type: A1 @@ -698,7 +698,7 @@ tree: carbon-operational: 0.008565277777777778 carbon: 0.008575405885337391 sci: 0.00009235052491901808 - - timestamp: '2023-12-12T00:00:10.000Z' + - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 cpu/utilization: 30.6 cloud/instance-type: A1 @@ -721,7 +721,7 @@ tree: carbon-operational: 0.008505555555555556 carbon: 0.00851568366311517 sci: 0.0001439849894729618 - - timestamp: '2023-12-12T00:00:15.000Z' + - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 cpu/utilization: 26.4 cloud/instance-type: A1 @@ -744,7 +744,7 @@ tree: carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:20.000Z' + - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 cpu/utilization: 26.4 cloud/instance-type: A1 @@ -767,7 +767,7 @@ tree: carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:25.000Z' + - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 cpu/utilization: 26.4 cloud/instance-type: A1 @@ -790,7 +790,7 @@ tree: carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:30.000Z' + - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 cpu/utilization: 26.4 cloud/instance-type: A1 @@ -813,7 +813,7 @@ tree: carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:35.000Z' + - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 cpu/utilization: 26.4 cloud/instance-type: A1 @@ -836,7 +836,7 @@ tree: carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 - - timestamp: '2023-12-12T00:00:40.000Z' + - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 cpu/utilization: 19.8 cloud/instance-type: A1 @@ -859,7 +859,7 @@ tree: carbon-operational: 0.004727083333333333 carbon: 0.0047331601978691015 sci: 0.00026295334432606117 - - timestamp: '2023-12-12T00:00:45.000Z' + - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 cpu/utilization: 0 cloud/instance-type: A1 @@ -882,7 +882,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' + - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 cpu/utilization: 0 cloud/instance-type: A1 @@ -905,7 +905,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' + - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 cpu/utilization: 0 cloud/instance-type: A1 @@ -928,7 +928,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 cpu/utilization: 0 cloud/instance-type: A1 @@ -955,43 +955,43 @@ tree: carbon: 0.06846904616945712 outputs: - carbon: 0.012850811770674785 - timestamp: '2023-12-12T00:00:00.000Z' + timestamp: "2023-12-12T00:00:00.000Z" duration: 5 - carbon: 0.013925811770674782 - timestamp: '2023-12-12T00:00:05.000Z' + timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - carbon: 0.013716783992897007 - timestamp: '2023-12-12T00:00:10.000Z' + timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:15.000Z' + timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:20.000Z' + timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:25.000Z' + timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:30.000Z' + timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - carbon: 0.013089700659563674 - timestamp: '2023-12-12T00:00:35.000Z' + timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - carbon: 0.007853820395738204 - timestamp: '2023-12-12T00:00:40.000Z' + timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' + timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' + timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' + timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - carbon: 0 - timestamp: '2023-12-12T00:01:00.000Z' + timestamp: "2023-12-12T00:01:00.000Z" duration: 1 aggregated: carbon: 0.11379573122780316 diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index c86d6fec1..6b4f1c51d 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -10,7 +10,7 @@ initialize: mock-observations: path: builtin method: MockObservations - global-config: + config: timestamp-from: 2023-12-12T00:00 timestamp-to: 2023-12-12T00:10 duration: 60 @@ -44,7 +44,7 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 @@ -72,7 +72,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -95,7 +95,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -118,7 +118,7 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -136,7 +136,7 @@ initialize: calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -158,7 +158,7 @@ initialize: correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -183,7 +183,7 @@ initialize: operational-carbon: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-energy-kwh - grid/carbon-intensity @@ -206,7 +206,7 @@ initialize: sum-carbon: path: builtin method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -229,7 +229,7 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: requests parameter-metadata: inputs: @@ -245,7 +245,7 @@ initialize: time-sync: path: builtin method: TimeSync - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/examples/pipelines/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml index d80d0e89e..28243d38f 100644 --- a/manifests/examples/pipelines/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -5,43 +5,43 @@ initialize: plugins: "interpolate": method: Interpolation - path: 'builtin' - global-config: + path: "builtin" + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] - input-parameter: 'cpu/utilization' - output-parameter: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" "cpu-factor-to-wattage": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" "wattage-times-duration": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" "wattage-to-energy-kwh": method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw "calculate-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -51,18 +51,18 @@ initialize: "operational-carbon": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" "sci": path: "builtin" method: Sci - global-config: + config: functional-unit: "component" "sum-carbon": path: "builtin" method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -70,7 +70,7 @@ initialize: "time-sync": method: TimeSync path: "builtin" - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index 6f7822ad7..7cf805d92 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -10,7 +10,7 @@ initialize: "interpolate": method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -30,7 +30,7 @@ initialize: "cpu-factor-to-wattage": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" parameter-metadata: @@ -51,13 +51,13 @@ initialize: "wattage-times-duration": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" "wattage-to-energy-kwh": method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -75,7 +75,7 @@ initialize: "calculate-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -97,7 +97,7 @@ initialize: "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -107,7 +107,7 @@ initialize: "operational-carbon": method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" parameter-metadata: @@ -128,7 +128,7 @@ initialize: "sci": path: "builtin" method: Sci - global-config: + config: functional-unit: requests # factor to convert per time to per f.unit parameter-metadata: inputs: @@ -139,7 +139,7 @@ initialize: "sum-carbon": path: "builtin" method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -153,7 +153,7 @@ initialize: "time-sync": method: TimeSync path: "builtin" - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index fc6f81cb0..b27b9bb04 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -11,7 +11,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: "2023-12-12T00:00:00.000Z" timestamp-to: "2023-12-12T00:00:13.000Z" duration: 30 @@ -45,7 +45,7 @@ initialize: interpolate: method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -65,7 +65,7 @@ initialize: cpu-factor-to-wattage: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" parameter-metadata: @@ -86,7 +86,7 @@ initialize: wattage-times-duration: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" parameter-metadata: @@ -107,7 +107,7 @@ initialize: wattage-to-energy-kwh: method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -125,7 +125,7 @@ initialize: calculate-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -147,7 +147,7 @@ initialize: correct-cpu-energy-for-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -172,7 +172,7 @@ initialize: operational-carbon: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-energy-kwh", "grid/carbon-intensity"] output-parameter: "carbon-operational" parameter-metadata: @@ -193,7 +193,7 @@ initialize: sum-carbon: path: "builtin" method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -216,7 +216,7 @@ initialize: sci: path: "builtin" method: Sci - global-config: + config: functional-unit: "requests" parameter-metadata: inputs: @@ -232,7 +232,7 @@ initialize: time-sync: method: TimeSync path: "builtin" - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/examples/pipelines/scenario-1.yml b/manifests/examples/pipelines/scenario-1.yml index 9ab2d20f4..0c474fe67 100644 --- a/manifests/examples/pipelines/scenario-1.yml +++ b/manifests/examples/pipelines/scenario-1.yml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:01 duration: 60 diff --git a/manifests/examples/pipelines/scenario-2.yml b/manifests/examples/pipelines/scenario-2.yml index 569cbcb05..6f32afde6 100644 --- a/manifests/examples/pipelines/scenario-2.yml +++ b/manifests/examples/pipelines/scenario-2.yml @@ -1,11 +1,11 @@ name: regroup demo -description: +description: initialize: plugins: interpolate: method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] diff --git a/manifests/examples/pipelines/scenario-3.yml b/manifests/examples/pipelines/scenario-3.yml index f5710b553..8d8eb6c09 100644 --- a/manifests/examples/pipelines/scenario-3.yml +++ b/manifests/examples/pipelines/scenario-3.yml @@ -5,7 +5,7 @@ initialize: "sum": path: "builtin" method: Sum - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/examples/pipelines/scenario-4.yml b/manifests/examples/pipelines/scenario-4.yml index 151db09be..52f9e2bd8 100644 --- a/manifests/examples/pipelines/scenario-4.yml +++ b/manifests/examples/pipelines/scenario-4.yml @@ -1,12 +1,12 @@ name: demo -description: +description: tags: initialize: plugins: "sum": path: "builtin" method: Sum - global-config: + config: input-parameters: - cpu/energy - network/energy @@ -14,14 +14,14 @@ initialize: "coefficient": path: "builtin" method: Coefficient - global-config: + config: input-parameter: energy coefficient: 2 output-parameter: energy-doubled "multiply": path: "builtin" method: Multiply - global-config: + config: input-parameters: ["cpu/utilization", "duration"] output-parameter: "cpu-times-duration" tree: @@ -29,7 +29,7 @@ tree: child-1: pipeline: observe: - compute: + compute: - sum - coefficient - multiply diff --git a/manifests/examples/pipelines/scenario-5.yml b/manifests/examples/pipelines/scenario-5.yml index 6990c33e3..adb0fe139 100644 --- a/manifests/examples/pipelines/scenario-5.yml +++ b/manifests/examples/pipelines/scenario-5.yml @@ -1,5 +1,5 @@ name: demo -description: +description: tags: initialize: plugins: @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: "builtin" - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:01 duration: 60 @@ -28,7 +28,7 @@ initialize: sum: path: "builtin" method: Sum - global-config: + config: input-parameters: - cpu/utilization - memory/utilization diff --git a/manifests/examples/pipelines/sci.yml b/manifests/examples/pipelines/sci.yml index 949d9e7df..37a338286 100644 --- a/manifests/examples/pipelines/sci.yml +++ b/manifests/examples/pipelines/sci.yml @@ -6,7 +6,7 @@ initialize: interpolate: method: Interpolation path: "builtin" - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -15,40 +15,40 @@ initialize: cpu-factor-to-wattage: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "cpu/thermal-design-power"] output-parameter: "cpu-wattage" wattage-times-duration: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" wattage-to-energy-kwh: method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu/energy sum-energy-components: path: "builtin" method: Sum - global-config: + config: input-parameters: - cpu/energy - network/energy @@ -59,13 +59,13 @@ initialize: "operational-carbon": method: Multiply path: builtin - global-config: + config: input-parameters: ["energy", "grid/carbon-intensity"] output-parameter: "carbon-operational" "sum-carbon": path: "builtin" method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -73,7 +73,7 @@ initialize: "sci": path: "builtin" method: Sci - global-config: + config: functional-unit: "component" tree: children: diff --git a/manifests/examples/pipelines/teads-curve.yml b/manifests/examples/pipelines/teads-curve.yml index 1679a0976..f0a650aa9 100644 --- a/manifests/examples/pipelines/teads-curve.yml +++ b/manifests/examples/pipelines/teads-curve.yml @@ -1,47 +1,47 @@ name: carbon-intensity plugin demo -description: +description: tags: initialize: plugins: interpolate: method: Interpolation - path: 'builtin' - global-config: + path: "builtin" + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] - input-parameter: 'cpu/utilization' - output-parameter: 'cpu-factor' + input-parameter: "cpu/utilization" + output-parameter: "cpu-factor" cpu-factor-to-wattage: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-factor", "thermal-design-power"] output-parameter: "cpu-wattage" wattage-times-duration: method: Multiply path: builtin - global-config: + config: input-parameters: ["cpu-wattage", "duration"] output-parameter: "cpu-wattage-times-duration" wattage-to-energy-kwh: method: Divide path: "builtin" - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: method: Divide path: "builtin" - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh diff --git a/manifests/examples/pipelines/zeros.yml b/manifests/examples/pipelines/zeros.yml index f76a2c79f..958aa2b99 100644 --- a/manifests/examples/pipelines/zeros.yml +++ b/manifests/examples/pipelines/zeros.yml @@ -6,7 +6,7 @@ initialize: "sum-zero-and-one": path: "builtin" method: Sum - global-config: + config: input-parameters: - some-value - zero-value @@ -14,7 +14,7 @@ initialize: "sum-zero-and-zero": path: "builtin" method: Sum - global-config: + config: input-parameters: - zero-value - zero-value @@ -22,7 +22,7 @@ initialize: "subtract-one-and-zero": path: "builtin" method: Subtract - global-config: + config: input-parameters: - some-value - zero-value @@ -30,7 +30,7 @@ initialize: "subtract-zero-and-zero": path: "builtin" method: Sum - global-config: + config: input-parameters: - zero-value - zero-value @@ -38,7 +38,7 @@ initialize: "subtract-zero-and-one": path: "builtin" method: Subtract - global-config: + config: input-parameters: - zero-value - some-value @@ -46,61 +46,61 @@ initialize: "coefficient-one-times-zero": path: "builtin" method: Coefficient - global-config: + config: input-parameter: zero-value coefficient: 1 output-parameter: zero-times-one-coefficient "coefficient-zero-times-one": path: "builtin" method: Coefficient - global-config: + config: input-parameter: some-value coefficient: 0 output-parameter: one-times-zero-coefficient "coefficient-zero-times-zero": path: "builtin" method: Coefficient - global-config: + config: input-parameter: zero-value coefficient: 0 output-parameter: zero-times-zero-coefficient "multiply-one-times-zero": path: "builtin" method: Multiply - global-config: + config: input-parameters: ["some-value", "zero-value"] output-parameter: "one-times-zero" "multiply-zero-times-one": path: "builtin" method: Multiply - global-config: + config: input-parameters: ["zero-value", "zero-value"] output-parameter: "zero-times-one" exponent-one-to-zero: method: Exponent - path: 'builtin' - global-config: - input-parameter: 'some-value' + path: "builtin" + config: + input-parameter: "some-value" exponent: 0 - output-parameter: 'one-raised-to-zero-power' + output-parameter: "one-raised-to-zero-power" exponent-zero-to-zero: method: Exponent - path: 'builtin' - global-config: - input-parameter: 'zero-value' + path: "builtin" + config: + input-parameter: "zero-value" exponent: 0 - output-parameter: 'zero-raised-to-zero-power' + output-parameter: "zero-raised-to-zero-power" exponent-zero-to-one: method: Exponent - path: 'builtin' - global-config: - input-parameter: 'zero-value' + path: "builtin" + config: + input-parameter: "zero-value" exponent: 1 - output-parameter: 'zero-raised-to-first-power' + output-parameter: "zero-raised-to-first-power" "sci": path: "builtin" method: Sci - global-config: + config: functional-unit: "zero-value" tree: children: diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index ed4c00385..c6e8284ca 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -12,7 +12,7 @@ initialize: interpolate: method: Interpolation path: builtin - global-config: + config: method: linear x: - 0 @@ -29,7 +29,7 @@ initialize: cpu-factor-to-wattage: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -37,7 +37,7 @@ initialize: wattage-times-duration: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu-wattage - duration @@ -45,21 +45,21 @@ initialize: wattage-to-energy-kwh: method: Divide path: builtin - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: method: Divide path: builtin - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: method: Divide path: builtin - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -69,7 +69,7 @@ initialize: operational-carbon: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu-energy-kwh - grid/carbon-intensity @@ -77,12 +77,12 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: requests time-sync: method: TimeSync path: builtin - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/outputs/bugs/input-error-missing-duration.yaml b/manifests/outputs/bugs/input-error-missing-duration.yaml index 1006c1c0c..3119c72d9 100644 --- a/manifests/outputs/bugs/input-error-missing-duration.yaml +++ b/manifests/outputs/bugs/input-error-missing-duration.yaml @@ -8,7 +8,7 @@ initialize: interpolate: method: Interpolation path: builtin - global-config: + config: method: linear x: - 0 diff --git a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml index d137975b5..a3c760849 100644 --- a/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml +++ b/manifests/outputs/bugs/mock-observations-failure-duration-is-zero.yaml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: builtin - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 0 @@ -69,7 +69,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.22.4 - error: "InputValidationError: \"duration\" parameter is number must be greater than 0. Error code: too_small." + error: 'InputValidationError: "duration" parameter is number must be greater than 0. Error code: too_small.' tree: children: child: diff --git a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml index fef0fa246..39227bd84 100644 --- a/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml +++ b/manifests/outputs/bugs/pipeline-error-naming-mismatch.yaml @@ -8,7 +8,7 @@ initialize: interpolate: method: Interpolation path: builtin - global-config: + config: method: linear x: - 0 diff --git a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml index 7a0060013..bb47be31e 100644 --- a/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml +++ b/manifests/outputs/bugs/pipeline-error-uninitialized-plugin.yaml @@ -8,7 +8,7 @@ initialize: interpolate: method: Interpolation path: builtin - global-config: + config: method: linear x: - 0 diff --git a/manifests/outputs/bugs/pipeline-ordering-error.yaml b/manifests/outputs/bugs/pipeline-ordering-error.yaml index d1bd27d27..7df81f61a 100644 --- a/manifests/outputs/bugs/pipeline-ordering-error.yaml +++ b/manifests/outputs/bugs/pipeline-ordering-error.yaml @@ -8,7 +8,7 @@ initialize: interpolate: method: Interpolation path: builtin - global-config: + config: method: linear x: - 0 @@ -25,7 +25,7 @@ initialize: cpu-factor-to-wattage: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -33,7 +33,7 @@ initialize: wattage-times-duration: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu-wattage - duration @@ -41,21 +41,21 @@ initialize: wattage-to-energy-kwh: method: Divide path: builtin - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: method: Divide path: builtin - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: method: Divide path: builtin - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh diff --git a/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml b/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml index 7b6051dce..e8239c914 100644 --- a/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml +++ b/manifests/outputs/builtins/coefficient/failure-invalid-config-input-param.yaml @@ -1,12 +1,12 @@ name: coefficient-demo -description: failure with ivalid `global-config.input-parameter` +description: failure with ivalid `config.input-parameter` tags: null initialize: plugins: coefficient: method: Coefficient path: builtin - global-config: + config: input-parameter: 4 coefficient: 3 output-parameter: carbon-product diff --git a/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml b/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml index 847e984e7..9482011f8 100644 --- a/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml +++ b/manifests/outputs/builtins/coefficient/failure-output-param-is-null.yaml @@ -6,7 +6,7 @@ initialize: coefficient: method: Coefficient path: builtin - global-config: + config: input-parameter: carbon coefficient: 3 output-parameter: null diff --git a/manifests/outputs/builtins/coefficient/success.yaml b/manifests/outputs/builtins/coefficient/success.yaml index 14a235709..4ea679a9a 100644 --- a/manifests/outputs/builtins/coefficient/success.yaml +++ b/manifests/outputs/builtins/coefficient/success.yaml @@ -6,7 +6,7 @@ initialize: coefficient: path: builtin method: Coefficient - global-config: + config: input-parameter: carbon coefficient: 3 output-parameter: carbon-product diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml index 6945e6012..e8cc6170e 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-instance-type.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 333d9e1ce..09539ee9a 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml index 37fab5816..a4e5cdf21 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/success.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml index 842080a77..e1128e36b 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-column.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: builtin - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml index 32ca690d9..341a17aca 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: method: CSVLookup path: builtin - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml index 2f6f23dcf..7fc116809 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/success-renaming.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml index f8bd9fdba..bb099e8ee 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/success.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml index ce268cd02..1b97a0c30 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-missing-input-param.yaml @@ -6,7 +6,7 @@ initialize: tdp-finder: method: CSVLookup path: builtin - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml index 28dc0b1a0..aec123ef4 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/failure-unsupported-physical-processor.yaml @@ -6,7 +6,7 @@ initialize: tdp-finder: method: CSVLookup path: builtin - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: diff --git a/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml b/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml index f085664ff..1d8dd9797 100644 --- a/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml +++ b/manifests/outputs/builtins/csv-lookup/tdp-finder/success.yaml @@ -6,7 +6,7 @@ initialize: tdp-finder: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/tdp-data-1.csv query: diff --git a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml index b1149c505..fd0c50cce 100644 --- a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml +++ b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml @@ -1,12 +1,12 @@ name: divide -description: failure when `global-config.denominator` is string +description: failure when `config.denominator` is string tags: null initialize: plugins: divide: method: Divide path: builtin - global-config: + config: numerator: cpu/utilization denominator: test output: cpu/divided-two diff --git a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml index 235b3395a..a59e2f962 100644 --- a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml @@ -6,7 +6,7 @@ initialize: divide: method: Divide path: builtin - global-config: + config: denominator: 2 output: cpu/number-cores execution: diff --git a/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml b/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml index 25033c32c..940b042e1 100644 --- a/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml +++ b/manifests/outputs/builtins/divide/success-denominator-equal-zero.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -17,7 +17,7 @@ initialize: divide: path: builtin method: Divide - global-config: + config: numerator: vcpus-allocated denominator: 0 output: cpu/number-cores diff --git a/manifests/outputs/builtins/divide/success.yaml b/manifests/outputs/builtins/divide/success.yaml index f7bab8b04..625e81d4e 100644 --- a/manifests/outputs/builtins/divide/success.yaml +++ b/manifests/outputs/builtins/divide/success.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -17,7 +17,7 @@ initialize: divide: path: builtin method: Divide - global-config: + config: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores diff --git a/manifests/outputs/builtins/exponent/success.yaml b/manifests/outputs/builtins/exponent/success.yaml index 8586b57f6..04ac4e6de 100644 --- a/manifests/outputs/builtins/exponent/success.yaml +++ b/manifests/outputs/builtins/exponent/success.yaml @@ -6,7 +6,7 @@ initialize: exponent: path: builtin method: Exponent - global-config: + config: input-parameter: cpu/energy exponent: 2 output-parameter: energy diff --git a/manifests/outputs/builtins/interpolation/interpolation.yaml b/manifests/outputs/builtins/interpolation/interpolation.yaml index 2569b5eb4..a67ab0a1e 100644 --- a/manifests/outputs/builtins/interpolation/interpolation.yaml +++ b/manifests/outputs/builtins/interpolation/interpolation.yaml @@ -6,7 +6,7 @@ initialize: interpolation: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 diff --git a/manifests/outputs/builtins/interpolation/success.yaml b/manifests/outputs/builtins/interpolation/success.yaml index 80def13d9..5eb41320d 100644 --- a/manifests/outputs/builtins/interpolation/success.yaml +++ b/manifests/outputs/builtins/interpolation/success.yaml @@ -6,7 +6,7 @@ initialize: interpolation: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml index 272d9940e..43887d3b6 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -1,6 +1,6 @@ name: mock-observation-demo description: >- - failure with `global-config->generators->randint->cpu/utilization->min` is + failure with `config->generators->randint->cpu/utilization->min` is greater than `max` tags: null initialize: @@ -9,7 +9,7 @@ initialize: kind: plugin method: MockObservations path: builtin - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml index e7c7e6180..3ca8f7af9 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: builtin - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml b/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml index 86f4afd9e..733ac0a97 100644 --- a/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-missing-timestamp-from-param.yaml @@ -7,7 +7,7 @@ initialize: kind: plugin method: MockObservations path: builtin - global-config: + config: timestamp-to: 2023-07-06T00:10 duration: 60 components: diff --git a/manifests/outputs/builtins/mock-observations/success.yaml b/manifests/outputs/builtins/mock-observations/success.yaml index bcc5ee034..c2ee71085 100644 --- a/manifests/outputs/builtins/mock-observations/success.yaml +++ b/manifests/outputs/builtins/mock-observations/success.yaml @@ -6,7 +6,7 @@ initialize: mock-observations: path: builtin method: MockObservations - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 @@ -33,20 +33,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-08-02T15:04:18.262Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.16' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.16" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -75,284 +75,284 @@ tree: observe: - mock-observations inputs: - - timestamp: '2023-07-06T00:00:00.000Z' + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:01:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:02:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:03:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:04:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:05:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:06:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:07:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:08:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:09:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:00:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:01:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:02:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:03:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:04:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:05:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:06:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:07:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:08:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:09:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' + cpu/utilization: "*" + memory/utilization: "*" outputs: - - timestamp: '2023-07-06T00:00:00.000Z' + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:01:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:02:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:03:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:04:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:05:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:06:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:07:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:08:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:09:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:00:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:00:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:01:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:01:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:02:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:02:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:03:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:03:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:04:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:04:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:05:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:05:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:06:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:06:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:07:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:07:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:08:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:08:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' - - timestamp: '2023-07-06T00:09:00.000Z' + cpu/utilization: "*" + memory/utilization: "*" + - timestamp: "2023-07-06T00:09:00.000Z" duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val - cpu/utilization: '*' - memory/utilization: '*' + cpu/utilization: "*" + memory/utilization: "*" diff --git a/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml b/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml index 80738e80c..04388331f 100644 --- a/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml +++ b/manifests/outputs/builtins/multiply/failure-input-parameter-is-missing.yaml @@ -6,7 +6,7 @@ initialize: multiply: method: Multiply path: builtin - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml b/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml index 359e25a06..60daf4c76 100644 --- a/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml +++ b/manifests/outputs/builtins/multiply/success-with-multiple-inputs.yaml @@ -6,7 +6,7 @@ initialize: multiply: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/multiply/success.yaml b/manifests/outputs/builtins/multiply/success.yaml index 1f93a9140..62b8e4be4 100644 --- a/manifests/outputs/builtins/multiply/success.yaml +++ b/manifests/outputs/builtins/multiply/success.yaml @@ -6,7 +6,7 @@ initialize: multiply: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/regex/failure-missing-input-param.yaml b/manifests/outputs/builtins/regex/failure-missing-input-param.yaml index cd578218f..44505edde 100644 --- a/manifests/outputs/builtins/regex/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/regex/failure-missing-input-param.yaml @@ -6,7 +6,7 @@ initialize: regex: method: Regex path: builtin - global-config: + config: parameter: physical-processor match: ^(.*), output: cpu/name diff --git a/manifests/outputs/builtins/regex/success.yaml b/manifests/outputs/builtins/regex/success.yaml index 22988eead..c4f0838bd 100644 --- a/manifests/outputs/builtins/regex/success.yaml +++ b/manifests/outputs/builtins/regex/success.yaml @@ -6,7 +6,7 @@ initialize: regex: path: builtin method: Regex - global-config: + config: parameter: physical-processor match: ^(.*), output: cpu/name diff --git a/manifests/outputs/builtins/sci/failure-missing-input-param.yaml b/manifests/outputs/builtins/sci/failure-missing-input-param.yaml index b0fbce2f8..08c482991 100644 --- a/manifests/outputs/builtins/sci/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/sci/failure-missing-input-param.yaml @@ -7,7 +7,7 @@ initialize: kind: plugin method: Sci path: builtin - global-config: + config: functional-unit: requests execution: status: fail diff --git a/manifests/outputs/builtins/sci/success.yaml b/manifests/outputs/builtins/sci/success.yaml index 9f36fc9bd..1f384be28 100644 --- a/manifests/outputs/builtins/sci/success.yaml +++ b/manifests/outputs/builtins/sci/success.yaml @@ -6,7 +6,7 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: requests execution: command: >- diff --git a/manifests/outputs/builtins/shell/failure-invalid-command.yaml b/manifests/outputs/builtins/shell/failure-invalid-command.yaml index 97d8bb6af..9c1c3b84b 100644 --- a/manifests/outputs/builtins/shell/failure-invalid-command.yaml +++ b/manifests/outputs/builtins/shell/failure-invalid-command.yaml @@ -1,12 +1,12 @@ name: shell -description: falure with `global-config.command` being number instead od string +description: falure with `config.command` being number instead od string tags: null initialize: plugins: shell: method: Shell path: builtin - global-config: + config: command: 1000 execution: status: fail diff --git a/manifests/outputs/builtins/shell/success.yaml b/manifests/outputs/builtins/shell/success.yaml index b85cbfb95..cd7a41989 100644 --- a/manifests/outputs/builtins/shell/success.yaml +++ b/manifests/outputs/builtins/shell/success.yaml @@ -6,7 +6,7 @@ initialize: shell: path: builtin method: Shell - global-config: + config: command: python3 /usr/local/bin/sampler execution: command: >- diff --git a/manifests/outputs/builtins/subtract/success.yaml b/manifests/outputs/builtins/subtract/success.yaml index 5eb0a7bd3..bcc9c1ae3 100644 --- a/manifests/outputs/builtins/subtract/success.yaml +++ b/manifests/outputs/builtins/subtract/success.yaml @@ -6,7 +6,7 @@ initialize: subtract: path: builtin method: Subtract - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/sum/failure-missing-input-param.yaml b/manifests/outputs/builtins/sum/failure-missing-input-param.yaml index e2aaf8158..3eb324c4a 100644 --- a/manifests/outputs/builtins/sum/failure-missing-input-param.yaml +++ b/manifests/outputs/builtins/sum/failure-missing-input-param.yaml @@ -1,12 +1,12 @@ name: sum -description: failure with `inputs[0]` misses one of `global-config.input-parameters` +description: failure with `inputs[0]` misses one of `config.input-parameters` tags: null initialize: plugins: sum: method: Sum path: builtin - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/sum/failure-missing-output-param.yaml b/manifests/outputs/builtins/sum/failure-missing-output-param.yaml index d7a4d9302..f72ef14f8 100644 --- a/manifests/outputs/builtins/sum/failure-missing-output-param.yaml +++ b/manifests/outputs/builtins/sum/failure-missing-output-param.yaml @@ -1,12 +1,12 @@ name: sum -description: missing `output-parameter` in global-config +description: missing `output-parameter` in config tags: null initialize: plugins: sum: method: Sum path: builtin - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/sum/success.yaml b/manifests/outputs/builtins/sum/success.yaml index 6b5b4d973..e044ddb4b 100644 --- a/manifests/outputs/builtins/sum/success.yaml +++ b/manifests/outputs/builtins/sum/success.yaml @@ -6,7 +6,7 @@ initialize: sum: path: builtin method: Sum - global-config: + config: input-parameters: - cpu/energy - network/energy diff --git a/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml b/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml index bb5ae79fb..e0c633680 100644 --- a/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml +++ b/manifests/outputs/builtins/time-sync/failure-config-start-later-end.yaml @@ -1,14 +1,14 @@ name: time-sync description: >- - failure with `global-config.start-time` being later than - `global-config.end-time` + failure with `config.start-time` being later than + `config.end-time` tags: null initialize: plugins: time-sync: method: TimeSync path: builtin - global-config: + config: start-time: "2023-12-12T00:01:00.000Z" end-time: "2023-12-12T00:00:00.000Z" interval: 5 diff --git a/manifests/outputs/builtins/time-sync/success.yaml b/manifests/outputs/builtins/time-sync/success.yaml index 7b1d6bbb8..36d6c10da 100644 --- a/manifests/outputs/builtins/time-sync/success.yaml +++ b/manifests/outputs/builtins/time-sync/success.yaml @@ -6,7 +6,7 @@ initialize: time-sync: path: builtin method: TimeSync - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml index aef8ef6c5..e369846ff 100644 --- a/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml +++ b/manifests/outputs/features/aggregate-failure-invalid-metrics.yaml @@ -9,7 +9,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml index 2dfc9fe80..fc53a6859 100644 --- a/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml +++ b/manifests/outputs/features/aggregate-failure-missing-metric-in-inputs.yaml @@ -9,7 +9,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index d595d5bdb..888ae1441 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -9,7 +9,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 9213522af..3ba96d0b1 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -9,7 +9,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index cb9ed29dc..96c72adf2 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -9,7 +9,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: diff --git a/manifests/outputs/pipelines/cloud-metadata-divide.yaml b/manifests/outputs/pipelines/cloud-metadata-divide.yaml index 02ff19b86..40afe668c 100644 --- a/manifests/outputs/pipelines/cloud-metadata-divide.yaml +++ b/manifests/outputs/pipelines/cloud-metadata-divide.yaml @@ -6,7 +6,7 @@ initialize: cloud-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: @@ -17,7 +17,7 @@ initialize: divide: path: builtin method: Divide - global-config: + config: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores diff --git a/manifests/outputs/pipelines/generics.yaml b/manifests/outputs/pipelines/generics.yaml index 613a65f83..addba9510 100644 --- a/manifests/outputs/pipelines/generics.yaml +++ b/manifests/outputs/pipelines/generics.yaml @@ -8,14 +8,14 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -25,7 +25,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -33,7 +33,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -41,35 +41,35 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh coefficient: path: builtin method: Coefficient - global-config: + config: input-parameter: cpu-energy-kwh coefficient: 2 output-parameter: energy-doubled multiply: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu/utilization - duration @@ -83,20 +83,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-17T20:30:54.004Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -136,28 +136,28 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 10 energy: 5 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 10 energy: 5 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 10 energy: 5 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -165,7 +165,7 @@ tree: network/energy: 10 energy: 5 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 @@ -183,7 +183,7 @@ tree: cpu-energy-kwh: 0.0000026041666666666666 energy-doubled: 0.000005208333333333333 cpu-times-duration: 50 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 @@ -201,7 +201,7 @@ tree: cpu-energy-kwh: 0.000007421875 energy-doubled: 0.00001484375 cpu-times-duration: 100 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 @@ -219,7 +219,7 @@ tree: cpu-energy-kwh: 0.000009084201388888889 energy-doubled: 0.000018168402777777778 cpu-times-duration: 105 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west diff --git a/manifests/outputs/pipelines/instance-metadata.yaml b/manifests/outputs/pipelines/instance-metadata.yaml index 369d54c27..b38876e08 100644 --- a/manifests/outputs/pipelines/instance-metadata.yaml +++ b/manifests/outputs/pipelines/instance-metadata.yaml @@ -6,16 +6,16 @@ initialize: cloud-instance-metadata: path: builtin method: CSVLookup - global-config: + config: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv query: instance-class: cloud/instance-type - output: '*' + output: "*" extract-processor-name: path: builtin method: Regex - global-config: + config: parameter: cpu-model-name match: /^([^,])+/g output: cpu/name @@ -28,20 +28,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-19T06:31:27.411Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml index 04eb881ec..efe31175e 100644 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ b/manifests/outputs/pipelines/mock-obs-time-sync.yaml @@ -6,7 +6,7 @@ initialize: mock-observations: path: builtin method: MockObservations - global-config: + config: timestamp-from: 2023-12-12T00:00 timestamp-to: 2023-12-12T00:10 duration: 60 @@ -40,7 +40,7 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 @@ -63,7 +63,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -77,7 +77,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -85,14 +85,14 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -109,14 +109,14 @@ initialize: correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh time-sync: path: builtin method: TimeSync - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 @@ -184,83 +184,83 @@ tree: vcpus-total: 8 vcpus-allocated: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:01:00.000Z' + - timestamp: "2023-12-12T00:01:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:02:00.000Z' + - timestamp: "2023-12-12T00:02:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:03:00.000Z' + - timestamp: "2023-12-12T00:03:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:04:00.000Z' + - timestamp: "2023-12-12T00:04:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:05:00.000Z' + - timestamp: "2023-12-12T00:05:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:06:00.000Z' + - timestamp: "2023-12-12T00:06:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:07:00.000Z' + - timestamp: "2023-12-12T00:07:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:08:00.000Z' + - timestamp: "2023-12-12T00:08:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - - timestamp: '2023-12-12T00:09:00.000Z' + - timestamp: "2023-12-12T00:09:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 60 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 @@ -269,181 +269,181 @@ tree: cloud/instance-type: A1 cloud/region: uk-west duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:05.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:10.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:15.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:20.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:25.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:30.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:35.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:40.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:45.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:50.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:00:55.000Z" duration: 5 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 80 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" - timestamp: "2023-12-12T00:01:00.000Z" duration: 1 - cpu/utilization: '*' + cpu/utilization: "*" cloud/instance-type: A1 cloud/region: uk-west cpu/thermal-design-power: 100 vcpus-total: 8 vcpus-allocated: 1 - cpu-factor: '*' - cpu-wattage: '*' - cpu-wattage-times-duration: '*' - cpu-energy-raw: '*' - vcpu-ratio: '*' - cpu-energy-kwh: '*' + cpu-factor: "*" + cpu-wattage: "*" + cpu-wattage-times-duration: "*" + cpu-energy-raw: "*" + vcpu-ratio: "*" + cpu-energy-kwh: "*" diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 792f41243..f32120275 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -13,7 +13,7 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 @@ -41,7 +41,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -64,7 +64,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -72,7 +72,7 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw @@ -90,7 +90,7 @@ initialize: calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio @@ -103,7 +103,7 @@ initialize: correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -113,7 +113,7 @@ initialize: operational-carbon: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-energy-kwh - grid/carbon-intensity @@ -136,7 +136,7 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: requests parameter-metadata: inputs: @@ -147,7 +147,7 @@ initialize: sum-carbon: path: builtin method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -170,7 +170,7 @@ initialize: time-sync: path: builtin method: TimeSync - global-config: + config: start-time: "2023-12-12T00:00:00.000Z" end-time: "2023-12-12T00:01:00.000Z" interval: 5 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index 05e28edd4..abefd4adf 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -8,14 +8,14 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -25,7 +25,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -33,7 +33,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -41,21 +41,21 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -65,7 +65,7 @@ initialize: operational-carbon: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-energy-kwh - grid/carbon-intensity @@ -73,12 +73,12 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: component sum-carbon: path: builtin method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -92,20 +92,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-19T06:32:50.994Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -152,32 +152,32 @@ tree: vcpus-allocated: 1 component: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 network/energy: 0.000001 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 @@ -201,7 +201,7 @@ tree: carbon-operational: 0.0020833333333333333 carbon: 0.002085358954845256 sci: 0.002085358954845256 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 @@ -225,7 +225,7 @@ tree: carbon-operational: 0.0059375 carbon: 0.005947628107559615 sci: 0.005947628107559615 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 @@ -249,7 +249,7 @@ tree: carbon-operational: 0.007267361111111111 carbon: 0.007281540461694571 sci: 0.007281540461694571 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml index c4fa641c2..99eed0ff6 100644 --- a/manifests/outputs/pipelines/sci.yaml +++ b/manifests/outputs/pipelines/sci.yaml @@ -8,14 +8,14 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -25,7 +25,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - cpu/thermal-design-power @@ -33,7 +33,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -41,28 +41,28 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu/energy sum-energy-components: path: builtin method: Sum - global-config: + config: input-parameters: - cpu/energy - network/energy @@ -73,7 +73,7 @@ initialize: operational-carbon: path: builtin method: Multiply - global-config: + config: input-parameters: - energy - grid/carbon-intensity @@ -81,7 +81,7 @@ initialize: sum-carbon: path: builtin method: Sum - global-config: + config: input-parameters: - carbon-operational - carbon-embodied @@ -89,7 +89,7 @@ initialize: sci: path: builtin method: Sci - global-config: + config: functional-unit: component execution: command: >- @@ -99,20 +99,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-19T06:34:45.027Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -162,32 +162,32 @@ tree: resources-total: vcpus-total component: 1 inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 network/energy: 0.000001 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" cloud/instance-type: A1 cloud/region: uk-west duration: 1 @@ -214,7 +214,7 @@ tree: carbon-operational: 0.004966666666666666 carbon: 0.004970717909690512 sci: 0.004970717909690512 - - timestamp: '2023-12-12T00:00:01.000Z' + - timestamp: "2023-12-12T00:00:01.000Z" duration: 5 cpu/utilization: 20 cloud/instance-type: A1 @@ -241,7 +241,7 @@ tree: carbon-operational: 0.012674999999999999 carbon: 0.012695256215119228 sci: 0.012695256215119228 - - timestamp: '2023-12-12T00:00:06.000Z' + - timestamp: "2023-12-12T00:00:06.000Z" duration: 7 cpu/utilization: 15 cloud/instance-type: A1 @@ -268,7 +268,7 @@ tree: carbon-operational: 0.015334722222222222 carbon: 0.015363080923389142 sci: 0.015363080923389142 - - timestamp: '2023-12-12T00:00:13.000Z' + - timestamp: "2023-12-12T00:00:13.000Z" duration: 30 cloud/instance-type: A1 cloud/region: uk-west diff --git a/manifests/outputs/pipelines/teads-curve.yaml b/manifests/outputs/pipelines/teads-curve.yaml index 26885e1c7..ea3cab0ef 100644 --- a/manifests/outputs/pipelines/teads-curve.yaml +++ b/manifests/outputs/pipelines/teads-curve.yaml @@ -6,14 +6,14 @@ initialize: interpolate: path: builtin method: Interpolation - global-config: + config: method: linear x: - 0 - 10 - 50 - 100 - 'y': + "y": - 0.12 - 0.32 - 0.75 @@ -23,7 +23,7 @@ initialize: cpu-factor-to-wattage: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-factor - thermal-design-power @@ -31,7 +31,7 @@ initialize: wattage-times-duration: path: builtin method: Multiply - global-config: + config: input-parameters: - cpu-wattage - duration @@ -39,21 +39,21 @@ initialize: wattage-to-energy-kwh: path: builtin method: Divide - global-config: + config: numerator: cpu-wattage-times-duration denominator: 3600000 output: cpu-energy-raw calculate-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: vcpus-total denominator: vcpus-allocated output: vcpu-ratio correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide - global-config: + config: numerator: cpu-energy-raw denominator: vcpu-ratio output: cpu-energy-kwh @@ -66,20 +66,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-19T06:35:33.728Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 diff --git a/manifests/outputs/pipelines/zeros.yaml b/manifests/outputs/pipelines/zeros.yaml index 3efd3c0fb..d7513f077 100644 --- a/manifests/outputs/pipelines/zeros.yaml +++ b/manifests/outputs/pipelines/zeros.yaml @@ -8,7 +8,7 @@ initialize: sum-zero-and-one: path: builtin method: Sum - global-config: + config: input-parameters: - some-value - zero-value @@ -16,7 +16,7 @@ initialize: sum-zero-and-zero: path: builtin method: Sum - global-config: + config: input-parameters: - zero-value - zero-value @@ -24,7 +24,7 @@ initialize: subtract-one-and-zero: path: builtin method: Subtract - global-config: + config: input-parameters: - some-value - zero-value @@ -32,7 +32,7 @@ initialize: subtract-zero-and-zero: path: builtin method: Sum - global-config: + config: input-parameters: - zero-value - zero-value @@ -40,7 +40,7 @@ initialize: subtract-zero-and-one: path: builtin method: Subtract - global-config: + config: input-parameters: - zero-value - some-value @@ -48,28 +48,28 @@ initialize: coefficient-one-times-zero: path: builtin method: Coefficient - global-config: + config: input-parameter: zero-value coefficient: 1 output-parameter: zero-times-one-coefficient coefficient-zero-times-one: path: builtin method: Coefficient - global-config: + config: input-parameter: some-value coefficient: 0 output-parameter: one-times-zero-coefficient coefficient-zero-times-zero: path: builtin method: Coefficient - global-config: + config: input-parameter: zero-value coefficient: 0 output-parameter: zero-times-zero-coefficient multiply-one-times-zero: path: builtin method: Multiply - global-config: + config: input-parameters: - some-value - zero-value @@ -77,7 +77,7 @@ initialize: multiply-zero-times-one: path: builtin method: Multiply - global-config: + config: input-parameters: - zero-value - zero-value @@ -85,28 +85,28 @@ initialize: exponent-one-to-zero: path: builtin method: Exponent - global-config: + config: input-parameter: some-value exponent: 0 output-parameter: one-raised-to-zero-power exponent-zero-to-zero: path: builtin method: Exponent - global-config: + config: input-parameter: zero-value exponent: 0 output-parameter: zero-raised-to-zero-power exponent-zero-to-one: path: builtin method: Exponent - global-config: + config: input-parameter: zero-value exponent: 1 output-parameter: zero-raised-to-first-power sci: path: builtin method: Sci - global-config: + config: functional-unit: zero-value execution: command: >- @@ -116,20 +116,20 @@ execution: environment: if-version: 0.5.0 os: macOS - os-version: '14.5' + os-version: "14.5" node-version: 18.14.2 date-time: 2024-07-19T06:36:00.790Z (UTC) dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.10' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' + - "@babel/core@7.22.10" + - "@babel/preset-typescript@7.23.3" + - "@commitlint/cli@18.6.0" + - "@commitlint/config-conventional@18.6.0" + - "@grnsft/if-core@0.0.10" + - "@jest/globals@29.7.0" + - "@types/jest@29.5.8" + - "@types/js-yaml@4.0.9" + - "@types/luxon@3.4.2" + - "@types/node@20.9.0" - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -171,13 +171,13 @@ tree: - exponent-zero-to-zero - sci inputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 some-value: 1 zero-value: 0 carbon: 10 outputs: - - timestamp: '2023-12-12T00:00:00.000Z' + - timestamp: "2023-12-12T00:00:00.000Z" duration: 1 some-value: 1 zero-value: 0 diff --git a/src/__mocks__/builtins/export-yaml.ts b/src/__mocks__/builtins/export-yaml.ts index b323de7b5..5ebf9cb1b 100644 --- a/src/__mocks__/builtins/export-yaml.ts +++ b/src/__mocks__/builtins/export-yaml.ts @@ -124,14 +124,14 @@ export const context: Context = { 'teads-curve': { path: '@grnsft/if-unofficial-plugins', method: 'TeadsCurve', - 'global-config': { + config: { interpolation: 'spline', }, }, sum: { path: '@grnsft/if-plugins', method: 'Sum', - 'global-config': { + config: { 'input-parameters': ['cpu/energy', 'network/energy'], 'output-parameter': "carbon-plus-energy'", }, @@ -147,7 +147,7 @@ export const context: Context = { sci: { path: '@grnsft/if-plugins', method: 'Sci', - 'global-config': { + config: { 'functional-unit': 'requests', }, }, diff --git a/src/__mocks__/mock-manifest.yaml b/src/__mocks__/mock-manifest.yaml index 549b2c14f..1b9d38ac6 100644 --- a/src/__mocks__/mock-manifest.yaml +++ b/src/__mocks__/mock-manifest.yaml @@ -6,7 +6,7 @@ initialize: memory-energy-from-memory-util: path: builtin method: Coefficient - global-config: + config: input-parameter: memory/utilization coefficient: 0.0001 output-parameter: memory/energy From 3f0d624f1eb9498eb7e9c5201af780b0b8478640 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 20:07:45 +0400 Subject: [PATCH 629/863] fix(config): rename global-config to config in the if-env template --- src/if-env/config/env-template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-env/config/env-template.yml b/src/if-env/config/env-template.yml index ec412c47b..4dd25ad63 100644 --- a/src/if-env/config/env-template.yml +++ b/src/if-env/config/env-template.yml @@ -6,7 +6,7 @@ initialize: memory-energy-from-memory-util: # you can name this any way you like! method: Coefficient # the name of the function exported from the plugin path: "builtin" # the import path - global-config: # any config required by the plugin + config: # any config required by the plugin input-parameter: "memory/utilization" coefficient: 0.0001 #kwH/GB output-parameter: "memory/energy" From c198e657054cde59efd97897161934838567ac8c Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 20:09:20 +0400 Subject: [PATCH 630/863] test(builtins): renam global-config to config --- src/__tests__/if-merge/util/helpers.test.ts | 4 +- .../if-run/builtins/CommonGenerator.test.ts | 4 +- .../if-run/builtins/RandIntGenerator.test.ts | 4 +- .../if-run/builtins/coefficient.test.ts | 12 ++-- .../if-run/builtins/copy-param.test.ts | 20 +++--- .../if-run/builtins/csv-lookup.test.ts | 68 +++++++++---------- src/__tests__/if-run/builtins/divide.test.ts | 32 ++++----- .../if-run/builtins/exponent.test.ts | 4 +- .../if-run/builtins/interpolation.test.ts | 42 ++++++------ .../if-run/builtins/multiply.test.ts | 4 +- src/__tests__/if-run/builtins/regex.test.ts | 24 +++---- .../if-run/builtins/subtract.test.ts | 4 +- src/__tests__/if-run/builtins/sum.test.ts | 12 ++-- .../if-run/builtins/time-converter.test.ts | 12 ++-- .../if-run/builtins/time-sync.test.ts | 4 +- src/__tests__/if-run/lib/environment.test.ts | 2 +- src/__tests__/if-run/lib/initialize.test.ts | 14 ++-- 17 files changed, 123 insertions(+), 143 deletions(-) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index 1f4c0609f..fe592c94b 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -27,7 +27,7 @@ jest.mock('../../../if-run/builtins/export-yaml', () => ({ multiply: { path: 'builtin', method: 'Multiply', - 'global-config': { + config: { 'input-parameters': ['cpu/utilization', 'duration'], 'output-parameter': 'cpu-times-duration', }, @@ -103,7 +103,7 @@ describe('if-merge/util/helpers: ', () => { multiply: { path: 'builtin', method: 'Multiply', - 'global-config': { + config: { 'input-parameters': ['cpu/utilization', 'duration'], 'output-parameter': 'cpu-times-duration', }, diff --git a/src/__tests__/if-run/builtins/CommonGenerator.test.ts b/src/__tests__/if-run/builtins/CommonGenerator.test.ts index 87b8457a8..820c2a9c6 100644 --- a/src/__tests__/if-run/builtins/CommonGenerator.test.ts +++ b/src/__tests__/if-run/builtins/CommonGenerator.test.ts @@ -5,7 +5,7 @@ import {CommonGenerator} from '../../../if-run/builtins/mock-observations/helper import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; describe('builtins/mock-observations/CommonGenerator: ', () => { describe('initialize: ', () => { @@ -17,7 +17,7 @@ describe('builtins/mock-observations/CommonGenerator: ', () => { try { commonGenerator.next([]); } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); } }); }); diff --git a/src/__tests__/if-run/builtins/RandIntGenerator.test.ts b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts index 05fdb37f2..6c650425b 100644 --- a/src/__tests__/if-run/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts @@ -5,7 +5,7 @@ import {RandIntGenerator} from '../../../if-run/builtins/mock-observations/helpe import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError} = ERRORS; -const {INVALID_NAME, MISSING_MIN_MAX, MISSING_GLOBAL_CONFIG} = STRINGS; +const {INVALID_NAME, MISSING_MIN_MAX, MISSING_CONFIG} = STRINGS; describe('builtins/mock-observations/RandIntGenerator: ', () => { describe('initialize', () => { @@ -23,7 +23,7 @@ describe('builtins/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('generator-name', {}); } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 8d99c3e87..7244454b1 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -5,11 +5,11 @@ import {Coefficient} from '../../../if-run/builtins/coefficient'; import {STRINGS} from '../../../if-run/config'; const {InputValidationError, GlobalConfigError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { describe('Coefficient: ', () => { - const globalConfig = { + const config = { 'input-parameter': 'carbon', coefficient: 3, 'output-parameter': 'carbon-product', @@ -18,7 +18,7 @@ describe('builtins/coefficient: ', () => { inputs: {}, outputs: {}, }; - const coefficient = Coefficient(globalConfig, parametersMetadata); + const coefficient = Coefficient(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -53,7 +53,7 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when global config is not provided.', () => { + it('throws an error when config is not provided.', () => { const config = undefined; const coefficient = Coefficient(config!, parametersMetadata); @@ -68,9 +68,7 @@ describe('builtins/coefficient: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 952546505..e2c5c3db0 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -5,11 +5,11 @@ import {Copy} from '../../../if-run/builtins/copy-param'; import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError, InputValidationError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; describe('builtins/copy: ', () => { describe('Copy: ', () => { - const globalConfig = { + const config = { 'keep-existing': true, from: 'original', to: 'copy', @@ -18,7 +18,7 @@ describe('builtins/copy: ', () => { inputs: {}, outputs: {}, }; - const copy = Copy(globalConfig, parametersMetadata); + const copy = Copy(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -51,7 +51,7 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when global config is not provided.', () => { + it('throws an error when config is not provided.', () => { const config = undefined; const copy = Copy(config!, parametersMetadata); @@ -66,19 +66,17 @@ describe('builtins/copy: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); it('throws an error on missing params in input.', () => { - const globalConfig = { + const config = { 'keep-existing': true, from: 'original', to: 'copy', }; - const copy = Copy(globalConfig, parametersMetadata); + const copy = Copy(config, parametersMetadata); expect.assertions(1); try { @@ -98,12 +96,12 @@ describe('builtins/copy: ', () => { }); it('does not persist the original value when keep-existing==false.', () => { expect.assertions(1); - const globalConfig = { + const config = { 'keep-existing': false, from: 'original', to: 'copy', }; - const copy = Copy(globalConfig, parametersMetadata); + const copy = Copy(config, 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 49e4d45bb..be0ddb35a 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -16,7 +16,7 @@ const { MissingCSVColumnError, CSVParseError, } = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; +const {MISSING_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { const parametersMetadata = { @@ -32,14 +32,14 @@ describe('builtins/CSVLookup: ', () => { describe('init: ', () => { it('successfully initalized.', () => { - const globalConfig = { + const config = { filepath: '', query: { 'cpu-cores-available': 'cpu/available', }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); expect(csvLookup).toHaveProperty('metadata'); expect(csvLookup).toHaveProperty('execute'); }); @@ -48,7 +48,7 @@ describe('builtins/CSVLookup: ', () => { describe('execute(): ', () => { it('successfully applies CSVLookup `url` strategy to given input.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', query: { @@ -58,12 +58,12 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, 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 16,16,AWS,AWS Graviton,150.00,N/A,N/A,AWS Graviton (ARM),a1.4xlarge,EBS-Only,32,32,November 2018,0`; - mock.onGet(globalConfig.filepath).reply(200, responseData); + mock.onGet(config.filepath).reply(200, responseData); const result = await csvLookup.execute([ { @@ -88,7 +88,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully applies CSVLookup `local file` strategy to given input.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -97,7 +97,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -121,7 +121,7 @@ describe('builtins/CSVLookup: ', () => { }); it('rejects with file not found error.', async () => { - const globalConfig = { + const config = { filepath: './file-fail.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -130,7 +130,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -150,7 +150,7 @@ describe('builtins/CSVLookup: ', () => { }); it('rejects with file not found error.', async () => { - const globalConfig = { + const config = { filepath: './file-fail.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -159,7 +159,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -179,7 +179,7 @@ describe('builtins/CSVLookup: ', () => { }); it('rejects with axios error.', async () => { - const globalConfig = { + const config = { filepath: 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', query: { @@ -189,9 +189,9 @@ describe('builtins/CSVLookup: ', () => { }, output: ['cpu-tdp', 'tdp'], }; - mock.onGet(globalConfig.filepath).reply(404); + mock.onGet(config.filepath).reply(404); - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -212,7 +212,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully applies CSVLookup if output is `*`.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -221,7 +221,7 @@ describe('builtins/CSVLookup: ', () => { }, output: '*', }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -257,7 +257,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully applies CSVLookup if output is matrix.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -269,7 +269,7 @@ describe('builtins/CSVLookup: ', () => { ['gpu-model-name', 'gpumodel'], ], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -295,7 +295,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully applies CSVLookup if output is exact string.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -304,7 +304,7 @@ describe('builtins/CSVLookup: ', () => { }, output: 'gpu-count', }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -329,7 +329,7 @@ describe('builtins/CSVLookup: ', () => { it('rejects with query data not found.', async () => { expect.assertions(2); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'fail-cpu-cores-available': 'cpu/available', @@ -339,7 +339,7 @@ describe('builtins/CSVLookup: ', () => { output: ['cpu-tdp', 'tdp'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -379,7 +379,7 @@ describe('builtins/CSVLookup: ', () => { } catch (error) { if (error instanceof Error) { expect(error).toBeInstanceOf(GlobalConfigError); - expect(error.message).toEqual(MISSING_GLOBAL_CONFIG); + expect(error.message).toEqual(MISSING_CONFIG); } } }); @@ -387,7 +387,7 @@ describe('builtins/CSVLookup: ', () => { it('rejects with no such column in csv error.', async () => { expect.assertions(2); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -396,7 +396,7 @@ describe('builtins/CSVLookup: ', () => { }, output: 'mock', }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const input = [ { timestamp: '2024-03-01', @@ -411,16 +411,14 @@ describe('builtins/CSVLookup: ', () => { } catch (error) { if (error instanceof Error) { expect(error).toBeInstanceOf(MissingCSVColumnError); - expect(error.message).toEqual( - MISSING_CSV_COLUMN(globalConfig.output) - ); + expect(error.message).toEqual(MISSING_CSV_COLUMN(config.output)); } } }); it('successfully applies CSVLookup if output is array with string.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -429,7 +427,7 @@ describe('builtins/CSVLookup: ', () => { }, output: ['gpu-count'], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -454,7 +452,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully applies CSVLookup if output is matrix with strings.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -463,7 +461,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, parametersMetadata); const result = await csvLookup.execute([ { @@ -490,7 +488,7 @@ describe('builtins/CSVLookup: ', () => { it('rejects with CSV parse error', async () => { process.env.csv = 'fail'; expect.assertions(1); - const globalConfig = { + const config = { filepath: './fail-csv-reader.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -499,7 +497,7 @@ describe('builtins/CSVLookup: ', () => { }, output: [['gpu-count']], }; - const csvLookup = CSVLookup(globalConfig, parametersMetadata); + const csvLookup = CSVLookup(config, 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 e0a472998..32f6a5843 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -5,11 +5,11 @@ import {Divide} from '../../../if-run/builtins'; import {STRINGS} from '../../../if-run/config'; const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA} = STRINGS; +const {MISSING_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { describe('Divide: ', () => { - const globalConfig = { + const config = { numerator: 'vcpus-allocated', denominator: 2, output: 'cpu/number-cores', @@ -18,7 +18,7 @@ describe('builtins/divide: ', () => { inputs: {}, outputs: {}, }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -53,12 +53,12 @@ describe('builtins/divide: ', () => { it('returns a result when `denominator` is provded in input.', async () => { expect.assertions(1); - const globalConfig = { + const config = { numerator: 'vcpus-allocated', denominator: 'duration', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(config, parametersMetadata); const input = [ { @@ -85,12 +85,12 @@ describe('builtins/divide: ', () => { const expectedMessage = '"vcpus-allocated" parameter is required. Error code: invalid_type.'; - const globalConfig = { + const config = { numerator: 'vcpus-allocated', denominator: 3600, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(config, parametersMetadata); expect.assertions(1); @@ -109,7 +109,7 @@ describe('builtins/divide: ', () => { }); }); - it('throws an error on missing global config.', async () => { + it('throws an error on missing config.', async () => { const config = undefined; const divide = Divide(config!, parametersMetadata); @@ -123,19 +123,17 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); it('throws an error when `denominator` is 0.', async () => { - const globalConfig = { + const config = { numerator: 'vcpus-allocated', denominator: 0, output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(config, parametersMetadata); expect.assertions(1); @@ -158,12 +156,12 @@ describe('builtins/divide: ', () => { }); it('throws an error when `denominator` is string.', async () => { - const globalConfig = { + const config = { numerator: 'vcpus-allocated', denominator: '10', output: 'vcpus-allocated-per-second', }; - const divide = Divide(globalConfig, parametersMetadata); + const divide = Divide(config, parametersMetadata); expect.assertions(1); @@ -177,9 +175,7 @@ describe('builtins/divide: ', () => { ]); } catch (error) { expect(error).toStrictEqual( - new MissingInputDataError( - MISSING_INPUT_DATA(globalConfig.denominator) - ) + new MissingInputDataError(MISSING_INPUT_DATA(config.denominator)) ); } }); diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index 2e0419686..2c828bd5f 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -6,7 +6,7 @@ const {InputValidationError} = ERRORS; describe('builtins/exponent: ', () => { describe('Exponent: ', () => { - const globalConfig = { + const config = { 'input-parameter': 'energy/base', exponent: 3, 'output-parameter': 'energy', @@ -15,7 +15,7 @@ describe('builtins/exponent: ', () => { inputs: {}, outputs: {}, }; - const exponent = Exponent(globalConfig, parametersMetadata); + const exponent = Exponent(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index 6634556dd..04af10945 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -6,16 +6,12 @@ import {Interpolation} from '../../../if-run/builtins'; import {STRINGS} from '../../../if-run/config'; const {InputValidationError, GlobalConfigError} = ERRORS; -const { - MISSING_GLOBAL_CONFIG, - WITHIN_THE_RANGE, - ARRAY_LENGTH_NON_EMPTY, - X_Y_EQUAL, -} = STRINGS; +const {MISSING_CONFIG, WITHIN_THE_RANGE, ARRAY_LENGTH_NON_EMPTY, X_Y_EQUAL} = + STRINGS; describe('builtins/interpolation: ', () => { describe('Interpolation: ', () => { - const globalConfig = { + const config = { method: Method.LINEAR, x: [0, 10, 50, 100], y: [0.12, 0.32, 0.75, 1.02], @@ -33,7 +29,7 @@ describe('builtins/interpolation: ', () => { 'cpu/utilization': 45, }, ]; - const plugin = Interpolation(globalConfig, parametersMetadata); + const plugin = Interpolation(config, parametersMetadata); describe('init Interpolation: ', () => { it('initalizes object with properties.', async () => { @@ -56,14 +52,14 @@ describe('builtins/interpolation: ', () => { expect(plugin.execute(inputs)).toEqual(outputs); }); - it('returns result when the `method` is not provided in the global config.', () => { - const globalConfig = { + it('returns result when the `method` is not provided in the config.', () => { + const config = { x: [0, 10, 50, 100], y: [0.12, 0.32, 0.75, 1.02], 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const plugin = Interpolation(globalConfig, parametersMetadata); + const plugin = Interpolation(config, parametersMetadata); const outputs = [ { @@ -78,8 +74,8 @@ 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 newConfig = Object.assign({}, config, {method: Method.SPLINE}); + const plugin = Interpolation(newConfig, parametersMetadata); const outputs = [ { @@ -94,10 +90,10 @@ describe('builtins/interpolation: ', () => { }); it('returns result when the `method` is `polynomial`.', () => { - const config = Object.assign({}, globalConfig, { + const newConfig = Object.assign({}, config, { method: Method.POLYNOMIAL, }); - const plugin = Interpolation(config, parametersMetadata); + const plugin = Interpolation(newConfig, parametersMetadata); const outputs = [ { @@ -112,10 +108,10 @@ describe('builtins/interpolation: ', () => { }); it('returns result when the elements of `x` is not in acsending order.', () => { - const config = Object.assign({}, globalConfig, { + const newConfig = Object.assign({}, config, { x: [0, 10, 100, 50], }); - const plugin = Interpolation(config, parametersMetadata); + const plugin = Interpolation(newConfig, parametersMetadata); const outputs = [ { @@ -149,7 +145,7 @@ describe('builtins/interpolation: ', () => { expect(plugin.execute(inputs)).toEqual(outputs); }); - it('throws an when the global config is not provided.', () => { + it('throws an when the config is not provided.', () => { const config = undefined; const plugin = Interpolation(config!, parametersMetadata); @@ -158,16 +154,16 @@ describe('builtins/interpolation: ', () => { plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual(new GlobalConfigError(MISSING_GLOBAL_CONFIG)); + expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); } }); it('throws an error when `x` and `y` points not equal.', () => { - const config = Object.assign({}, globalConfig, { + const newConfig = Object.assign({}, config, { x: [0, 10, 100], }); - const plugin = Interpolation(config, parametersMetadata); + const plugin = Interpolation(newConfig, parametersMetadata); expect.assertions(2); try { @@ -195,13 +191,13 @@ describe('builtins/interpolation: ', () => { } }); it('throws an error when the the length of the input arrays is <2', () => { - const globalConfig = { + const basicConfig = { x: [0], y: [0.12], 'input-parameter': 'cpu/utilization', 'output-parameter': 'interpolation-result', }; - const config = Object.assign({}, globalConfig, {method: Method.SPLINE}); + const config = Object.assign({}, basicConfig, {method: Method.SPLINE}); const plugin = Interpolation(config, parametersMetadata); const inputs = [ { diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index b3856dfd4..5deee49c0 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -6,7 +6,7 @@ const {InputValidationError} = ERRORS; describe('builtins/multiply: ', () => { describe('Multiply: ', () => { - const globalConfig = { + const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; @@ -14,7 +14,7 @@ describe('builtins/multiply: ', () => { inputs: {}, outputs: {}, }; - const multiply = Multiply(globalConfig, parametersMetadata); + const multiply = Multiply(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index ea45c49d1..f3aaca983 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -5,11 +5,11 @@ import {Regex} from '../../../if-run/builtins/regex'; import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; -const {MISSING_GLOBAL_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; +const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; describe('builtins/regex: ', () => { describe('Regex: ', () => { - const globalConfig = { + const config = { parameter: 'physical-processor', match: '^[^,]+', output: 'cpu/name', @@ -18,7 +18,7 @@ describe('builtins/regex: ', () => { inputs: {}, outputs: {}, }; - const regex = Regex(globalConfig, parametersMetadata); + const regex = Regex(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -54,12 +54,12 @@ describe('builtins/regex: ', () => { }); it('successfully applies regex strategy with multiple matches', async () => { - const globalConfig = { + const config = { parameter: 'cloud/instance-type', match: '/(?<=_)[^_]+?(?=_|$)/g', output: 'cloud/instance-type', }; - const regex = Regex(globalConfig, parametersMetadata); + const regex = Regex(config, parametersMetadata); const expectedResult = [ { @@ -85,12 +85,12 @@ describe('builtins/regex: ', () => { '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'; expect.assertions(1); - const globalConfig = { + const config = { parameter: 'physical-processor', match: '[^,]+/', output: 'cpu/name', }; - const regex = Regex(globalConfig, parametersMetadata); + const regex = Regex(config, parametersMetadata); const expectedResult = [ { @@ -116,12 +116,12 @@ describe('builtins/regex: ', () => { 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'; - const globalConfig = { + const config = { parameter: 'physical-processor', match: '^(^:)+', output: 'cpu/name', }; - const regex = Regex(globalConfig, parametersMetadata); + const regex = Regex(config, parametersMetadata); expect.assertions(1); @@ -142,7 +142,7 @@ describe('builtins/regex: ', () => { } }); - it('throws an error on missing global config.', async () => { + it('throws an error on missing config.', async () => { const config = undefined; const regex = Regex(config!, parametersMetadata); @@ -156,9 +156,7 @@ describe('builtins/regex: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index 134cebfa7..1f2189fee 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -6,7 +6,7 @@ const {InputValidationError} = ERRORS; describe('builtins/subtract: ', () => { describe('Subtract: ', () => { - const globalConfig = { + const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', }; @@ -14,7 +14,7 @@ describe('builtins/subtract: ', () => { inputs: {}, outputs: {}, }; - const subtract = Subtract(globalConfig, parametersMetadata); + const subtract = Subtract(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 9ccc64378..94fcf8bbe 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -5,11 +5,11 @@ import {Sum} from '../../../if-run/builtins/sum'; import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError, InputValidationError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; describe('builtins/sum: ', () => { describe('Sum: ', () => { - const globalConfig = { + const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; @@ -17,7 +17,7 @@ describe('builtins/sum: ', () => { inputs: {}, outputs: {}, }; - const sum = Sum(globalConfig, parametersMetadata); + const sum = Sum(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -54,7 +54,7 @@ describe('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when global config is not provided.', () => { + it('throws an error when config is not provided.', () => { const config = undefined; const sum = Sum(config!, parametersMetadata); @@ -71,9 +71,7 @@ describe('builtins/sum: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index ae55daf5d..9e6ddb3dc 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -5,11 +5,11 @@ import {TimeConverter} from '../../../if-run/builtins/time-converter'; import {STRINGS} from '../../../if-run/config'; const {GlobalConfigError, InputValidationError} = ERRORS; -const {MISSING_GLOBAL_CONFIG} = STRINGS; +const {MISSING_CONFIG} = STRINGS; describe('builtins/time-converter: ', () => { describe('TimeConverter: ', () => { - const globalConfig = { + const config = { 'input-parameter': 'energy-per-year', 'original-time-unit': 'year', 'new-time-unit': 'duration', @@ -19,7 +19,7 @@ describe('builtins/time-converter: ', () => { inputs: {}, outputs: {}, }; - const timeConverter = TimeConverter(globalConfig, parametersMetadata); + const timeConverter = TimeConverter(config, parametersMetadata); describe('init: ', () => { it('successfully initalized.', () => { @@ -52,7 +52,7 @@ describe('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when global config is not provided.', () => { + it('throws an error when config is not provided.', () => { const config = undefined; const timeConverter = TimeConverter(config!, parametersMetadata); @@ -67,9 +67,7 @@ describe('builtins/time-converter: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(MISSING_GLOBAL_CONFIG) - ); + expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index a9fa13cd1..0ec0ace1f 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -218,7 +218,7 @@ describe('execute(): ', () => { } }); - it('throws error on missing global config.', async () => { + it('throws error on missing config.', async () => { const config = undefined; const timeModel = TimeSync(config!, parametersMetadata); @@ -399,7 +399,7 @@ describe('execute(): ', () => { } }); - it('throws error if end is before start in global config.', async () => { + it('throws error if end is before start in config.', async () => { const basicConfig = { 'start-time': '2023-12-12T00:00:10.000Z', 'end-time': '2023-12-12T00:00:00.000Z', diff --git a/src/__tests__/if-run/lib/environment.test.ts b/src/__tests__/if-run/lib/environment.test.ts index 324bd1da6..63127fd5a 100644 --- a/src/__tests__/if-run/lib/environment.test.ts +++ b/src/__tests__/if-run/lib/environment.test.ts @@ -2,7 +2,7 @@ import {injectEnvironment} from '../../../if-run/lib/environment'; -describe('lib/envirnoment: ', () => { +describe.skip('lib/envirnoment: ', () => { describe('injectEnvironment(): ', () => { const context = {}; diff --git a/src/__tests__/if-run/lib/initialize.test.ts b/src/__tests__/if-run/lib/initialize.test.ts index a1eda8924..3b2c82fdc 100644 --- a/src/__tests__/if-run/lib/initialize.test.ts +++ b/src/__tests__/if-run/lib/initialize.test.ts @@ -60,14 +60,14 @@ describe('lib/initalize: ', () => { expect(mockLog).toHaveBeenCalledTimes(1); // checks if logger is called }); - it('checks if plugin is initalized with global config and has execute and metadata.', async () => { + it('checks if plugin is initalized with config and has execute and metadata.', async () => { const context = { initialize: { plugins: { mockavizta: { path: 'mockavizta', method: 'Mockavizta', - 'global-config': { + config: { verbose: true, }, }, @@ -89,7 +89,7 @@ describe('lib/initalize: ', () => { plugins: { mockavizta: { method: 'Mockavizta', - 'global-config': { + config: { verbose: true, }, }, @@ -115,7 +115,7 @@ describe('lib/initalize: ', () => { plugins: { mockavizta: { path: 'mockavizta', - 'global-config': { + config: { verbose: true, }, }, @@ -142,7 +142,7 @@ describe('lib/initalize: ', () => { mockavizta: { path: 'builtin', method: 'Mockavizta', - 'global-config': { + config: { verbose: true, }, }, @@ -165,7 +165,7 @@ describe('lib/initalize: ', () => { mockavizta: { path: 'https://github.com/mockavizta', method: 'Mockavizta', - 'global-config': { + config: { verbose: true, }, }, @@ -188,7 +188,7 @@ describe('lib/initalize: ', () => { mockavizta: { path: 'failing-mock', method: 'Mockavizta', - 'global-config': { + config: { verbose: true, }, }, From d60817cef2e95285dbb491e02a2af84ba83da5a0 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 12 Aug 2024 20:12:17 +0400 Subject: [PATCH 631/863] docs(builtins): update docs --- Refactor-migration-guide.md | 22 +++++++++---------- src/if-run/builtins/coefficient/README.md | 12 +++++----- 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 | 12 +++++----- src/if-run/builtins/exponent/README.md | 10 ++++----- src/if-run/builtins/interpolation/README.md | 20 ++++++++--------- .../builtins/mock-observations/README.md | 6 ++--- src/if-run/builtins/multiply/README.md | 10 ++++----- src/if-run/builtins/regex/README.md | 12 +++++----- src/if-run/builtins/sci/README.md | 6 ++--- src/if-run/builtins/shell/README.md | 8 +++---- src/if-run/builtins/subtract/README.md | 10 ++++----- src/if-run/builtins/sum/README.md | 10 ++++----- src/if-run/builtins/time-converter/README.md | 10 ++++----- src/if-run/builtins/time-sync/README.md | 8 +++---- 16 files changed, 85 insertions(+), 85 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index f9c2e26ce..ebdf94b20 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -105,10 +105,10 @@ There have also been some changes to the structure of manifest files. Some of th method: SciEmbodied ``` -- **Global config** - We have introduced the concept of global config to the plugins. This is truly global configuration data that should be kept constant regardless of where the plugin is invoked across the manifest file. +- **Config** + We have introduced the concept of config to the plugins. This is truly configuration data that should be kept constant regardless of where the plugin is invoked across the manifest file. - A good example is the `interpolation` method to use in the Teads curve plugin - this is not expected to vary from component to component and can therefore be defined in global config. The plugin code itself must expect the global config. Then, the config can be passed in the `Initialize` block, for example: + A good example is the `interpolation` method to use in the Teads curve plugin - this is not expected to vary from component to component and can therefore be defined in config. The plugin code itself must expect the config. Then, the config can be passed in the `Initialize` block, for example: ```yaml initialize: @@ -116,7 +116,7 @@ There have also been some changes to the structure of manifest files. Some of th 'time-sync': method: TimeSync path: 'builtin' - global-config: + config: start-time: '2023-12-12T00:00:00.000Z' end-time: '2023-12-12T00:01:00.000Z' interval: 5 @@ -157,7 +157,7 @@ There have also been some changes to the structure of manifest files. Some of th Technically time-sync is not a new feature as it was present in IF before the refactor, but there are some tweaks to how the plugin is configured that are worth explaining here. Time sync snaps all input arrays across an entire graph to a common time grid. -This means you have to define a global start time, end time and interval to use everywhere. There is also a boolean to toggle whether you should allow the time sync model to pad the start and end of your time series with zeroes. You should default to `true` unless you have a specific reason not to. In the refactored IF we expect this information to be provided in global config, as follows: +This means you have to define a start time, end time and interval to use everywhere. There is also a boolean to toggle whether you should allow the time sync model to pad the start and end of your time series with zeroes. You should default to `true` unless you have a specific reason not to. In the refactored IF we expect this information to be provided in config, as follows: ```yaml initialize: @@ -165,7 +165,7 @@ initialize: 'time-sync': method: TimeSync path: 'builtin' - global-config: + config: start-time: '2023-12-12T00:00:00.000Z' end-time: '2023-12-12T00:01:00.000Z' interval: 5 @@ -215,13 +215,13 @@ export type PluginInterface = { The plugin still requires an execute function. This is where you implement the plugin logic. -Here's a minimal example for a plugin that sums some inputs defined in global config - see inline comments for some important notes: +Here's a minimal example for a plugin that sums some inputs defined in config - see inline comments for some important notes: ```ts -// Here's the function definition - notice that global config is passed in here! -export const Sum = (globalConfig: SumConfig): PluginInterface => { - const inputParameters = globalConfig['input-parameters'] || []; - const outputParameter = globalConfig['output-parameter']; +// Here's the function definition - notice that config is passed in here! +export const Sum = (config: SumConfig): PluginInterface => { + const inputParameters = config['input-parameters'] || []; + const outputParameter = config['output-parameter']; // we also return metadata now too - you can add more or just use this default const metadata = { diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 903a15496..c77ffdc0a 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -8,9 +8,9 @@ For example, you could multiply `cpu/energy` by 10 and name the result `energy-p ## Parameters -### Plugin global config +### Plugin config -Three parameters are required in global config: `input-parameter`, `coefficient` and `output-parameter`. +Three parameters are required in config: `input-parameter`, `coefficient` and `output-parameter`. - `input-parameter`: a string matching an existing key in the `inputs` array - `coefficient`: the value to multiply `input-parameter` by. @@ -21,13 +21,13 @@ Three parameters are required in global config: `input-parameter`, `coefficient` The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe parameters of the `input-parameter` of the global config. Each parameter has: +- `inputs`: describe parameters of the `input-parameter` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe parameters of the `output-parameter` of the global config. Each parameter has: +- `outputs`: describe parameters of the `output-parameter` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -38,7 +38,7 @@ All of `input-parameters` must be available in the input array. ## Returns -- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -80,7 +80,7 @@ initialize: coefficient: method: Coefficient path: 'builtin' - global-config: + config: input-parameter: 'carbon' coefficient: 3 output-parameter: 'carbon-product' diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 2f76c98da..abe33d221 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -43,13 +43,13 @@ Three parameters are required in config: `from` and `to` and `keep-existing`. The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe the parameter of the `from` of the global config. The parameter has the following attributes: +- `inputs`: describe the parameter of the `from` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameters of the `to` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameters of the `to` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -99,7 +99,7 @@ initialize: copy-param: path: builtin method: Copy - global-config: + config: keep-existing: true from: original to: copy diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 434e234a2..d049c898d 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -78,7 +78,7 @@ The input data with the requested csv content appended to it. ## Plugin logic -1. Validates global config which contains `filepath`, `query` and `output`. +1. Validates config which contains `filepath`, `query` and `output`. 2. Tries to retrieve given file (with url or local path). 3. Parses given CSV. 4. Filters requested information from CSV. @@ -90,7 +90,7 @@ The input data with the requested csv content appended to it. To run the plugin, you must first create an instance of `CSVLookup`. Then, you can call `execute()`. ```typescript -const globalConfig = { +const config = { filepath: 'https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv', query: { 'cloud-provider': 'cloud/provider' @@ -99,7 +99,7 @@ const globalConfig = { }, output: ['cpu-tdp', 'tdp'], }; -const csvLookup = CSVLookup(globalConfig); +const csvLookup = CSVLookup(config); const input = [ { @@ -125,7 +125,7 @@ initialize: cloud-metadata: method: CSVLookup path: 'builtin' - global-config: + config: filepath: https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/region-metadata.csv query: cloud-provider: 'cloud/provider' diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index abb534c8f..3cb83f6eb 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -16,13 +16,13 @@ You provide the names of the values you want to divide, and a name to use to add The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe the parameter of the `numerator` of the global config. The parameter has the following attributes: +- `inputs`: describe the parameter of the `numerator` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `denominator` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameter of the `denominator` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -35,7 +35,7 @@ The `parameter-metadata` section contains information about `description`, `unit ## Returns -- `output`: the division of `numerator` with the parameter name into `denominator` with the parameter name defined by `output` in global config. +- `output`: the division of `numerator` with the parameter name into `denominator` with the parameter name defined by `output` in config. The plugin throws an exception if the division result is not a number. @@ -52,12 +52,12 @@ output = input0 / input1 To run the plugin, you must first create an instance of `Divide`. Then, you can call `execute()`. ```typescript -const globalConfig = { +const config = { numerator: 'vcpus-allocated', denominator: 2, output: 'cpu/number-cores', }; -const divide = Divide(globalConfig, parametersMetadata); +const divide = Divide(config, parametersMetadata); const input = [ { @@ -81,7 +81,7 @@ initialize: divide: method: Divide path: 'builtin' - global-config: + config: numerator: vcpus-allocated denominator: 2 output: cpu/number-cores diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index fddb55ffa..8e837b10d 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -10,7 +10,7 @@ For example, you use `cpu/energy` as base and `network/energy` as and name the r ### Plugin config -Three parameters are required in global config: `input-parameter`, `exponent` and `output-parameter`. +Three parameters are required in config: `input-parameter`, `exponent` and `output-parameter`. `input-parameter`: a string defining the base. Must match an existing key in the `inputs` array `exponent`: a number defining the exponent. @@ -20,13 +20,13 @@ Three parameters are required in global config: `input-parameter`, `exponent` an The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: +- `inputs`: describe the parameter of the `input-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes:: +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes:: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -37,7 +37,7 @@ The `parameter-metadata` section contains information about `description`, `unit ## Returns -- `output-parameter`: `input-parameter` raised by `exponent` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: `input-parameter` raised by `exponent` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -82,7 +82,7 @@ initialize: exponent: method: Exponent path: 'builtin' - global-config: + config: input-parameter: 'cpu/energy' exponent: 2 output-parameter: 'energy' diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index 243b70e70..3279ae89b 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -9,13 +9,13 @@ This plugin provides the `y` value at a given `x` by interpolating between known To employ the `Interpolation` plugin, adhere to these steps: -1. **Initialize Plugin**: Import the `Interpolation` function and initialize it with global configuration parameters `method`, `x`, `y`, `input-parameter` and `output-parameter`. +1. **Initialize Plugin**: Import the `Interpolation` function and initialize it with configuration parameters `method`, `x`, `y`, `input-parameter` and `output-parameter`. 2. **Execute Plugin**: Invoke the `execute` method of the initialized plugin instance with an array of input parameters. Each input parameter should include a `timestamp`, `duration` and `[input-parameter]` information. 3. **Result**: The plugin will return an array of plugin parameters enriched with the calculated average carbon intensity for each input. -## Global Config +## Config - `method`: specifies the interpolation method for the data. Acceptable values are 'linear', 'spline', or 'polynomial'. The default method is linear. (optional) - `x`: array of x points. Numbers should be in ascending order (required). @@ -29,13 +29,13 @@ To employ the `Interpolation` plugin, adhere to these steps: The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe the parameter of the `input-parameter` of the global config. The parameter has the following attributes: +- `inputs`: describe the parameter of the `input-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameters of the `output-parameter` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameters of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -46,7 +46,7 @@ The plugin expects the following input parameters: - `timestamp`: a timestamp for the input (required) - `duration`: the amount of time, in seconds, that the input covers. (required) -- `[input-parameter]` - a field whose name matches the string provided to input-parameter in global config (i.e. if the input-parameter in global config is cpu/utilisation then cpu-utilisation must exist in the input data) +- `[input-parameter]` - a field whose name matches the string provided to input-parameter in config (i.e. if the input-parameter in config is cpu/utilisation then cpu-utilisation must exist in the input data) ## Output @@ -60,7 +60,7 @@ The plugin conducts input validation using the `zod` library and may throw error 1. **Execution**: - - Validate Global config + - Validate config - `method` - validates if the method is one of these methods: `linear`, `spline`, or `polynomial`. If the method isn’t provided, it sets to `linear`. - `x` and `y` should be arrays of numbers, the length should be equal, and elements should be ordered in the ascendant order. @@ -84,7 +84,7 @@ The plugin conducts input validation using the `zod` library and may throw error ### TypeScript Usage ```ts -const globalConfig = { +const config = { method: 'linear', x: [0, 10, 50, 100], y: [0.12, 0.32, 0.75, 1.02], @@ -93,7 +93,7 @@ const globalConfig = { }; -const interpolationPlugin = Interpolation(globalConfig); +const interpolationPlugin = Interpolation(config); const inputs = [ { @@ -121,7 +121,7 @@ initialize: interpolation: method: Interpolation path: 'builtin' - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] @@ -150,7 +150,7 @@ initialize: interpolation: method: Interpolation path: 'builtin' - global-config: + config: method: linear x: [0, 10, 50, 100] y: [0.12, 0.32, 0.75, 1.02] diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 53bd89924..82f965006 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -11,7 +11,7 @@ The mode currently mocks 2 types of observation data: - Common key-value pairs, that are generated statically and are the same for each generated observation/input (see 'helpers/CommonGenerator.ts') - Randomly generated integer values for predefined keys (see 'helpers/RandIntGenerator.ts') -### Plugin global config +### Plugin config - `timestamp-from`, `timestamp-to` and `duration` define time buckets for which to generate observations. - `generators` define which fields to generate for each observation @@ -38,7 +38,7 @@ N/A ### Inputs -The plugin's `global-config` section in the manifest file determines its behaviour. +The plugin's `config` section in the manifest file determines its behaviour. 'inputs' section is ignored. ### Typescript Usage @@ -74,7 +74,7 @@ initialize: kind: plugin method: MockObservations path: 'builtin' - global-config: + config: timestamp-from: 2023-07-06T00:00 timestamp-to: 2023-07-06T00:10 duration: 60 diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index dc6cde7c7..426a8ba45 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -10,7 +10,7 @@ For example, you could multiply `cpu/energy` and `network/energy` and name the r ### Plugin config -Two parameters are required in global config: `input-parameters` and `output-parameter`. +Two parameters are required in config: `input-parameters` and `output-parameter`. `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the product of the input parameters to the output array. @@ -19,13 +19,13 @@ Two parameters are required in global config: `input-parameters` and `output-par The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: +- `inputs`: describe parameters of the `input-parameters` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -36,7 +36,7 @@ All of `input-parameters` must be available in the input array. ## Returns -- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: the product of all `input-parameters` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -80,7 +80,7 @@ initialize: multiply: method: Multiply path: 'builtin' - global-config: + config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy-product' tree: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 2c6a4cd88..78fda8c37 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -20,13 +20,13 @@ Intel® Xeon® Platinum 8272CL,Intel® Xeon® 8171M 2.1 GHz,Intel® Xeon® E5-26 The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe the parameter of the `parameter` value of the global config. The parameter has the following attributes: +- `inputs`: describe the parameter of the `parameter` value of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameters of the `output` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameters of the `output` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -37,19 +37,19 @@ The `parameter-metadata` section contains information about `description`, `unit ## Returns -- `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. +- `output`: The match of the `parameter` value using the `match` regex defined in the 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 = { +const config = { parameter: 'physical-processor', match: '^[^,]+', output: 'cpu/name', }; -const regex = Regex(globalConfig); +const regex = Regex(config); const input = [ { @@ -74,7 +74,7 @@ initialize: regex: method: Regex path: 'builtin' - global-config: + config: parameter: physical-processor match: ^[^,]+ output: cpu/name diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 31b15afed..0211f6a32 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -4,7 +4,7 @@ ## Parameters -### Plugin global config +### Plugin config - `functional-unit`: the name of the functional unit in which to express the carbon impact (required) @@ -26,7 +26,7 @@ The `parameter-metadata` section contains information about `description`, `unit ### Inputs - `carbon`: total carbon in gCO2eq (required) -- `functional-unit`: whatever `functional-unit` you define in global config also has to be present in each input, for example if you provide `functional-unit: requests` in global config, `requests` must be present in your input data. +- `functional-unit`: whatever `functional-unit` you define in config also has to be present in each input, for example if you provide `functional-unit: requests` in config, `requests` must be present in your input data. ## Returns @@ -76,7 +76,7 @@ initialize: sci: method: Sci path: 'builtin' - global-config: + config: functional-unit: 'requests' tree: children: diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index d114adb3b..f21da8a4b 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -4,7 +4,7 @@ The `shell` is a wrapper enabling plugins implemented in any other programming l ## Parameters -### Plugin global config +### Plugin config The plugin should be initialized as follows: @@ -14,7 +14,7 @@ initialize: shell: method: Shell path: 'builtin' - global-config: + config: command: python3 /usr/local/bin/sampler ``` @@ -85,7 +85,7 @@ initialize: sampler: method: Shell path: 'builtin' - global-config: + config: command: python3 /usr/local/bin/sampler tree: children: @@ -112,7 +112,7 @@ initialize: sampler: method: Shell path: 'builtin' - global-config: + config: command: python3 /usr/local/bin/sampler tree: children: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 776526c7e..e97a9bcf6 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -10,7 +10,7 @@ For example, you could subtract `cpu/energy` and `network/energy` and name the r ### Plugin config -Two parameters are required in global config: `input-parameters` and `output-parameter`. +Two parameters are required in config: `input-parameters` and `output-parameter`. `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the result of the diff to the output array. @@ -19,13 +19,13 @@ Two parameters are required in global config: `input-parameters` and `output-par The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has the following attributes: +- `inputs`: describe parameters of the `input-parameters` of the config. Each parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -36,7 +36,7 @@ All of `input-parameters` must be available in the input array. ## Returns -- `output-parameter`: the subtraction of all `input-parameters` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: the subtraction of all `input-parameters` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -80,7 +80,7 @@ initialize: subtract: method: Subtract path: 'builtin' - global-config: + config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy/diff' tree: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 14ad1c336..06fdef539 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -10,7 +10,7 @@ For example, you could add `cpu/energy` and `network/energy` and name the result ### Plugin config -Two parameters are required in global config: `input-parameters` and `output-parameter`. +Two parameters are required in config: `input-parameters` and `output-parameter`. `input-parameters`: an array of strings. Each string should match an existing key in the `inputs` array `output-parameter`: a string defining the name to use to add the result of summing the input parameters to the output array. @@ -19,13 +19,13 @@ Two parameters are required in global config: `input-parameters` and `output-par The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs -- `inputs`: describe parameters of the `input-parameters` of the global config. Each parameter has: +- `inputs`: describe parameters of the `input-parameters` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) @@ -36,7 +36,7 @@ All of `input-parameters` must be available in the input array. ## Returns -- `output-parameter`: the sum of all `input-parameters` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: the sum of all `input-parameters` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -78,7 +78,7 @@ initialize: sum: method: Sum path: 'builtin' - global-config: + config: input-parameters: ['cpu/energy', 'network/energy'] output-parameter: 'energy' parameter-metadata: diff --git a/src/if-run/builtins/time-converter/README.md b/src/if-run/builtins/time-converter/README.md index b6c945c20..ffe532355 100644 --- a/src/if-run/builtins/time-converter/README.md +++ b/src/if-run/builtins/time-converter/README.md @@ -10,7 +10,7 @@ For example, you could add `energy-per-year`, the time unit `year`, and the new ### Plugin config -These parameters are required in global config: +These parameters are required in config: - `input-parameter`: a string that should match an existing key in the `inputs` array - `original-time-unit`: a string that defines the time unit of the `input-parameter`. The original time unit should be a valid unit, like `year`, `month`, `day`, `hour` and so on @@ -21,13 +21,13 @@ These parameters are required in global config: 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: +- `inputs`: describe parameters of the `input-parameter` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: the aggregation method of the parameter (can be `sum`, `avg` or `none`) -- `outputs`: describe the parameter of the `output-parameter` of the global config. The parameter has the following attributes: +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: the aggregation method of the parameter (can be `sum`, `avg` or `none`) @@ -38,7 +38,7 @@ The `input-parameter` must be available in the input array. ## Returns -- `output-parameter`: the converted energy of the `input-parameter` with the parameter name defined by `output-parameter` in global config. +- `output-parameter`: the converted energy of the `input-parameter` with the parameter name defined by `output-parameter` in config. ## Calculation @@ -81,7 +81,7 @@ initialize: time-converter: method: TimeConverter path: builtin - global-config: + config: input-parameter: 'energy-per-year' original-time-unit: 'year' new-time-unit: 'duration' diff --git a/src/if-run/builtins/time-sync/README.md b/src/if-run/builtins/time-sync/README.md index e22d03bf1..196724657 100644 --- a/src/if-run/builtins/time-sync/README.md +++ b/src/if-run/builtins/time-sync/README.md @@ -118,7 +118,7 @@ Note that when `error-on-padding` is `true` no gap-filling is performed and the ##### Trimming and padding -To ensure parity across all the components in a tree, we need to synchronize the start and end times for all time series. To do this, we pass the `time-sync` plugin plugin some global config: `startTime`, `endTime` and `interval`. The `startTime` is the timestamp where _all_ input arrays across the entire tree should begin, and `endTime` is the timestamp where _all_ input arrays across the entire tree should end. `interval` is the time resolution we ultimately want to resample to. +To ensure parity across all the components in a tree, we need to synchronize the start and end times for all time series. To do this, we pass the `time-sync` plugin plugin some config: `startTime`, `endTime` and `interval`. The `startTime` is the timestamp where _all_ input arrays across the entire tree should begin, and `endTime` is the timestamp where _all_ input arrays across the entire tree should end. `interval` is the time resolution we ultimately want to resample to. To synchronize the time series start and end we check the first element of `inputs` for each node in the tree and determine whether it is earlier, later or equal to the global start time. If it is equal then no action is required. If the `input` start time is earlier than the global start time, we simply discard entries from the front of the array until the start times are aligned. If the `input` start time is after the global start time, then we pad with our "zero-observation" object - one for every second separating the global start time from the `input` start time. The same process is repeated for the end time - we either trim away `input` data or pad it out with "zero-observation" objects. @@ -170,12 +170,12 @@ To run the plugin, you must first create an instance of `TimeSync`. Then, you can call `execute()`. ```typescript -const globalConfig = { +const config = { 'start-time': '2023-12-12T00:00:00.000Z', 'end-time': '2023-12-12T00:00:30.000Z', interval: 10 } -const timeSync = TimeSync(globalConfig); +const timeSync = TimeSync(config); const results = timeSync.execute([ { timestamp: '2023-12-12T00:00:00.000Z' @@ -224,7 +224,7 @@ initialize: time-sync: method: TimeSync path: builtin - global-config: + config: start-time: '2023-12-12T00:00:00.000Z' # ISO timestamp end-time: '2023-12-12T00:01:00.000Z' # ISO timestamp interval: 5 # seconds From 9279ec0d4d2e32f2e51fd303e12eb1aafef05c5b Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 12:19:31 +0400 Subject: [PATCH 632/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80f89027a..c11cceb0d 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.16", + "@grnsft/if-core": "^0.0.17", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.16.tgz", - "integrity": "sha512-Ep/YRk8rpFK7+kgD3iKon6PtY8jEj8H3ihYglw9Jli5lPszObwIMb4e6aHXmW2kcCndpBQKuSXaruGTgQ/d9ww==", + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.17.tgz", + "integrity": "sha512-t94QvQgP4qomJoSqPUy70Th271/3b3E8+FfmW0Fv00je5Lb5OVAzF1FAD1GdP1UkoXJkbklO99d6hbTMCZSHlw==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index f8bec2d83..8a86b90ee 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.16", + "@grnsft/if-core": "^0.0.17", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 10400327a920312f981d62eeee110102f783de92 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 12:21:36 +0400 Subject: [PATCH 633/863] test(builtins): rename `GlobalConfigError` to `ConfigError` --- src/__tests__/if-run/builtins/CommonGenerator.test.ts | 4 ++-- src/__tests__/if-run/builtins/RandIntGenerator.test.ts | 8 ++++---- src/__tests__/if-run/builtins/coefficient.test.ts | 4 ++-- src/__tests__/if-run/builtins/copy-param.test.ts | 4 ++-- src/__tests__/if-run/builtins/csv-lookup.test.ts | 4 ++-- src/__tests__/if-run/builtins/divide.test.ts | 4 ++-- src/__tests__/if-run/builtins/interpolation.test.ts | 6 +++--- src/__tests__/if-run/builtins/mock-observations.test.ts | 6 +++--- src/__tests__/if-run/builtins/regex.test.ts | 4 ++-- src/__tests__/if-run/builtins/sum.test.ts | 4 ++-- src/__tests__/if-run/builtins/time-converter.test.ts | 4 ++-- src/__tests__/if-run/builtins/time-sync.test.ts | 6 ++---- 12 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/__tests__/if-run/builtins/CommonGenerator.test.ts b/src/__tests__/if-run/builtins/CommonGenerator.test.ts index 820c2a9c6..62a1b52da 100644 --- a/src/__tests__/if-run/builtins/CommonGenerator.test.ts +++ b/src/__tests__/if-run/builtins/CommonGenerator.test.ts @@ -4,7 +4,7 @@ import {CommonGenerator} from '../../../if-run/builtins/mock-observations/helper import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/mock-observations/CommonGenerator: ', () => { @@ -17,7 +17,7 @@ describe('builtins/mock-observations/CommonGenerator: ', () => { try { commonGenerator.next([]); } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toEqual(new ConfigError(MISSING_CONFIG)); } }); }); diff --git a/src/__tests__/if-run/builtins/RandIntGenerator.test.ts b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts index 6c650425b..7ffbfb581 100644 --- a/src/__tests__/if-run/builtins/RandIntGenerator.test.ts +++ b/src/__tests__/if-run/builtins/RandIntGenerator.test.ts @@ -4,7 +4,7 @@ import {RandIntGenerator} from '../../../if-run/builtins/mock-observations/helpe import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {INVALID_NAME, MISSING_MIN_MAX, MISSING_CONFIG} = STRINGS; describe('builtins/mock-observations/RandIntGenerator: ', () => { @@ -14,7 +14,7 @@ describe('builtins/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('', {}); } catch (error) { - expect(error).toEqual(new GlobalConfigError(INVALID_NAME)); + expect(error).toEqual(new ConfigError(INVALID_NAME)); } }); @@ -23,7 +23,7 @@ describe('builtins/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('generator-name', {}); } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toEqual(new ConfigError(MISSING_CONFIG)); } }); @@ -35,7 +35,7 @@ describe('builtins/mock-observations/RandIntGenerator: ', () => { try { RandIntGenerator('random', config); } catch (error) { - expect(error).toEqual(new GlobalConfigError(MISSING_MIN_MAX)); + expect(error).toEqual(new ConfigError(MISSING_MIN_MAX)); } }); }); diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 7244454b1..b715a8b61 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -4,7 +4,7 @@ import {Coefficient} from '../../../if-run/builtins/coefficient'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, GlobalConfigError} = ERRORS; +const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { @@ -68,7 +68,7 @@ describe('builtins/coefficient: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index e2c5c3db0..793c8dd55 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -4,7 +4,7 @@ import {Copy} from '../../../if-run/builtins/copy-param'; import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError, InputValidationError} = ERRORS; +const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/copy: ', () => { @@ -66,7 +66,7 @@ describe('builtins/copy: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index be0ddb35a..50d1b1ee0 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -9,7 +9,7 @@ import {CSVLookup} from '../../../if-run/builtins'; import {STRINGS} from '../../../if-run/config'; const { - GlobalConfigError, + ConfigError, ReadFileError, FetchingFileError, QueryDataNotFoundError, @@ -378,7 +378,7 @@ describe('builtins/CSVLookup: ', () => { await csvLookup.execute(input); } catch (error) { if (error instanceof Error) { - expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toBeInstanceOf(ConfigError); expect(error.message).toEqual(MISSING_CONFIG); } } diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index 32f6a5843..5802b0d40 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -4,7 +4,7 @@ import {Divide} from '../../../if-run/builtins'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, GlobalConfigError, MissingInputDataError} = ERRORS; +const {InputValidationError, ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { @@ -123,7 +123,7 @@ describe('builtins/divide: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index 04af10945..904111e8f 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -5,7 +5,7 @@ import {Interpolation} from '../../../if-run/builtins'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, GlobalConfigError} = ERRORS; +const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG, WITHIN_THE_RANGE, ARRAY_LENGTH_NON_EMPTY, X_Y_EQUAL} = STRINGS; @@ -153,8 +153,8 @@ describe('builtins/interpolation: ', () => { try { plugin.execute(inputs); } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); - expect(error).toEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toBeInstanceOf(ConfigError); + expect(error).toEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index 0569b4c93..af5acbf6c 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -4,7 +4,7 @@ import {MockObservations} from '../../../if-run/builtins/mock-observations'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, GlobalConfigError} = ERRORS; +const {InputValidationError, ConfigError} = ERRORS; const {INVALID_MIN_MAX} = STRINGS; describe('builtins/mock-observations: ', () => { @@ -121,9 +121,9 @@ describe('builtins/mock-observations: ', () => { try { await mockObservations.execute([]); } catch (error) { - expect(error).toBeInstanceOf(GlobalConfigError); + expect(error).toBeInstanceOf(ConfigError); expect(error).toEqual( - new GlobalConfigError(INVALID_MIN_MAX('cpu/utilization')) + new ConfigError(INVALID_MIN_MAX('cpu/utilization')) ); } }); diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index f3aaca983..9265043be 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -4,7 +4,7 @@ import {Regex} from '../../../if-run/builtins/regex'; import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; +const {ConfigError, MissingInputDataError, RegexMismatchError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; describe('builtins/regex: ', () => { @@ -156,7 +156,7 @@ describe('builtins/regex: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 94fcf8bbe..071e075d5 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -4,7 +4,7 @@ import {Sum} from '../../../if-run/builtins/sum'; import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError, InputValidationError} = ERRORS; +const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/sum: ', () => { @@ -71,7 +71,7 @@ describe('builtins/sum: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index 9e6ddb3dc..72a71cf5d 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -4,7 +4,7 @@ import {TimeConverter} from '../../../if-run/builtins/time-converter'; import {STRINGS} from '../../../if-run/config'; -const {GlobalConfigError, InputValidationError} = ERRORS; +const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/time-converter: ', () => { @@ -67,7 +67,7 @@ describe('builtins/time-converter: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new GlobalConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); } }); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 0ec0ace1f..76fc4aeb3 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -15,7 +15,7 @@ const { InvalidPaddingError, InvalidDateInInputError, InvalidInputError, - GlobalConfigError, + ConfigError, } = ERRORS; const { @@ -238,9 +238,7 @@ describe('execute(): ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual( - new GlobalConfigError(INVALID_TIME_NORMALIZATION) - ); + expect(error).toStrictEqual(new ConfigError(INVALID_TIME_NORMALIZATION)); } }); From 78298c8f7668e21f0151c618639e5bf3825e768a Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 12:23:35 +0400 Subject: [PATCH 634/863] fix(builtins): rename `GlobalConfigError` to `ConfigError` --- src/if-run/builtins/coefficient/index.ts | 4 ++-- src/if-run/builtins/copy-param/index.ts | 4 ++-- src/if-run/builtins/csv-lookup/index.ts | 4 ++-- src/if-run/builtins/divide/index.ts | 4 ++-- src/if-run/builtins/interpolation/index.ts | 4 ++-- .../mock-observations/helpers/common-generator.ts | 6 +++--- .../mock-observations/helpers/rand-int-generator.ts | 10 +++++----- src/if-run/builtins/regex/index.ts | 4 ++-- src/if-run/builtins/sum/index.ts | 4 ++-- src/if-run/builtins/time-converter/index.ts | 4 ++-- src/if-run/builtins/time-sync/index.ts | 4 ++-- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index d237c9a91..8f15dbee1 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -11,7 +11,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Coefficient = ( @@ -70,7 +70,7 @@ export const Coefficient = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const configSchema = z.object({ diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index af38b6e7b..223c76e86 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -11,7 +11,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; const {MISSING_CONFIG} = STRINGS; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = 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) @@ -31,7 +31,7 @@ export const Copy = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const configSchema = z.object({ diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index f412a1240..e1960e14d 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -28,7 +28,7 @@ const { ReadFileError, MissingCSVColumnError, QueryDataNotFoundError, - GlobalConfigError, + ConfigError, CSVParseError, } = ERRORS; @@ -231,7 +231,7 @@ export const CSVLookup = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const configSchema = z.object({ diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 31ef613e5..5b39512e7 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -11,7 +11,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {GlobalConfigError, MissingInputDataError} = ERRORS; +const {ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; export const Divide = ( @@ -50,7 +50,7 @@ export const Divide = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const schema = z.object({ diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 5e3c3e717..4a292285c 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -13,7 +13,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG, X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE} = STRINGS; @@ -134,7 +134,7 @@ export const Interpolation = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const schema = z diff --git a/src/if-run/builtins/mock-observations/helpers/common-generator.ts b/src/if-run/builtins/mock-observations/helpers/common-generator.ts index be0800eec..1aceb59f6 100644 --- a/src/if-run/builtins/mock-observations/helpers/common-generator.ts +++ b/src/if-run/builtins/mock-observations/helpers/common-generator.ts @@ -5,18 +5,18 @@ import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const CommonGenerator = (config: ConfigParams): Generator => { /** * Generates next value by copying the validated config. * Validates the provided config is not null or empty. - * Returns a copy of the validated config, otherwise throws an GlobalConfigError. + * Returns a copy of the validated config, otherwise throws an ConfigError. */ const validateConfig = (config: object) => { if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } return structuredClone(config); diff --git a/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts index b62c63e3f..9194fe4b1 100644 --- a/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts +++ b/src/if-run/builtins/mock-observations/helpers/rand-int-generator.ts @@ -5,7 +5,7 @@ import {STRINGS} from '../../../config'; import {Generator} from '../interfaces'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG, MISSING_MIN_MAX, INVALID_MIN_MAX, INVALID_NAME} = STRINGS; @@ -20,7 +20,7 @@ export const RandIntGenerator = ( const validateName = (name: string | null): string => { if (!name || name.trim() === '') { - throw new GlobalConfigError(INVALID_NAME); + throw new ConfigError(INVALID_NAME); } return name; @@ -28,15 +28,15 @@ export const RandIntGenerator = ( const validateConfig = (config: ConfigParams): {min: number; max: number} => { if (!config || Object.keys(config).length === 0) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } if (!config.min || !config.max) { - throw new GlobalConfigError(MISSING_MIN_MAX); + throw new ConfigError(MISSING_MIN_MAX); } if (config.min >= config.max) { - throw new GlobalConfigError(INVALID_MIN_MAX(validatedName)); + throw new ConfigError(INVALID_MIN_MAX(validatedName)); } return {min: config.min, max: config.max}; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index b48d0264b..f405afc76 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -11,7 +11,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {MissingInputDataError, GlobalConfigError, RegexMismatchError} = ERRORS; +const {MissingInputDataError, ConfigError, RegexMismatchError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; export const Regex = ( @@ -29,7 +29,7 @@ export const Regex = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const schema = z.object({ diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 8255080c3..03d93af0f 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -11,7 +11,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Sum = ( @@ -47,7 +47,7 @@ export const Sum = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const configSchema = z.object({ diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index 527e8e146..0b583dbd5 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -13,7 +13,7 @@ import {STRINGS} from '../../config'; import {TIME_UNITS_IN_SECONDS} from './config'; -const {GlobalConfigError} = ERRORS; +const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const TimeConverter = ( @@ -74,7 +74,7 @@ export const TimeConverter = ( */ const validateConfig = () => { if (!config) { - throw new GlobalConfigError(MISSING_CONFIG); + throw new ConfigError(MISSING_CONFIG); } const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 65b1bd9a8..814c27b90 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -21,7 +21,7 @@ import {getAggregationMethod} from '../../lib/aggregate'; Settings.defaultZone = 'utc'; const { - GlobalConfigError, + ConfigError, InvalidDateInInputError, InvalidPaddingError, InvalidInputError, @@ -195,7 +195,7 @@ export const TimeSync = ( */ const validateConfig = () => { if (config === undefined) { - throw new GlobalConfigError(INVALID_TIME_NORMALIZATION); + throw new ConfigError(INVALID_TIME_NORMALIZATION); } const schema = z From 8b35049ad4d965b97d38a4b549e987a85c533b61 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 12:25:04 +0400 Subject: [PATCH 635/863] docs(builtins): rename `GlobalConfigError` to `ConfigError` --- src/if-run/builtins/coefficient/README.md | 4 ++-- src/if-run/builtins/csv-lookup/README.md | 4 ++-- src/if-run/builtins/divide/README.md | 4 ++-- src/if-run/builtins/interpolation/README.md | 6 +++--- src/if-run/builtins/regex/README.md | 4 ++-- src/if-run/builtins/sum/README.md | 4 ++-- src/if-run/builtins/time-converter/README.md | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index c77ffdc0a..4ea300abf 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -117,9 +117,9 @@ The results will be saved to a new `yaml` file in `./examples/outputs` `Coefficient` exposes one of the IF error classes. -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index d049c898d..30f1788e6 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -177,9 +177,9 @@ This error is caused by the `CsvLookup` plugin failing to find data that matches This error arises due to problems parsing CSV data into IF. This can occur when the CSV data is incorrectly formatted or contains unexpected characters that IF does not recognize. These errors are expected to be unusual edge cases as incorrectly formatted data will usually be identified during file loading and cause a `ReadFileError`. To debug, check your CSV file for any unexpected formatting or unusual characters. -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 3cb83f6eb..be0d0ec50 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -110,9 +110,9 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. `Divide` exposes two of IF's error classes. -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index 3279ae89b..dc710aa74 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -184,11 +184,11 @@ if-run --manifest ./manifests/examples/interpolation.yml --output ./manifests/ou `Interpolation` exposes one of IF's error classes. -## `GlobalConfigError` +## `ConfigError` -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 78fda8c37..a4fe4f244 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -112,9 +112,9 @@ Every element in the `inputs` array must contain: - `duration` - whatever value you passed to `parameter` -### `GlobalConfigError` +### `ConfigError` -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 06fdef539..b11484494 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -121,9 +121,9 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. `Sum` exposes two of the IF error classes. -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: diff --git a/src/if-run/builtins/time-converter/README.md b/src/if-run/builtins/time-converter/README.md index ffe532355..199b44923 100644 --- a/src/if-run/builtins/time-converter/README.md +++ b/src/if-run/builtins/time-converter/README.md @@ -111,9 +111,9 @@ The results will be saved to a new `yaml` file in `./examples/outputs`. `TimeConverter` exposes two of the IF error classes. -### GlobalConfigError +### ConfigError -You will receive an error starting `GlobalConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. +You will receive an error starting `ConfigError: ` if you have not provided the expected configuration data in the plugin's `initialize` block. The required parameters are: From 81931562f2bac051504a6cda40bcbc74cf7bb10d Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 12:25:45 +0400 Subject: [PATCH 636/863] fix(manifests): rename `GlobalConfigError` to `ConfigError` --- .../mock-observations/failure-invalid-config-cpu-range.yaml | 2 +- .../failure-invalid-memory-utilization-range.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml index 43887d3b6..f335e47b7 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-config-cpu-range.yaml @@ -73,7 +73,7 @@ execution: - winston@3.11.0 - zod@3.22.4 error: >- - GlobalConfigError: Min value should not be greater than or equal to max + ConfigError: Min value should not be greater than or equal to max value of cpu/utilization tree: children: diff --git a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml index 3ca8f7af9..90a3e7429 100644 --- a/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml +++ b/manifests/outputs/builtins/mock-observations/failure-invalid-memory-utilization-range.yaml @@ -71,7 +71,7 @@ execution: - winston@3.11.0 - zod@3.22.4 error: >- - GlobalConfigError: Min value should not be greater than or equal to max + ConfigError: Min value should not be greater than or equal to max value of memory/utilization tree: children: From fc6747082f126d8c31ccf80e9f167d7fd071d504 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 16:30:40 +0400 Subject: [PATCH 637/863] fix(builtins): add support string and number types for `from` of copy-param plugin --- src/if-run/builtins/copy-param/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 7f10bf696..0cfe81d3b 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -36,7 +36,7 @@ export const Copy = ( const globalConfigSchema = z.object({ 'keep-existing': z.boolean(), - from: z.string().min(1), + from: z.string().min(1).or(z.number()), to: z.string().min(1), }); @@ -51,7 +51,7 @@ export const Copy = ( */ const validateSingleInput = ( input: PluginParams, - inputParameters: string[] + inputParameters: (string | number)[] ) => { const inputData = inputParameters.reduce( (acc, param) => { @@ -59,10 +59,10 @@ export const Copy = ( return acc; }, - {} as Record + {} as Record ); - const validationSchema = z.record(z.string(), z.string()); + const validationSchema = z.record(z.string(), z.string().or(z.number())); validate(validationSchema, inputData); From 8f1b2f6d66586500176ea074196b09cebfced0b8 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 13 Aug 2024 16:32:56 +0400 Subject: [PATCH 638/863] test(builtins): update copy-param test error message --- src/__tests__/if-run/builtins/copy-param.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 952546505..e6e197d2e 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -91,7 +91,7 @@ describe('builtins/copy: ', () => { } catch (error) { expect(error).toStrictEqual( new InputValidationError( - '"original" parameter is required. Error code: invalid_type.' + '"original" parameter is required. Error code: invalid_union.' ) ); } From 10ed069ed07bb9814fd5812bc41436ba0ba5f57e Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 14:13:21 +0400 Subject: [PATCH 639/863] feat(config): add debug strings --- src/if-run/config/strings.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index b8f639450..943d9962c 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -46,11 +46,14 @@ Note that for the '--output' option you also need to define the output type in y CHECKING_AGGREGATION_METHOD: (unitName: string) => `Checking aggregation method for ${unitName}`, INITIALIZING_PLUGINS: 'Initializing plugins', - INITIALIZING_PLUGIN: (pluginName: string) => `Initializing ${pluginName}`, + INITIALIZING_PLUGIN: (pluginName: string) => + `Initializing \`${pluginName}\` plugin`, LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => `Loading ${pluginName} from ${path}`, COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => `Computing pipeline for \`${nodeName}\``, + REGROUPING: 'Regrouping', + OBSERVING: 'Observing', MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', AGGREGATING_OUTPUTS: 'Aggregating outputs', AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, From f6dcc3d9450c5bfd4c9e240d111ce32c4e1785c3 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 14:17:40 +0400 Subject: [PATCH 640/863] feat(util): add emoty row support and add new strings --- src/common/util/debug-logger.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts index 35dc77ea7..74f7c7dbd 100644 --- a/src/common/util/debug-logger.ts +++ b/src/common/util/debug-logger.ts @@ -11,6 +11,8 @@ const logMessagesKeys: (keyof typeof STRINGS)[] = [ 'INITIALIZING_PLUGIN', 'LOADING_PLUGIN_FROM_PATH', 'COMPUTING_PIPELINE_FOR_NODE', + 'REGROUPING', + 'OBSERVING', 'MERGING_DEFAULTS_WITH_INPUT_DATA', 'AGGREGATING_OUTPUTS', 'AGGREGATING_NODE', @@ -101,6 +103,11 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { return; } + if (args[0] === '\n') { + originalConsole.log(); + return; + } + const date = new Date().toISOString(); const plugin = pluginNameManager.currentPluginName; const formattedMessage = `${level}: ${date}: ${ From 7226fe5f8e8d4be6f4cd7e6434e5e0e4585a9473 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 14:20:55 +0400 Subject: [PATCH 641/863] fix(lib): add debug logs for observe and regroup phases, change the plugin method name to pluginName --- src/if-run/lib/compute.ts | 13 ++++++++++++- src/if-run/lib/exhaust.ts | 1 + src/if-run/lib/initialize.ts | 5 +++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 8caa0a38e..27e037a72 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -13,7 +13,13 @@ import {STRINGS} from '../config/strings'; import {ComputeParams, Node, PhasedPipeline} from '../types/compute'; import {isExecute} from '../types/interface'; -const {MERGING_DEFAULTS_WITH_INPUT_DATA, EMPTY_PIPELINE, CONFIG_WARN} = STRINGS; +const { + MERGING_DEFAULTS_WITH_INPUT_DATA, + EMPTY_PIPELINE, + CONFIG_WARN, + REGROUPING, + OBSERVING, +} = STRINGS; /** * Traverses all child nodes based on children grouping. @@ -96,6 +102,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { */ if ((noFlags || params.observe) && pipelineCopy.observe) { while (pipelineCopy.observe.length !== 0) { + console.debug(OBSERVING); + const pluginName = pipelineCopy.observe.shift() as string; const plugin = params.pluginStorage.get(pluginName); const nodeConfig = config && config[pluginName]; @@ -123,6 +131,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { delete node.inputs; delete node.outputs; + console.debug(REGROUPING); + return traverse(node.children, { ...params, pipeline: { @@ -154,6 +164,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { pluginData: params.context.initialize!.plugins[pluginName], }); } + debugLogger.setExecutingPluginName(); } } diff --git a/src/if-run/lib/exhaust.ts b/src/if-run/lib/exhaust.ts index bed36f405..c08926164 100644 --- a/src/if-run/lib/exhaust.ts +++ b/src/if-run/lib/exhaust.ts @@ -21,6 +21,7 @@ export const exhaust = async ( outputOptions: Options ) => { console.debug(PREPARING_OUTPUT_DATA); + console.log('\n'); if (!outputOptions.noOutput && !outputOptions.outputPath) { ExportLog().execute(tree, context); diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 181e88d15..cb5157b83 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -87,8 +87,6 @@ const initPlugin = async ( 'parameter-metadata': parameterMetadata, } = initPluginParams!; - console.debug(INITIALIZING_PLUGIN(method)); - if (!method) { throw new MissingPluginMethodError(MISSING_METHOD); } @@ -113,6 +111,9 @@ export const initialize = async ( const storage = pluginStorage(); for await (const pluginName of Object.keys(plugins)) { + console.log('\n'); + console.debug(INITIALIZING_PLUGIN(pluginName)); + const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; From fe5cb1ad9fe00d0e4d5c60850ce404ea618db094 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 14:26:13 +0400 Subject: [PATCH 642/863] test(src): update tests --- src/__tests__/if-merge/util/helpers.test.ts | 2 +- src/__tests__/if-run/lib/exhaust.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index 1f4c0609f..2b7a27d04 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -149,7 +149,7 @@ describe('if-merge/util/helpers: ', () => { await mergeManifests(mockCommandArgs); expect.assertions(1); - expect(consopleSpy).toHaveBeenCalledTimes(1); + expect(consopleSpy).toHaveBeenCalledTimes(2); }); it('gets YAML files when there is only one manifest.', async () => { diff --git a/src/__tests__/if-run/lib/exhaust.test.ts b/src/__tests__/if-run/lib/exhaust.test.ts index 71d2367e6..1b1ad007a 100644 --- a/src/__tests__/if-run/lib/exhaust.test.ts +++ b/src/__tests__/if-run/lib/exhaust.test.ts @@ -53,7 +53,7 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {'no-outout': false}); - expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(2); }); }); }); From 18bcefe5497b23edfe8d5e9880a1bfceaecab1a8 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 14:53:28 +0400 Subject: [PATCH 643/863] fix(builtins): add a check for the config in missing plugins --- src/if-run/builtins/exponent/index.ts | 10 ++++++++++ src/if-run/builtins/mock-observations/index.ts | 10 ++++++++++ src/if-run/builtins/multiply/index.ts | 10 ++++++++++ src/if-run/builtins/sci/index.ts | 13 ++++++++++--- src/if-run/builtins/shell/index.ts | 9 ++++++++- src/if-run/builtins/subtract/index.ts | 10 ++++++++++ 6 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index aef2faead..096128fa0 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -5,9 +5,15 @@ import { ExponentConfig, PluginParametersMetadata, } from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Exponent = ( config: ExponentConfig, parametersMetadata: PluginParametersMetadata @@ -22,6 +28,10 @@ export const Exponent = ( * Checks config value are valid. */ const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const configSchema = z.object({ 'input-parameter': z.string().min(1), exponent: z.number(), diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index dc4111677..4bc421601 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -7,14 +7,20 @@ import { ObservationParams, PluginParametersMetadata, } from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const MockObservations = ( config: ConfigParams, parametersMetadata: PluginParametersMetadata @@ -58,6 +64,10 @@ export const MockObservations = ( * Validates config parameters. */ const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z.object({ 'timestamp-from': z.string(), 'timestamp-to': z.string(), diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 5da795c3b..834bdacaa 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -5,9 +5,15 @@ import { MultiplyConfig, PluginParametersMetadata, } from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Multiply = ( config: MultiplyConfig, parametersMetadata: PluginParametersMetadata @@ -22,6 +28,10 @@ export const Multiply = ( * Checks config value are valid. */ const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const configSchema = z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 8dba4a4fc..138fe961d 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -12,6 +12,9 @@ import {validate, allDefined} from '../../../common/util/validations'; import {STRINGS} from '../../config'; +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + const {MissingInputDataError} = ERRORS; const { MISSING_FUNCTIONAL_UNIT_CONFIG, @@ -52,9 +55,13 @@ export const Sci = ( }; /** - * Validates node and gloabl configs. + * Validates config. */ - const validateConfig = (config?: ConfigParams) => { + const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z .object({ 'functional-unit': z.string(), @@ -93,7 +100,7 @@ export const Sci = ( * Checks for fields in input. */ const validateInput = (input: PluginParams) => { - const validatedConfig = validateConfig(config); + const validatedConfig = validateConfig(); if ( !( diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 9a24f1ee5..9b81bf16d 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -12,7 +12,10 @@ import { import {validate} from '../../../common/util/validations'; -const {ProcessExecutionError} = ERRORS; +import {STRINGS} from '../../config'; + +const {ProcessExecutionError, ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; export const Shell = ( config: ConfigParams, @@ -40,6 +43,10 @@ export const Shell = ( * Checks for required fields in input. */ const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z.object({ command: z.string(), }); diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 75303d80b..11dd344c1 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -5,9 +5,15 @@ import { PluginParams, SubtractConfig, } from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Subtract = ( config: SubtractConfig, parametersMetadata: PluginParametersMetadata @@ -22,6 +28,10 @@ export const Subtract = ( * Checks config value are valid. */ const validateConfig = () => { + if (!config) { + throw new ConfigError(MISSING_CONFIG); + } + const configSchema = z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), From 335cfe7cf8e8f2045bf484fb19404780de12ecd1 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 15:02:11 +0400 Subject: [PATCH 644/863] test(util): fix typo --- src/__tests__/if-merge/util/helpers.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index 2b7a27d04..0840b9e14 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -50,10 +50,10 @@ jest.mock('../../../if-run/builtins/export-yaml', () => ({ })); describe('if-merge/util/helpers: ', () => { - const consopleSpy = jest.spyOn(global.console, 'log'); + const consoleSpy = jest.spyOn(global.console, 'log'); beforeEach(() => { - consopleSpy.mockReset(); + consoleSpy.mockReset(); }); describe('mergeManifests(): ', () => { @@ -149,7 +149,7 @@ describe('if-merge/util/helpers: ', () => { await mergeManifests(mockCommandArgs); expect.assertions(1); - expect(consopleSpy).toHaveBeenCalledTimes(2); + expect(consoleSpy).toHaveBeenCalledTimes(2); }); it('gets YAML files when there is only one manifest.', async () => { From 30acccdc92dc5737807eca73fb8881738cab187b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 15:17:41 +0400 Subject: [PATCH 645/863] fix(lib): change console.log to console.debug for empty row --- src/if-run/lib/exhaust.ts | 2 +- src/if-run/lib/initialize.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/exhaust.ts b/src/if-run/lib/exhaust.ts index c08926164..60a121684 100644 --- a/src/if-run/lib/exhaust.ts +++ b/src/if-run/lib/exhaust.ts @@ -21,7 +21,7 @@ export const exhaust = async ( outputOptions: Options ) => { console.debug(PREPARING_OUTPUT_DATA); - console.log('\n'); + console.debug('\n'); if (!outputOptions.noOutput && !outputOptions.outputPath) { ExportLog().execute(tree, context); diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index cb5157b83..839bff98f 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -111,7 +111,7 @@ export const initialize = async ( const storage = pluginStorage(); for await (const pluginName of Object.keys(plugins)) { - console.log('\n'); + console.debug('\n'); console.debug(INITIALIZING_PLUGIN(pluginName)); const plugin = await initPlugin(plugins[pluginName]); From 8019d8f346f87ece3112ebb0147bcf16ed9a17b8 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 15:19:21 +0400 Subject: [PATCH 646/863] test(src): revert tests --- src/__tests__/if-merge/util/helpers.test.ts | 2 +- src/__tests__/if-run/lib/exhaust.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-merge/util/helpers.test.ts b/src/__tests__/if-merge/util/helpers.test.ts index 0840b9e14..ba1198d65 100644 --- a/src/__tests__/if-merge/util/helpers.test.ts +++ b/src/__tests__/if-merge/util/helpers.test.ts @@ -149,7 +149,7 @@ describe('if-merge/util/helpers: ', () => { await mergeManifests(mockCommandArgs); expect.assertions(1); - expect(consoleSpy).toHaveBeenCalledTimes(2); + expect(consoleSpy).toHaveBeenCalledTimes(1); }); it('gets YAML files when there is only one manifest.', async () => { diff --git a/src/__tests__/if-run/lib/exhaust.test.ts b/src/__tests__/if-run/lib/exhaust.test.ts index 1b1ad007a..71d2367e6 100644 --- a/src/__tests__/if-run/lib/exhaust.test.ts +++ b/src/__tests__/if-run/lib/exhaust.test.ts @@ -53,7 +53,7 @@ describe('lib/exhaust: ', () => { // @ts-ignore await exhaust(tree, context, {'no-outout': false}); - expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledTimes(1); }); }); }); From 88e82c8ff71b273dfe635f4c25fe2993014cc501 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 17:21:43 +0400 Subject: [PATCH 647/863] fix(config): change `OBSERVING` type --- src/if-run/config/strings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 943d9962c..86185b1c9 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -53,7 +53,7 @@ Note that for the '--output' option you also need to define the output type in y COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => `Computing pipeline for \`${nodeName}\``, REGROUPING: 'Regrouping', - OBSERVING: 'Observing', + OBSERVING: (nodeName: string) => `Observing pipeline for \`${nodeName}\``, MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', AGGREGATING_OUTPUTS: 'Aggregating outputs', AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, From 4bc8a98ecbac866790165ab3ea148f4ecd045aa3 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 17:31:13 +0400 Subject: [PATCH 648/863] fix(lib): add missing debug logs --- src/if-run/lib/compute.ts | 11 ++++++++--- src/if-run/lib/initialize.ts | 5 ++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 27e037a72..73449bb97 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -17,6 +17,7 @@ const { MERGING_DEFAULTS_WITH_INPUT_DATA, EMPTY_PIPELINE, CONFIG_WARN, + COMPUTING_PIPELINE_FOR_NODE, REGROUPING, OBSERVING, } = STRINGS; @@ -72,6 +73,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { const defaults = node.defaults || params.defaults; const noFlags = !params.observe && !params.regroup && !params.compute; + debugLogger.setExecutingPluginName(); warnIfConfigProvided(node); if (node.children) { @@ -102,9 +104,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { */ if ((noFlags || params.observe) && pipelineCopy.observe) { while (pipelineCopy.observe.length !== 0) { - console.debug(OBSERVING); - const pluginName = pipelineCopy.observe.shift() as string; + console.debug(OBSERVING(pluginName)); + debugLogger.setExecutingPluginName(pluginName); + const plugin = params.pluginStorage.get(pluginName); const nodeConfig = config && config[pluginName]; @@ -131,6 +134,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { delete node.inputs; delete node.outputs; + debugLogger.setExecutingPluginName(); console.debug(REGROUPING); return traverse(node.children, { @@ -165,7 +169,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { }); } - debugLogger.setExecutingPluginName(); + console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); + debugLogger.setExecutingPluginName(pluginName); } } } diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 839bff98f..48b90a023 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -86,6 +86,8 @@ const initPlugin = async ( 'global-config': globalConfig, 'parameter-metadata': parameterMetadata, } = initPluginParams!; + console.debug('\n'); + console.debug(INITIALIZING_PLUGIN(method)); if (!method) { throw new MissingPluginMethodError(MISSING_METHOD); @@ -111,9 +113,6 @@ export const initialize = async ( const storage = pluginStorage(); for await (const pluginName of Object.keys(plugins)) { - console.debug('\n'); - console.debug(INITIALIZING_PLUGIN(pluginName)); - const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; From 45e8077d0e7e4e2fab1b126772cd923de0d6b946 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 18:50:51 +0400 Subject: [PATCH 649/863] fix(config): update strings --- src/if-run/config/strings.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 86185b1c9..35ad7cb67 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -51,9 +51,10 @@ Note that for the '--output' option you also need to define the output type in y LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => `Loading ${pluginName} from ${path}`, COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => - `Computing pipeline for \`${nodeName}\``, + `Running compute pipeline: \`${nodeName}\` plugin`, REGROUPING: 'Regrouping', - OBSERVING: (nodeName: string) => `Observing pipeline for \`${nodeName}\``, + OBSERVING: (nodeName: string) => + `Running observe pipeline: \`${nodeName}\` plugin`, MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', AGGREGATING_OUTPUTS: 'Aggregating outputs', AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, From c7f89f79dcb7c72dd0dc31ec655cf12a8f849c39 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 14 Aug 2024 18:51:56 +0400 Subject: [PATCH 650/863] fix(lib): fix logs positions --- src/if-run/lib/compute.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 73449bb97..8d29c1c8f 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -157,8 +157,13 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { const plugin = params.pluginStorage.get(pluginName); const nodeConfig = config && config[pluginName]; + console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); + debugLogger.setExecutingPluginName(pluginName); + if (isExecute(plugin)) { inputStorage = await plugin.execute(inputStorage, nodeConfig); + debugLogger.setExecutingPluginName(); + node.outputs = inputStorage; if (params.context.explainer) { @@ -168,9 +173,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { pluginData: params.context.initialize!.plugins[pluginName], }); } - - console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); - debugLogger.setExecutingPluginName(pluginName); } } } From cd22343f5ee0e4f6372541d10fbc60f2601f785a Mon Sep 17 00:00:00 2001 From: James Crowley Date: Sun, 4 Aug 2024 17:59:13 +1000 Subject: [PATCH 651/863] feat(src): add support for appending to existing outputs Signed-off-by: James Crowley --- src/__tests__/if-run/lib/compute.test.ts | 34 ++++++++++++++++++++++++ src/if-run/config/config.ts | 6 +++++ src/if-run/index.ts | 2 ++ src/if-run/lib/compute.ts | 4 +++ src/if-run/types/compute.ts | 1 + src/if-run/types/process-args.ts | 2 ++ src/if-run/util/args.ts | 2 ++ 7 files changed, 51 insertions(+) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index 4663d461b..ae062b2bb 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -252,6 +252,40 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); + + it('computes simple tree with append and execute plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + outputs: [ + { + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + duration: 10, + }, + { + timestamp: 'mock-timestamp-2', + newField: 'mock-newField', + duration: 10, + }, + ], + }, + }, + }; + const paramsExecuteWithAppend = {...paramsExecute, append: true}; + const response = await compute(tree, paramsExecuteWithAppend); + const expectedResult = [ + ...tree.children.mockChild.outputs, + ...mockExecutePlugin().execute(tree.children.mockChild.inputs), + ]; + expect(response.children.mockChild.outputs).toHaveLength(4); + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); }); it('computes simple tree with observe plugin.', async () => { diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index 9bd39d89f..881dbf6e3 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -38,6 +38,12 @@ export const CONFIG = { alias: 'h', description: '[prints out the above help instruction]', }, + append: { + type: Boolean, + optional: true, + alias: 'a', + description: '[append to outputs, instead of overwriting]', + }, debug: { type: Boolean, optional: true, diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 6d9f61a78..4652beed2 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -31,6 +31,7 @@ const impactEngine = async () => { observe, regroup, compute: computeFlag, + append, } = options; debugLogger.overrideConsoleMethods(!!debug); @@ -61,6 +62,7 @@ const impactEngine = async () => { observe, regroup, compute: computeFlag, + append, }); const aggregatedTree = aggregate(computedTree, context.aggregation); diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 8caa0a38e..07c5cc27d 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -90,6 +90,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } + const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -158,6 +159,9 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { } } } + if (params.append) { + node.outputs = originalOutputs.concat(node.outputs || []); + } }; /** diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index 56346d390..22b80b9cc 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -25,6 +25,7 @@ export type ComputeParams = { observe?: Boolean; regroup?: Boolean; compute?: Boolean; + append?: boolean; }; export type Node = { diff --git a/src/if-run/types/process-args.ts b/src/if-run/types/process-args.ts index 298cadda6..60deb686b 100644 --- a/src/if-run/types/process-args.ts +++ b/src/if-run/types/process-args.ts @@ -6,6 +6,7 @@ export interface IfRunArgs { observe?: boolean; regroup?: boolean; compute?: boolean; + append?: boolean; } export interface ProcessArgsOutputs { @@ -19,6 +20,7 @@ export interface ProcessArgsOutputs { observe?: boolean; regroup?: boolean; compute?: boolean; + append?: boolean; } export interface Options { diff --git a/src/if-run/util/args.ts b/src/if-run/util/args.ts index 538d37a36..b0cf90b8f 100644 --- a/src/if-run/util/args.ts +++ b/src/if-run/util/args.ts @@ -48,6 +48,7 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { observe, regroup, compute, + append, } = validateAndParseProcessArgs(); if (!output && noOutput) { @@ -66,6 +67,7 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { observe, regroup, compute, + ...(append && {append}), }; } From 65e3fd4dab2d9b80d8b57cdea8dc46ef35b1cc9f Mon Sep 17 00:00:00 2001 From: manushak Date: Sun, 18 Aug 2024 16:48:30 +0400 Subject: [PATCH 652/863] fix(config): update strings of debug mode --- src/if-run/config/strings.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 35ad7cb67..b3b6c8964 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -47,7 +47,7 @@ Note that for the '--output' option you also need to define the output type in y `Checking aggregation method for ${unitName}`, INITIALIZING_PLUGINS: 'Initializing plugins', INITIALIZING_PLUGIN: (pluginName: string) => - `Initializing \`${pluginName}\` plugin`, + `Initializing \`${pluginName}\` instance`, LOADING_PLUGIN_FROM_PATH: (pluginName: string, path: string) => `Loading ${pluginName} from ${path}`, COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => @@ -58,7 +58,10 @@ Note that for the '--output' option you also need to define the output type in y MERGING_DEFAULTS_WITH_INPUT_DATA: 'Merging defaults with input data', AGGREGATING_OUTPUTS: 'Aggregating outputs', AGGREGATING_NODE: (nodeName: string) => `Aggregating node ${nodeName}`, - PREPARING_OUTPUT_DATA: 'Preparing output data', + PREPARING_OUTPUT_DATA: () => { + console.debug('\n'); + return 'Preparing output data'; + }, EXPORTING_TO_YAML_FILE: (savepath: string) => `Exporting to yaml file: ${savepath}`, EMPTY_PIPELINE: `You're using an old style manifest. Please update for phased execution. More information can be found here: From 7040757f0796548b2e4befbcf96ccb8e3509c7bd Mon Sep 17 00:00:00 2001 From: manushak Date: Sun, 18 Aug 2024 16:52:38 +0400 Subject: [PATCH 653/863] feat(lib): add empty rows to seperate debug logs by sections --- src/if-run/lib/aggregate.ts | 1 + src/if-run/lib/compute.ts | 5 ++++- src/if-run/lib/exhaust.ts | 3 +-- src/if-run/lib/initialize.ts | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 508d7df25..cd19b00e9 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -145,6 +145,7 @@ const metricManager = (() => { */ export const getAggregationMethod = (unitName: string) => { debugLogger.setExecutingPluginName(); + memoizedLog(console.debug, '\n'); memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); const aggregationMetricsStorage = storeAggregationMetrics(); diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 8d29c1c8f..b5558af92 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -46,7 +46,7 @@ const mergeDefaults = ( return response; } - console.debug(MERGING_DEFAULTS_WITH_INPUT_DATA); + console.debug(MERGING_DEFAULTS_WITH_INPUT_DATA, '\n'); return defaults ? [defaults] : []; }; @@ -148,6 +148,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { }); } + console.debug('\n'); + /** * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. */ @@ -176,6 +178,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { } } } + console.debug('\n'); }; /** diff --git a/src/if-run/lib/exhaust.ts b/src/if-run/lib/exhaust.ts index 60a121684..f38977f4b 100644 --- a/src/if-run/lib/exhaust.ts +++ b/src/if-run/lib/exhaust.ts @@ -20,8 +20,7 @@ export const exhaust = async ( context: Context, outputOptions: Options ) => { - console.debug(PREPARING_OUTPUT_DATA); - console.debug('\n'); + console.debug(PREPARING_OUTPUT_DATA(), '\n'); if (!outputOptions.noOutput && !outputOptions.outputPath) { ExportLog().execute(tree, context); diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 48b90a023..abb9647d9 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -56,7 +56,7 @@ const importAndVerifyModule = async (method: string, path: string) => { * Imports module, then checks if it's a valid plugin. */ const handModule = (method: string, pluginPath: string) => { - console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath)); + console.debug(LOADING_PLUGIN_FROM_PATH(method, pluginPath), '\n'); if (pluginPath === 'builtin') { pluginPath = path.normalize(`${__dirname}/../builtins`); @@ -86,8 +86,6 @@ const initPlugin = async ( 'global-config': globalConfig, 'parameter-metadata': parameterMetadata, } = initPluginParams!; - console.debug('\n'); - console.debug(INITIALIZING_PLUGIN(method)); if (!method) { throw new MissingPluginMethodError(MISSING_METHOD); @@ -108,11 +106,13 @@ const initPlugin = async ( export const initialize = async ( context: Context ): Promise => { - console.debug(INITIALIZING_PLUGINS); + console.debug(INITIALIZING_PLUGINS, '\n'); const {plugins} = context.initialize; const storage = pluginStorage(); for await (const pluginName of Object.keys(plugins)) { + console.debug(INITIALIZING_PLUGIN(pluginName)); + const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; From aeddbed18f1403626e119c8cbbddacfd4d68a07f Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 09:04:47 +0400 Subject: [PATCH 654/863] feat(util): add map output functionality --- src/common/util/helpers.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index f9cc69db4..3a1f623ef 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -112,3 +112,22 @@ export const mapConfigIfNeeded = (config: any, mapping: MappingParams) => { return result; }; + +/** + * Maps the output parameter of the plugin if the `mapping` parameter is provided. + */ +export const mapOutputIfNeeded = ( + 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 b45a63bdd5d4c39ffb9d5289acb6e743e384bd34 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 09:17:22 +0400 Subject: [PATCH 655/863] feat(builtins): add map output logic into plugins --- src/if-run/builtins/coefficient/index.ts | 9 +++-- src/if-run/builtins/copy-param/index.ts | 9 +++-- src/if-run/builtins/csv-lookup/index.ts | 9 +++-- src/if-run/builtins/divide/index.ts | 9 +++-- src/if-run/builtins/exponent/index.ts | 9 +++-- src/if-run/builtins/interpolation/index.ts | 15 +++++--- .../builtins/mock-observations/index.ts | 34 ++++++++++++------- src/if-run/builtins/multiply/index.ts | 9 +++-- src/if-run/builtins/regex/index.ts | 9 +++-- src/if-run/builtins/sci-embodied/index.ts | 9 +++-- src/if-run/builtins/sci/index.ts | 9 +++-- src/if-run/builtins/shell/index.ts | 8 +++-- src/if-run/builtins/subtract/index.ts | 9 +++-- src/if-run/builtins/sum/index.ts | 9 +++-- src/if-run/builtins/time-converter/index.ts | 13 ++++--- src/if-run/builtins/time-sync/index.ts | 8 +++-- 16 files changed, 130 insertions(+), 47 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 4e2b29bbc..289b4d7be 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -9,7 +9,10 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -39,10 +42,12 @@ export const Coefficient = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - return { + const result = { ...input, [outputParameter]: calculateProduct(input, inputParameter, coefficient), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index cbee3252a..2128cff7d 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -11,7 +11,10 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; const {MISSING_CONFIG} = STRINGS; const {ConfigError} = ERRORS; @@ -91,10 +94,12 @@ export const Copy = ( } } - return { + const result = { ...safeInput, // need to return or what you provide won't be outputted, don't be evil! [to]: outputValue, }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 38b7b112f..373cbdeb0 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -15,7 +15,10 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; const { FILE_FETCH_FAILED, @@ -221,10 +224,12 @@ export const CSVLookup = ( throw new QueryDataNotFoundError(NO_QUERY_DATA); } - return { + const result = { ...input, ...filterOutput(relatedData, {output, query}), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 66ab8faab..ba02194bb 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -11,7 +11,10 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; const {ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; @@ -41,10 +44,12 @@ export const Divide = ( validateSingleInput(input, {numerator, denominator}) ); - return { + const result = { ...input, [output]: calculateDivide(safeInput, index, {numerator, denominator}), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 79a0d7ce3..38bc07d49 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -9,7 +9,10 @@ import { import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -71,10 +74,12 @@ export const Exponent = ( return inputs.map(input => { validateSingleInput(input, inputParameter); - return { + const result = { ...input, [outputParameter]: calculateExponent(input, inputParameter, exponent), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 6c1965f0e..1bd1cf48b 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -11,7 +11,10 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -38,12 +41,16 @@ export const Interpolation = ( return inputs.map((input, index) => { const safeInput = validateInput(input, index); - const result = calculateResult(validatedConfig, safeInput); - return { + const result = { ...input, - [validatedConfig['output-parameter']]: result, + [validatedConfig['output-parameter']]: calculateResult( + validatedConfig, + safeInput + ), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index 6a110f004..7b1dfee89 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -11,7 +11,10 @@ import { import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -48,19 +51,24 @@ export const MockObservations = ( 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 result = 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 result.map(output => mapOutputIfNeeded(output, mapping)); }; /** diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 65a75259f..e33ee1f15 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -9,7 +9,10 @@ import { import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -79,10 +82,12 @@ export const Multiply = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - return { + const result = { ...input, [outputParameter]: calculateProduct(input, inputParameters), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 266363d30..9f017e8e8 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -9,7 +9,10 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -71,10 +74,12 @@ export const Regex = ( validateSingleInput(input, parameter) ); - return { + const result = { ...input, [output]: extractMatching(safeInput, parameter, match), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index b18410454..1aad045a5 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -10,7 +10,10 @@ import { import {validate, allDefined} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {mapInputIfNeeded} from '../../../common/util/helpers'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; const {SCI_EMBODIED_ERROR} = STRINGS; @@ -83,10 +86,12 @@ export const SciEmbodied = ( const mappedInput = mapInputIfNeeded(input, mapping); const safeInput = validateInput(mappedInput); - return { + const result = { ...input, 'carbon-embodied': calculateEmbodiedCarbon(safeInput), }; + + return mapOutputIfNeeded(result, mapping); }); /** diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index ea97be941..dbafa6352 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -10,7 +10,10 @@ import { } from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; -import {mapInputIfNeeded} from '../../../common/util/helpers'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -94,10 +97,12 @@ export const Sci = ( }; } - return { + const result = { ...input, sci: safeInput['carbon'] / functionalUnit, }; + + return mapOutputIfNeeded(result, mapping); }); }; /** diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 7095b69da..8926a266e 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -8,9 +8,11 @@ import { PluginParams, ConfigParams, PluginParametersMetadata, + MappingParams, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; +import {mapOutputIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -19,7 +21,8 @@ const {MISSING_CONFIG} = STRINGS; export const Shell = ( config: ConfigParams, - parametersMetadata: PluginParametersMetadata + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams ): ExecutePlugin => { const metadata = { kind: 'execute', @@ -35,8 +38,9 @@ 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 results?.outputs?.flat() as PluginParams[]; + return outputs.map(output => mapOutputIfNeeded(output, mapping)); }; /** diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 5d468ade9..d4dc1181a 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -9,7 +9,10 @@ import { import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -80,10 +83,12 @@ export const Subtract = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - return { + const result = { ...input, [outputParameter]: calculateDiff(input, inputParameters), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 3bacdae11..eb0e519a5 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -9,7 +9,10 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; @@ -38,10 +41,12 @@ export const Sum = ( return inputs.map(input => { validateSingleInput(input, inputParameters); - return { + const result = { ...input, [outputParameter]: calculateSum(input, inputParameters), }; + + return mapOutputIfNeeded(result, mapping); }); }; diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index 66c35843e..e757ed967 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -13,7 +13,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {TIME_UNITS_IN_SECONDS} from './config'; -import {mapConfigIfNeeded} from '../../../common/util/helpers'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; @@ -37,10 +40,12 @@ export const TimeConverter = ( return inputs.map(input => { validateInput(input, inputParameter); - return { + const result = { ...input, [outputParameter]: calculateEnergy(input), }; + + return mapOutputIfNeeded(result, mapping); }); }; @@ -80,7 +85,7 @@ export const TimeConverter = ( throw new ConfigError(MISSING_CONFIG); } - const mappedConfig = mapConfigIfNeeded(config, mapping); + config = mapConfigIfNeeded(config, mapping); const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); const originalTimeUnitValuesWithDuration = [ 'duration', @@ -95,7 +100,7 @@ export const TimeConverter = ( 'output-parameter': z.string().min(1), }); - return validate>(configSchema, mappedConfig); + return validate>(configSchema, config); }; return { metadata, diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 39015b161..5d909bf77 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -18,7 +18,10 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {getAggregationMethod} from '../../lib/aggregate'; -import {mapInputIfNeeded} from '../../../common/util/helpers'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '../../../common/util/helpers'; Settings.defaultZone = 'utc'; @@ -155,7 +158,8 @@ export const TimeSync = ( 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 => mapOutputIfNeeded(output, mapping)); }; /** From 8b2f89bf63c4cdf97c24ad2f4f0edd0c19506322 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 10:54:01 +0400 Subject: [PATCH 656/863] fix(src): fix node-level config warning --- src/if-run/config/strings.ts | 10 +++++++--- src/if-run/lib/compute.ts | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 92e36712c..dce2b6294 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -108,10 +108,14 @@ ${error}`, MISSING_CONFIG: 'Config is not provided.', MISSING_INPUT_DATA: (param: string) => `${param} is missing from the input array, or has nullish value.`, - CONFIG_WARN: (plugins: string, isMore: boolean) => - `You have included node-level config in your manifest to support \`${plugins}\` plugin${ + CONFIG_WARN: (plugins: string, isMore: boolean) => { + const withoutPlugins = `You have included node-level config in your manifest. IF no longer supports node-level config. The manifest should be refactored to accept all its node-level config from config or input data.`; + const withPlugins = `You have included node-level config in your manifest to support \`${plugins}\` plugin${ isMore ? 's' : '' }. IF no longer supports node-level config. \`${plugins}\` plugin${ isMore ? 's' : '' - } should be refactored to accept all its config from config or input data.`, + } should be refactored to accept all its config from config or input data.`; + + return plugins.length ? withPlugins : withoutPlugins; + }, }; diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 8caa0a38e..8db75cd95 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -165,7 +165,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { */ const warnIfConfigProvided = (node: any) => { if ('config' in node) { - const plugins = Object.keys(node.config); + const plugins = Object.keys(node.config || {}); const joinedPlugins = plugins.join(', '); const isMore = plugins.length > 1; From ac8362260c62a648b0d56a244ac837b703b3b013 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 10:57:30 +0400 Subject: [PATCH 657/863] fix(builtins): update mapping descritption in Readme files --- src/if-run/builtins/coefficient/README.md | 6 +++--- src/if-run/builtins/copy-param/README.md | 6 +++--- src/if-run/builtins/csv-lookup/README.md | 2 +- src/if-run/builtins/divide/README.md | 2 +- src/if-run/builtins/exponent/README.md | 6 +++--- src/if-run/builtins/interpolation/README.md | 2 +- src/if-run/builtins/mock-observations/README.md | 10 +++------- src/if-run/builtins/multiply/README.md | 6 +++--- src/if-run/builtins/regex/README.md | 2 +- src/if-run/builtins/sci-embodied/README.md | 2 +- src/if-run/builtins/sci/README.md | 6 +++--- src/if-run/builtins/shell/README.md | 4 ++-- src/if-run/builtins/subtract/README.md | 6 +++--- src/if-run/builtins/sum/README.md | 6 +++--- 14 files changed, 31 insertions(+), 35 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 218936041..38209f953 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -34,7 +34,7 @@ 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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml coefficient: @@ -63,7 +63,7 @@ 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 globalConfig = { +const config = { 'input-parameter': 'carbon', coefficient: 10, 'output-parameter': 'carbon-product', @@ -71,7 +71,7 @@ const globalConfig = { const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const coeff = Coefficient(globalConfig, parametersMetadata, mapping); +const coeff = Coefficient(config, parametersMetadata, mapping); 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 997540c76..331c95e95 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -56,7 +56,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml copy-param: @@ -81,7 +81,7 @@ To run the plugin, you must first create an instance of `Copy`. Then, you can ca ```typescript import {Copy} from '.'; -const globalConfig = { +const config = { 'keep-existing': true, from: 'from-param', to: 'to-param', @@ -89,7 +89,7 @@ const globalConfig = { const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const plugin = Copy(globalConfig, parametersMetadata, mapping); +const plugin = Copy(config, parametersMetadata, mapping); 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 e5059c5bb..72ac25bab 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -70,7 +70,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml cloud-metadata: diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index b7b296cda..7280a94fd 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -29,7 +29,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml divide: diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index a743fcedb..4065e9ae3 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -33,7 +33,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml exponent: @@ -64,7 +64,7 @@ To run the plugin, you must first create an instance of `Exponent`. Then, you ca ```typescript import {Exponent} from 'builtins'; -const globalConfig = { +const config = { inputParameter: ['cpu/energy'], exponent: 2 outputParameter: 'energy', @@ -72,7 +72,7 @@ const globalConfig = { const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const exponent = Exponent(globalConfig, parametersMetadata, mapping); +const exponent = Exponent(config, parametersMetadata, mapping); 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 6a9097c74..35ef4df5e 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -42,7 +42,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml interpolation: diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index 1a69d99a4..b95da0bab 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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml mock-observations: @@ -57,7 +57,7 @@ The plugin's `config` section in the manifest file determines its behaviour. ### Typescript Usage ```typescript -const globalConfig = { +const config = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:10', duration: 60, @@ -72,11 +72,7 @@ const globalConfig = { }; const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const mockObservations = MockObservations( - globalConfig, - parametersMetadata, - mapping -); +const mockObservations = MockObservations(config, parametersMetadata, mapping); const result = await mockObservations.execute([]); ``` diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index a16872ef6..36d03e4c5 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -32,7 +32,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml multiply: @@ -63,14 +63,14 @@ To run the plugin, you must first create an instance of `Multiply`. Then, you ca ```typescript import {Multiply} from 'builtins'; -const globalConfig = { +const config = { inputParameters: ['cpu/energy', 'network/energy'], outputParameter: 'energy-product', }; const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const multiply = Multiply(globalConfig, parametersMetadata, mapping); +const multiply = Multiply(config, parametersMetadata, mapping); 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 5aff8fb4e..1d2a9ca00 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -33,7 +33,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml regex: diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index dd75dea6c..8933de211 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -27,7 +27,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml sci-embodied: diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index c9a11f217..10f9e5fea 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -26,7 +26,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml sci: @@ -61,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 globalConfig = {'functional-unit': 'requests'} +const config = {'functional-unit': 'requests'} const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const sci = Sci(globalConfig, parametersMetadata, mapping); +const sci = Sci(config, parametersMetadata, mapping); const results = await sci.execute( [ { diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index 08c9f70f2..2357e46c2 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -53,11 +53,11 @@ 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 globalConfig = { +const config = { command: '/usr/local/bin/sampler', }; const parametersMetadata = {inputs: {}, outputs: {}}; -const output = Shell(globalConfig, parametersMetadata); +const output = Shell(config, parametersMetadata); 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 fc0fee1dc..e19e873ec 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -32,7 +32,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml subtract: @@ -63,13 +63,13 @@ To run the plugin, you must first create an instance of `Subtract`. Then, you ca ```typescript import {Subtract} from 'builtins'; -const globalConfig = { +const config = { inputParameters: ['cpu/energy', 'network/energy'], outputParameter: 'offset/energy', }; const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; -const subtract = Subtract(globalConfig, parametersMetadata, mapping); +const subtract = Subtract(config, parametersMetadata, mapping); const result = subtract subtract.execute([ { duration: 3600, diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index eda6b0612..c6ba6d0cb 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -32,7 +32,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 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: +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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: ```yaml sum: @@ -61,7 +61,7 @@ output = input0 + input1 + input2 ... inputN To run the plugin, you must first create an instance of `Sum`. Then, you can call `execute()`. ```typescript -const globalConfig = { +const config = { inputParameters: ['cpu/energy', 'network/energy'], outputParameter: 'energy', }; @@ -71,7 +71,7 @@ const = mapping { 'network/energy': 'energy-from-network', }; -const sum = Sum(globalConfig, parametersMetadata, mapping); +const sum = Sum(config, parametersMetadata, mapping); const result = sum.execute([ { timestamp: '2021-01-01T00:00:00Z', From 3f63a32a577c9bcbbe6f339a53b70ddf5e61ce00 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 11:01:41 +0400 Subject: [PATCH 658/863] test(util): add tests for mapOutputIfNeeded function --- src/__tests__/common/util/helpers.test.ts | 54 +++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts index b73e638ef..387689371 100644 --- a/src/__tests__/common/util/helpers.test.ts +++ b/src/__tests__/common/util/helpers.test.ts @@ -6,6 +6,7 @@ import { parseManifestFromStdin, mapInputIfNeeded, mapConfigIfNeeded, + mapOutputIfNeeded, } from '../../../common/util/helpers'; describe('common/util/helpers: ', () => { @@ -140,4 +141,57 @@ describe('common/util/helpers: ', () => { expect(mapConfigIfNeeded([], {})).toEqual([]); }); }); + + describe('mapOutputIfNeeded(): ', () => { + 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 = mapOutputIfNeeded(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 = mapOutputIfNeeded(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 = mapOutputIfNeeded(output, mapping); + + expect.assertions(1); + expect(mappedOutput).toEqual(expectedOutput); + }); + }); }); From 9bfadcc35b22acdcf9ec013991a285a25c9745a0 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 11:05:13 +0400 Subject: [PATCH 659/863] fix(config): fix lint warnring --- src/if-run/config/strings.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index dce2b6294..777779c2f 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -109,7 +109,8 @@ ${error}`, MISSING_INPUT_DATA: (param: string) => `${param} is missing from the input array, or has nullish value.`, CONFIG_WARN: (plugins: string, isMore: boolean) => { - const withoutPlugins = `You have included node-level config in your manifest. IF no longer supports node-level config. The manifest should be refactored to accept all its node-level config from config or input data.`; + const withoutPlugins = + 'You have included node-level config in your manifest. IF no longer supports node-level config. The manifest should be refactored to accept all its node-level config from config or input data.'; const withPlugins = `You have included node-level config in your manifest to support \`${plugins}\` plugin${ isMore ? 's' : '' }. IF no longer supports node-level config. \`${plugins}\` plugin${ From eb3fb680eabe10bcc1f7069b672c7eac89de95b5 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 11:07:36 +0400 Subject: [PATCH 660/863] test(builtins): add tests for mapping output --- .../if-run/builtins/coefficient.test.ts | 30 +++++++++ .../if-run/builtins/copy-param.test.ts | 28 +++++++++ .../if-run/builtins/csv-lookup.test.ts | 42 ++++++++++++- src/__tests__/if-run/builtins/divide.test.ts | 28 +++++++++ .../if-run/builtins/exponent.test.ts | 35 ++++++++++- .../if-run/builtins/interpolation.test.ts | 34 +++++++++- .../if-run/builtins/mock-observations.test.ts | 20 +++--- .../if-run/builtins/multiply.test.ts | 39 +++++++++++- src/__tests__/if-run/builtins/regex.test.ts | 36 ++++++++++- .../if-run/builtins/sci-embodied.test.ts | 50 +++++++++++++++ src/__tests__/if-run/builtins/sci.test.ts | 32 ++++++++++ src/__tests__/if-run/builtins/shell.test.ts | 8 +-- .../if-run/builtins/subtract.test.ts | 39 +++++++++++- src/__tests__/if-run/builtins/sum.test.ts | 37 +++++++++++ .../if-run/builtins/time-converter.test.ts | 62 +++++++++++++++++++ 15 files changed, 492 insertions(+), 28 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 9c8a912d0..0aa638d50 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -83,6 +83,36 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('succcessfully executes when the mapping map output parameter.', () => { + const mapping = { + 'carbon-product': 'carbon-result', + }; + + const coefficient = Coefficient(config, parametersMetadata, mapping); + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + carbon: 3, + 'carbon-result': 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 coefficient = Coefficient(config!, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index 33c079fd9..fcbd3155c 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -79,6 +79,34 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executed when the `mapping` map output parameter.', () => { + expect.assertions(1); + + const mapping = { + copy: 'result', + }; + + const copy = Copy(config, parametersMetadata, mapping); + const expectedResult = [ + { + duration: 3600, + original: 'hello', + result: '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 config is not provided.', () => { const config = undefined; const copy = Copy(config!, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index 1248878b5..6861f9c39 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -124,7 +124,7 @@ describe('builtins/CSVLookup: ', () => { it('successfully executes when `mapping` has valid data.', async () => { expect.assertions(1); - const globalConfig = { + const config = { filepath: './file.csv', query: { 'cpu-cores-available': 'cpu/available', @@ -137,7 +137,7 @@ describe('builtins/CSVLookup: ', () => { const mapping = { 'cpu/utilized': 'cpu/util', }; - const csvLookup = CSVLookup(globalConfig, parameterMetadata, mapping); + const csvLookup = CSVLookup(config, parameterMetadata, mapping); const result = await csvLookup.execute([ { @@ -160,6 +160,44 @@ describe('builtins/CSVLookup: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` map output parameter.', async () => { + expect.assertions(1); + 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 parameterMetadata = {inputs: {}, outputs: {}}; + const mapping = { + tdp: 'tdp-finder', + }; + const csvLookup = CSVLookup(config, 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/utilized': 16, + 'cpu/manufacturer': 'AWS', + 'tdp-finder': 150, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); + it('rejects with file not found error.', async () => { const config = { filepath: './file-fail.csv', diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index ff5e912e7..10236e5c7 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -79,6 +79,34 @@ describe('builtins/divide: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` map output parameter.', async () => { + expect.assertions(1); + const mapping = { + 'cpu/number-cores': 'cpu-number-cores', + }; + + const divide = Divide(config, parametersMetadata, mapping); + + const expectedResult = [ + { + duration: 3600, + 'vcpus-allocated': 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 config = { diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index e7b3fa9b8..89df469e0 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -54,12 +54,12 @@ describe('builtins/exponent: ', () => { const mapping = { 'energy/base': 'energy/main', }; - const globalConfig = { + const config = { 'input-parameter': 'energy/base', exponent: 3, 'output-parameter': 'energy', }; - const exponent = Exponent(globalConfig, parametersMetadata, mapping); + const exponent = Exponent(config, parametersMetadata, mapping); const expectedResult = [ { duration: 3600, @@ -80,6 +80,37 @@ describe('builtins/exponent: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` maps output parameter.', async () => { + expect.assertions(1); + const mapping = { + energy: 'energy-result', + }; + const config = { + 'input-parameter': 'energy/base', + exponent: 3, + 'output-parameter': 'energy', + }; + const exponent = Exponent(config, parametersMetadata, mapping); + const expectedResult = [ + { + duration: 3600, + 'energy/base': 2, + 'energy-result': 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); diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index a2dad9a12..f2fb7a44f 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -56,14 +56,13 @@ describe('builtins/interpolation: ', () => { it('returns result when `mapping` has valid data.', () => { const mapping = { 'cpu/utilization': 'cpu/util', - 'interpolation-result': 'result', }; const config = { 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', + 'output-parameter': 'result', }; const inputs = [ { @@ -85,6 +84,37 @@ describe('builtins/interpolation: ', () => { expect(plugin.execute(inputs)).toEqual(outputs); }); + it('returns result when the `mapping` maps output parameter.', () => { + const mapping = { + 'interpolation-result': 'result', + }; + const config = { + 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/utilization': 45, + }, + ]; + const plugin = Interpolation(config, parametersMetadata, mapping); + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 45, + result: 0.69625, + }, + ]; + + expect(plugin.execute(inputs)).toEqual(outputs); + }); + it('returns result when the `method` is not provided in the config.', () => { const config = { x: [0, 10, 50, 100], diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index a3ad83fc7..046a066f6 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -14,7 +14,7 @@ describe('builtins/mock-observations: ', () => { }; describe('init: ', () => { it('successfully initalized.', () => { - const globalConfig = { + const config = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', duration: 5, @@ -30,11 +30,7 @@ describe('builtins/mock-observations: ', () => { }, }, }; - const mockObservations = MockObservations( - globalConfig, - parametersMetadata, - {} - ); + const mockObservations = MockObservations(config, parametersMetadata, {}); expect(mockObservations).toHaveProperty('metadata'); expect(mockObservations).toHaveProperty('execute'); @@ -256,7 +252,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const globalConfig = { + const config = { 'timestamp-from': '2023-07-06T00:00', 'timestamp-to': '2023-07-06T00:01', components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -272,7 +268,7 @@ describe('builtins/mock-observations: ', () => { }, }; const mockObservations = MockObservations( - globalConfig, + config, parametersMetadata, {} ); @@ -291,7 +287,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const globalConfig = { + const config = { 'timestamp-from': '2023-07-06T00:00', duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -307,7 +303,7 @@ describe('builtins/mock-observations: ', () => { }, }; const mockObservations = MockObservations( - globalConfig, + config, parametersMetadata, {} ); @@ -326,7 +322,7 @@ describe('builtins/mock-observations: ', () => { expect.assertions(2); try { - const globalConfig = { + const config = { 'timestamp-to': '2023-07-06T00:01', duration: 5, components: [{'instance-type': 'A1'}, {'instance-type': 'B1'}], @@ -342,7 +338,7 @@ describe('builtins/mock-observations: ', () => { }, }; const mockObservations = MockObservations( - globalConfig, + config, parametersMetadata, {} ); diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index 7588d7689..00979ea37 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -59,11 +59,11 @@ describe('builtins/multiply: ', () => { 'network/energy': 'energy-from-network', 'memory/energy': 'energy-from-memory', }; - const globalConfig = { + const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', }; - const multiply = Multiply(globalConfig, parametersMetadata, mapping); + const multiply = Multiply(config, parametersMetadata, mapping); const expectedResult = [ { @@ -89,6 +89,41 @@ describe('builtins/multiply: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` maps output parameter.', async () => { + expect.assertions(1); + const mapping = { + energy: 'total/energy', + }; + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; + const multiply = Multiply(config, parametersMetadata, mapping); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + 'total/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); diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index 864cde571..49974d169 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -80,7 +80,7 @@ describe('builtins/regex: ', () => { }); it('successfully applies regex when `mapping` has valid data.', async () => { - const globalConfig = { + const config = { parameter: 'cloud/instance-type', match: '/(?<=_)[^_]+?(?=_|$)/g', output: 'cloud/instance-type', @@ -89,7 +89,7 @@ describe('builtins/regex: ', () => { const mapping = { 'cloud/instance-type': 'instance-type', }; - const regex = Regex(globalConfig, parametersMetadata, mapping); + const regex = Regex(config, parametersMetadata, mapping); const expectedResult = [ { @@ -110,6 +110,38 @@ describe('builtins/regex: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully applies regex when the `mapping` maps output parameter.', async () => { + const config = { + parameter: 'cloud/instance-type', + match: '/(?<=_)[^_]+?(?=_|$)/g', + output: 'cloud/instance-name', + }; + + const mapping = { + 'cloud/instance-name': 'instance-name', + }; + const regex = Regex(config, parametersMetadata, mapping); + + const expectedResult = [ + { + timestamp: '2023-08-06T00:00', + duration: 3600, + 'cloud/instance-type': 'Standard_DS1_v2', + 'instance-name': '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'; diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index bf3ebfb1e..40670a821 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -119,6 +119,56 @@ describe('builtins/sci-embodied:', () => { ]); }); + it('executes when the `mapping` maps output parameter.', async () => { + const mapping = { + 'carbon-embodied': 'carbon', + }; + const sciEmbodied = SciEmbodied(undefined, 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/emissions-embodied': 200, + 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, + 'resources-reserved': 1, + 'resources-total': 1, + carbon: 4.10958904109589, + }, + { + 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, + carbon: 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 143d34757..0576b1e42 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -78,6 +78,38 @@ describe('builtins/sci:', () => { ]); }); + it('successfully executes when the `mapping` maps output parameter.', async () => { + const mapping = { + sci: 'sci-result', + }; + const sci = Sci(config, parametersMetadata, mapping); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 1, + 'carbon-operational': 0.02, + 'carbon-footprint': 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-result': 0.050199999999999995, + }, + ]); + }); + it('returns the same result regardless of input duration.', async () => { const config = {'functional-unit': 'requests'}; const sci = Sci(config, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/shell.test.ts b/src/__tests__/if-run/builtins/shell.test.ts index 125595ced..d295b21a4 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 globalConfig = {command: 'python3 /path/to/script.py'}; + const config = {command: 'python3 /path/to/script.py'}; const parametersMetadata = { inputs: {}, outputs: {}, }; - const shell = Shell(globalConfig, parametersMetadata); + const shell = Shell(config, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -57,7 +57,7 @@ describe('builtins/shell', () => { }); 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}, ]; @@ -76,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(config, 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 7831f308d..3343e2abd 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -55,11 +55,11 @@ describe('builtins/subtract: ', () => { const mapping = { 'cpu/energy': 'energy-for-cpu', }; - const globalConfig = { + const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', }; - const subtract = Subtract(globalConfig, parametersMetadata, mapping); + const subtract = Subtract(config, parametersMetadata, mapping); expect.assertions(1); const expectedResult = [ @@ -86,6 +86,41 @@ describe('builtins/subtract: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` maps output parameter.', async () => { + const mapping = { + 'energy/diff': 'diff/energy', + }; + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy/diff', + }; + const subtract = Subtract(config, parametersMetadata, mapping); + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 4, + 'network/energy': 2, + 'memory/energy': 1, + 'diff/energy': 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); diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index e742a2762..30701c23f 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -92,6 +92,43 @@ describe('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` maps output parameter.', () => { + expect.assertions(1); + + const mapping = { + energy: 'total/energy', + }; + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': 'energy', + }; + + const sum = Sum(config, parametersMetadata, mapping); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + 'total/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 config is not provided.', () => { const config = undefined; const sum = Sum(config!, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index 4791c6640..646beb3b2 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -52,6 +52,68 @@ describe('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); + it('successfully executes when the `mapping` is not empty object.', () => { + expect.assertions(1); + + const mapping = { + 'energy-per-year': 'energy/year', + }; + const timeConverter = TimeConverter( + config, + parametersMetadata, + mapping + ); + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy/year': 10000, + 'energy-per-duration': 1.140795, + }, + ]; + + const result = timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy/year': 10000, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('successfully executes when the `mapping` maps output parameter.', () => { + expect.assertions(1); + + const mapping = { + 'energy-per-duration': 'energy/duration', + }; + const timeConverter = TimeConverter( + config, + parametersMetadata, + mapping + ); + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + 'energy/duration': 1.140795, + }, + ]; + + const result = timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + it('throws an error when config is not provided.', () => { const config = undefined; const timeConverter = TimeConverter(config!, parametersMetadata, {}); From b68b852c5561b65db0809b743dadaf2206f95f39 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 13:58:03 +0400 Subject: [PATCH 661/863] feat(config): add string for debug log --- src/if-run/config/strings.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 5ddabdecf..64ef8bde4 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -52,6 +52,8 @@ Note that for the '--output' option you also need to define the output type in y `Loading ${pluginName} from ${path}`, COMPUTING_PIPELINE_FOR_NODE: (nodeName: string) => `Running compute pipeline: \`${nodeName}\` plugin`, + COMPUTING_COMPONENT_PIPELINE: (component: string) => + `**Computing \`${component}\` pipeline**`, REGROUPING: 'Regrouping', OBSERVING: (nodeName: string) => `Running observe pipeline: \`${nodeName}\` plugin`, From 16c956d9940eb08c191bed8363439ccdbd3aa66f Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 14:00:13 +0400 Subject: [PATCH 662/863] feat(util): update debug logic to accept exeption in formating message --- src/common/util/debug-logger.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts index 74f7c7dbd..1a9a614d9 100644 --- a/src/common/util/debug-logger.ts +++ b/src/common/util/debug-logger.ts @@ -11,6 +11,7 @@ const logMessagesKeys: (keyof typeof STRINGS)[] = [ 'INITIALIZING_PLUGIN', 'LOADING_PLUGIN_FROM_PATH', 'COMPUTING_PIPELINE_FOR_NODE', + 'COMPUTING_COMPONENT_PIPELINE', 'REGROUPING', 'OBSERVING', 'MERGING_DEFAULTS_WITH_INPUT_DATA', @@ -110,9 +111,12 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { const date = new Date().toISOString(); const plugin = pluginNameManager.currentPluginName; - const formattedMessage = `${level}: ${date}: ${ - plugin ? plugin + ': ' : '' - }${args.join(', ')}`; + const isExeption = args[0].includes('**Computing'); + const message = `${level}: ${date}: ${plugin ? plugin + ': ' : ''}${args.join( + ', ' + )}`; + + const formattedMessage = isExeption ? args.join(', ') : message; if (debugMode) { switch (level) { From 0bcc16343486090d19c3e8ba41f6e0ed5d62c681 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 20 Aug 2024 14:02:19 +0400 Subject: [PATCH 663/863] feat(lib): add debug log for tree components --- src/if-run/lib/compute.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index b5558af92..805216768 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -18,6 +18,7 @@ const { EMPTY_PIPELINE, CONFIG_WARN, COMPUTING_PIPELINE_FOR_NODE, + COMPUTING_COMPONENT_PIPELINE, REGROUPING, OBSERVING, } = STRINGS; @@ -27,6 +28,7 @@ const { */ const traverse = async (children: any, params: ComputeParams) => { for (const child in children) { + console.debug(COMPUTING_COMPONENT_PIPELINE(child)); await computeNode(children[child], params); } }; From 658afa987f4b99063bfc6ccbb5c1d55e052048bd Mon Sep 17 00:00:00 2001 From: James Crowley Date: Fri, 16 Aug 2024 18:41:42 +0100 Subject: [PATCH 664/863] test(lib): make the regroup intended behaviour clearer Signed-off-by: James Crowley --- src/__tests__/if-run/lib/compute.test.ts | 65 +++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index ae062b2bb..a4d9f24df 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -117,24 +117,28 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with groupby plugin.', async () => { + it('computes simple tree with regroup.', async () => { const tree = { children: { mockChild: { - pipeline: {regroup: ['duration']}, + pipeline: {regroup: ['region']}, inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, + {timestamp: 'mock-timestamp-1', region: 'uk-west'}, + {timestamp: 'mock-timestamp-2', region: 'uk-east'}, + {timestamp: 'mock-timestamp-3', region: 'uk-east'}, ], }, }, }; const response = await compute(tree, paramsExecute); const expectedResponse = { - '10': { + 'uk-west': { + inputs: [{region: 'uk-west', timestamp: 'mock-timestamp-1'}], + }, + 'uk-east': { inputs: [ - {duration: 10, timestamp: 'mock-timestamp-1'}, - {duration: 10, timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-3'}, ], }, }; @@ -142,6 +146,53 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.children).toEqual(expectedResponse); }); + it('computes tree with regroup and compute.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [ + {timestamp: 'mock-timestamp-1', region: 'uk-west'}, + {timestamp: 'mock-timestamp-2', region: 'uk-east'}, + {timestamp: 'mock-timestamp-3', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResponse = { + 'uk-west': { + inputs: [{region: 'uk-west', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-west', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + 'uk-east': { + inputs: [ + {region: 'uk-east', timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-3'}, + ], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-2', + newField: 'mock-newField', + }, + { + region: 'uk-east', + timestamp: 'mock-timestamp-3', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + it('computes simple tree with defaults and execute plugin.', async () => { const tree = { children: { From d5e2fda4d5240c9f6eff471e71d625b03779e0ab Mon Sep 17 00:00:00 2001 From: James Crowley Date: Sat, 17 Aug 2024 11:34:15 +0100 Subject: [PATCH 665/863] test(lib): fix typos in test names Signed-off-by: James Crowley --- src/__tests__/if-run/lib/compute.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index a4d9f24df..ba631b990 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -269,7 +269,7 @@ describe('lib/compute: ', () => { ); }); - it('computes simple tree with no defaults and no inputs with execue plugin.', async () => { + it('computes simple tree with no defaults and no inputs with execute plugin.', async () => { const tree = { children: { mockChild: { @@ -284,7 +284,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toBeUndefined(); }); - it('computes simple tree with defaults and no inputs with execue plugin.', async () => { + it('computes simple tree with defaults and no inputs with execute plugin.', async () => { const tree = { children: { mockChild: { From d7a145a16c77f7626e818054a143e637fe9fef47 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:33:50 +0100 Subject: [PATCH 666/863] refactor(lib): refactor regroup so we can then include outputs Signed-off-by: James Crowley --- src/if-run/lib/regroup.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index affd51307..c1a7b554e 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -60,9 +60,12 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { * Interates over inputs, grabs group values for each one. * Based on grouping, initializes the structure. */ - return inputs.reduce((acc, input) => { - const validtedGroups = validateGroups(groups); - const groupsWithData = validtedGroups.map(groupType => { + + const validatedGroups = validateGroups(groups); + + let acc = {} as any; + for (const input of inputs) { + const groupsWithData = validatedGroups.map(groupType => { if (!input[groupType]) { throw new InvalidGroupingError(INVALID_GROUP_KEY(groupType)); } @@ -74,7 +77,7 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { ...acc, ...appendGroup(input, acc, groupsWithData), }; + } - return acc; - }, {} as any).children; + return acc.children; }; From 4b48f878345b4276d74b2e0d0db566268e685454 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:38:36 +0100 Subject: [PATCH 667/863] refactor(lib): extract function for looking up group key value Signed-off-by: James Crowley --- src/if-run/lib/regroup.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index c1a7b554e..279dc6a4f 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -63,16 +63,19 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const validatedGroups = validateGroups(groups); - let acc = {} as any; - for (const input of inputs) { - const groupsWithData = validatedGroups.map(groupType => { - if (!input[groupType]) { - throw new InvalidGroupingError(INVALID_GROUP_KEY(groupType)); - } + const lookupGroupKey = (input: PluginParams, groupKey: string) => { + if (!input[groupKey]) { + throw new InvalidGroupingError(INVALID_GROUP_KEY(groupKey)); + } - return input[groupType]; - }); + return input[groupKey]; + }; + let acc = {} as any; + for (const input of inputs) { + const groupsWithData = validatedGroups.map(groupKey => + lookupGroupKey(input, groupKey) + ); acc = { ...acc, ...appendGroup(input, acc, groupsWithData), From 58697a13d7417b7c972937b984556fc0c3321fc8 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:42:25 +0100 Subject: [PATCH 668/863] refactor(lib): remove unnecessary spread appendGroup already returns acc merged anyway Signed-off-by: James Crowley --- src/if-run/lib/regroup.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index 279dc6a4f..f703aed42 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -76,10 +76,7 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const groupsWithData = validatedGroups.map(groupKey => lookupGroupKey(input, groupKey) ); - acc = { - ...acc, - ...appendGroup(input, acc, groupsWithData), - }; + acc = appendGroup(input, acc, groupsWithData); } return acc.children; From bf664a6ad738d28731adf42596e80c7904e2a667 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Tue, 20 Aug 2024 11:23:43 +0100 Subject: [PATCH 669/863] feat(lib): apply regroup to outputs not just inputs only when appending - otherwise outputs are lost if not already grouped. Signed-off-by: James Crowley --- src/__tests__/if-run/lib/compute.test.ts | 82 ++++++++++++++++++++---- src/__tests__/if-run/lib/regroup.test.ts | 78 ++++++++++++++++++++-- src/if-run/lib/compute.ts | 18 ++++-- src/if-run/lib/regroup.ts | 32 ++++++--- 4 files changed, 181 insertions(+), 29 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index ba631b990..a7e2b2cd2 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -94,6 +94,7 @@ describe('lib/compute: ', () => { .set('mock-observe-time-sync', mockObservePluginTimeSync()) .set('time-sync', mockTimeSync()), }; + const paramsExecuteWithAppend = {...paramsExecute, append: true}; describe('compute(): ', () => { it('computes simple tree with execute plugin.', async () => { @@ -117,7 +118,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with regroup.', async () => { + it('computes simple tree with regroup on inputs only (no compute).', async () => { const tree = { children: { mockChild: { @@ -146,7 +147,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.children).toEqual(expectedResponse); }); - it('computes tree with regroup and compute.', async () => { + it('computes simple tree with regroup, grouping inputs and outputs.', async () => { const tree = { children: { mockChild: { @@ -304,31 +305,30 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with append and execute plugin.', async () => { + it('computes simple tree with append, preserving existing outputs.', async () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, + {timestamp: 'mock-timestamp-1', region: 'eu-west'}, + {timestamp: 'mock-timestamp-2', region: 'eu-west'}, ], outputs: [ { - timestamp: 'mock-timestamp-1', + timestamp: 'mock-timestamp-preexisting-1', newField: 'mock-newField', - duration: 10, + region: 'eu-west', }, { - timestamp: 'mock-timestamp-2', + timestamp: 'mock-timestamp-preexisting-2', newField: 'mock-newField', - duration: 10, + region: 'eu-west', }, ], }, }, }; - const paramsExecuteWithAppend = {...paramsExecute, append: true}; const response = await compute(tree, paramsExecuteWithAppend); const expectedResult = [ ...tree.children.mockChild.outputs, @@ -339,6 +339,66 @@ describe('lib/compute: ', () => { }); }); + it('computes simple tree with regroup and append, with existing outputs preserved and regrouped without re-computing.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [{timestamp: 'mock-timestamp-1', region: 'uk-east'}], + outputs: [ + {timestamp: 'mock-timestamp-preexisting-1', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecuteWithAppend); + const expectedResponse = { + 'uk-east': { + inputs: [{region: 'uk-east', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-preexisting-1', + }, + { + region: 'uk-east', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + + it('computes simple tree with regroup and no append, with existing outputs that are removed.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [{timestamp: 'mock-timestamp-1', region: 'uk-east'}], + outputs: [ + {timestamp: 'mock-timestamp-preexisting-1', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResponse = { + 'uk-east': { + inputs: [{region: 'uk-east', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + it('computes simple tree with observe plugin.', async () => { const tree = { children: { diff --git a/src/__tests__/if-run/lib/regroup.test.ts b/src/__tests__/if-run/lib/regroup.test.ts index 67ff72e53..b4ba074c6 100644 --- a/src/__tests__/if-run/lib/regroup.test.ts +++ b/src/__tests__/if-run/lib/regroup.test.ts @@ -54,7 +54,75 @@ describe('lib/regroup: ', () => { }, }; - const result = Regroup(inputs, groups); + const result = Regroup(inputs, [], groups); + expect(result).toEqual(expectedOutput); + }); + + it('groups inputs combined with outputs correctly.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-east1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-east1', + }, + ]; + const outputs = [ + { + timestamp: '2022-06-06T00:00', + region: 'uk-west', + }, + { + timestamp: '2022-06-06T05:00', + region: 'uk-east2', + }, + ]; + const groups = ['region']; + + const expectedOutput = { + 'uk-west': { + inputs: [ + { + region: 'uk-west', + timestamp: '2023-07-06T00:00', + }, + ], + outputs: [ + { + timestamp: '2022-06-06T00:00', + region: 'uk-west', + }, + ], + }, + 'uk-east1': { + inputs: [ + { + timestamp: '2023-07-06T05:00', + region: 'uk-east1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-east1', + }, + ], + }, + 'uk-east2': { + outputs: [ + { + timestamp: '2022-06-06T05:00', + region: 'uk-east2', + }, + ], + }, + }; + + const result = Regroup(inputs, outputs, groups); expect(result).toEqual(expectedOutput); }); @@ -81,7 +149,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups!); + Regroup(inputs, [], groups!); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( @@ -113,7 +181,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( @@ -130,7 +198,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( @@ -149,7 +217,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 07c5cc27d..402da887b 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -90,7 +90,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } - const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -120,7 +119,14 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { * If regroup is requested, execute regroup strategy, delete child's inputs, outputs and empty regroup array. */ if ((noFlags || params.regroup) && pipelineCopy.regroup) { - node.children = Regroup(inputStorage, pipelineCopy.regroup); + const originalOutputs = params.append ? node.outputs || [] : []; + + node.children = Regroup( + inputStorage, + originalOutputs, + pipelineCopy.regroup + ); + delete node.inputs; delete node.outputs; @@ -139,6 +145,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. */ if ((noFlags || params.compute) && pipelineCopy.compute) { + const originalOutputs = params.append ? node.outputs || [] : []; while (pipelineCopy.compute.length !== 0) { const pluginName = pipelineCopy.compute.shift() as string; const plugin = params.pluginStorage.get(pluginName); @@ -158,9 +165,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { debugLogger.setExecutingPluginName(); } } - } - if (params.append) { - node.outputs = originalOutputs.concat(node.outputs || []); + + if (params.append) { + node.outputs = originalOutputs.concat(node.outputs || []); + } } }; diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index f703aed42..7e39b1c89 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -13,11 +13,20 @@ const {INVALID_GROUP_KEY, REGROUP_ERROR} = STRINGS; /** * Grouping strategy. */ -export const Regroup = (inputs: PluginParams[], groups: string[]) => { +export const Regroup = ( + inputs: PluginParams[], + outputs: PluginParams[], + groups: string[] +) => { /** * Creates structure to insert inputs by groups. */ - const appendGroup = (value: PluginParams, object: any, groups: string[]) => { + const appendGroup = ( + value: PluginParams, + object: any, + target: string, + groups: string[] + ) => { if (groups.length > 0) { const group = groups.shift() as string; @@ -26,16 +35,16 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { if (groups.length === 0) { if ( - object.children[group].inputs && - object.children[group].inputs.length > 0 + object.children[group][target] && + object.children[group][target].length > 0 ) { - object.children[group].inputs.push(value); + object.children[group][target].push(value); } else { - object.children[group].inputs = [value]; + object.children[group][target] = [value]; } } - appendGroup(value, object.children[group], groups); + appendGroup(value, object.children[group], target, groups); } return object; @@ -76,7 +85,14 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const groupsWithData = validatedGroups.map(groupKey => lookupGroupKey(input, groupKey) ); - acc = appendGroup(input, acc, groupsWithData); + acc = appendGroup(input, acc, 'inputs', groupsWithData); + } + + for (const output of outputs) { + const groupsWithData = validatedGroups.map(groupKey => + lookupGroupKey(output, groupKey) + ); + acc = appendGroup(output, acc, 'outputs', groupsWithData); } return acc.children; From 24b585db3a0afec29a74b02c2499dc36aae0076a Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 21 Aug 2024 18:01:55 +0400 Subject: [PATCH 670/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c11cceb0d..663d3b063 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.17", + "@grnsft/if-core": "^0.0.18", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.17.tgz", - "integrity": "sha512-t94QvQgP4qomJoSqPUy70Th271/3b3E8+FfmW0Fv00je5Lb5OVAzF1FAD1GdP1UkoXJkbklO99d6hbTMCZSHlw==", + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.18.tgz", + "integrity": "sha512-fZVGADUFf+9CQm+upGwGbQ5zlj7mndxZJ/Bfx2V/8+diU//xvK2vACC/7a1M0pHHhP8tKbfgdGopwWUI3POzcw==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 8a86b90ee..63ab8bf07 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.17", + "@grnsft/if-core": "^0.0.18", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From f5d7043b423dfc091e5c4d3cc52a6dc6c3bbe226 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 21 Aug 2024 18:02:53 +0400 Subject: [PATCH 671/863] feat(util): remove mapping functions --- src/common/util/helpers.ts | 68 -------------------------------------- 1 file changed, 68 deletions(-) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index 3a1f623ef..01b87c79d 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -2,7 +2,6 @@ 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`. @@ -64,70 +63,3 @@ export const parseManifestFromStdin = async () => { return match![1]; }; - -/** - * Maps input data if the mapping has valid data. - */ -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) ? [] : {}; - - Object.entries(config).forEach(([key, value]) => { - const mappedKey = mapping[key] || key; - - if (typeof value === 'object' && value !== null) { - result[mappedKey] = mapConfigIfNeeded(value, mapping); - } else { - result[mappedKey] = - typeof value === 'string' && value in mapping ? mapping[value] : value; - } - }); - - return result; -}; - -/** - * Maps the output parameter of the plugin if the `mapping` parameter is provided. - */ -export const mapOutputIfNeeded = ( - 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 a781b0f97ca2188fbaecea28a91399d1fb2750d9 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 21 Aug 2024 18:04:05 +0400 Subject: [PATCH 672/863] test(util): remove mapping functions tests --- src/__tests__/common/util/helpers.test.ts | 155 +--------------------- 1 file changed, 1 insertion(+), 154 deletions(-) diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts index 387689371..11838100c 100644 --- a/src/__tests__/common/util/helpers.test.ts +++ b/src/__tests__/common/util/helpers.test.ts @@ -2,12 +2,7 @@ jest.mock('node:readline/promises', () => require('../../../__mocks__/readline') ); -import { - parseManifestFromStdin, - mapInputIfNeeded, - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; +import {parseManifestFromStdin} from '../../../common/util/helpers'; describe('common/util/helpers: ', () => { describe('parseManifestFromStdin(): ', () => { @@ -46,152 +41,4 @@ describe('common/util/helpers: ', () => { expect(response).toEqual(expectedMessage); }); }); - - 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 = {}; - - const result = mapInputIfNeeded(input, mapping); - - expect(result).toEqual(input); - }); - - 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: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'resources-reserved': 1, - 'resources-total': 1, - }; - - const result = mapInputIfNeeded(input, mapping); - - expect(result).toEqual(expectedOutput); - expect(result).not.toHaveProperty('device/carbon-footprint'); - }); - }); - - 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 = { - 'cpu/utilized': 'cpu/util', - }; - - const expected = { - filepath: './file.csv', - query: { - 'cpu-cores-available': 'cpu/available', - 'cpu-cores-utilized': 'cpu/util', - 'cpu-manufacturer': 'cpu/manufacturer', - }, - output: ['cpu-tdp', 'tdp'], - }; - expect(mapConfigIfNeeded(config, mapping)).toEqual(expected); - }); - - it('returns an empty object or array when config is an empty object or array.', () => { - expect(mapConfigIfNeeded({}, {})).toEqual({}); - expect(mapConfigIfNeeded([], {})).toEqual([]); - }); - }); - - describe('mapOutputIfNeeded(): ', () => { - 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 = mapOutputIfNeeded(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 = mapOutputIfNeeded(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 = mapOutputIfNeeded(output, mapping); - - expect.assertions(1); - expect(mappedOutput).toEqual(expectedOutput); - }); - }); }); From d9087674bc76e6ef882d297c446ac9f35e87df28 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 21 Aug 2024 18:08:16 +0400 Subject: [PATCH 673/863] feat(builtins): update mapping functions path --- 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 ++++---- src/if-run/builtins/mock-observations/index.ts | 10 +++++----- src/if-run/builtins/multiply/index.ts | 10 +++++----- src/if-run/builtins/regex/index.ts | 8 ++++---- src/if-run/builtins/sci-embodied/index.ts | 8 ++++---- src/if-run/builtins/sci/index.ts | 8 ++++---- src/if-run/builtins/shell/index.ts | 2 +- src/if-run/builtins/subtract/index.ts | 10 +++++----- src/if-run/builtins/sum/index.ts | 8 ++++---- src/if-run/builtins/time-converter/index.ts | 8 ++++---- src/if-run/builtins/time-sync/index.ts | 8 ++++---- 16 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 289b4d7be..0a002f67a 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { CoefficientConfig, ExecutePlugin, @@ -9,10 +13,6 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 2128cff7d..fec1fd850 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ConfigParams, ExecutePlugin, @@ -11,10 +15,6 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; const {MISSING_CONFIG} = STRINGS; const {ConfigError} = ERRORS; diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 373cbdeb0..f66981b97 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -5,6 +5,10 @@ import axios from 'axios'; import {z} from 'zod'; import {parse} from 'csv-parse/sync'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, MappingParams, @@ -15,10 +19,6 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; const { FILE_FETCH_FAILED, diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index ba02194bb..767fd1d6d 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -11,10 +15,6 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; const {ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 38bc07d49..199f44b17 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -1,4 +1,8 @@ import {z} from 'zod'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -9,10 +13,6 @@ import { import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 1bd1cf48b..c7c9887f7 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -1,6 +1,10 @@ import Spline from 'typescript-cubic-spline'; import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -11,10 +15,6 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index 7b1dfee89..1aa72d303 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -1,5 +1,10 @@ import {DateTime, Duration} from 'luxon'; import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -8,13 +13,8 @@ import { PluginParametersMetadata, MappingParams, } from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index e33ee1f15..530cb77a1 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -1,4 +1,9 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -6,13 +11,8 @@ import { PluginParametersMetadata, MappingParams, } from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 9f017e8e8..5e65e677f 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -9,10 +13,6 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 1aad045a5..c6c953b50 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,4 +1,8 @@ import {z} from 'zod'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, ParameterMetadata, @@ -10,10 +14,6 @@ import { import {validate, allDefined} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import { - mapInputIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; const {SCI_EMBODIED_ERROR} = STRINGS; diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index dbafa6352..407621b86 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -10,10 +14,6 @@ import { } from '@grnsft/if-core/types'; import {validate, allDefined} from '../../../common/util/validations'; -import { - mapInputIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 8926a266e..ddf8b619d 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -3,6 +3,7 @@ import {spawnSync, SpawnSyncReturns} from 'child_process'; import {loadAll, dump} from 'js-yaml'; import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import {mapOutputIfNeeded} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -12,7 +13,6 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {mapOutputIfNeeded} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index d4dc1181a..5051017c5 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -1,4 +1,9 @@ import {z} from 'zod'; +import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, MappingParams, @@ -6,13 +11,8 @@ import { PluginParams, SubtractConfig, } from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index eb0e519a5..580821ddb 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -9,10 +13,6 @@ import { } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; import {STRINGS} from '../../config'; diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index e757ed967..c4b9ef577 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -1,5 +1,9 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapConfigIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -13,10 +17,6 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {TIME_UNITS_IN_SECONDS} from './config'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 5d909bf77..f72cae045 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -3,6 +3,10 @@ import {isDate} from 'node:util/types'; import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; +import { + mapInputIfNeeded, + mapOutputIfNeeded, +} from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, PluginParams, @@ -18,10 +22,6 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {getAggregationMethod} from '../../lib/aggregate'; -import { - mapInputIfNeeded, - mapOutputIfNeeded, -} from '../../../common/util/helpers'; Settings.defaultZone = 'utc'; From cc5c09368779842f8739e1de9a1c21a4cf304bc0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:27:42 +0400 Subject: [PATCH 674/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 663d3b063..ca145548d 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.18", + "@grnsft/if-core": "^0.0.20", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.18.tgz", - "integrity": "sha512-fZVGADUFf+9CQm+upGwGbQ5zlj7mndxZJ/Bfx2V/8+diU//xvK2vACC/7a1M0pHHhP8tKbfgdGopwWUI3POzcw==", + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.20.tgz", + "integrity": "sha512-D5P97E0O9qIw9Ok0qCcy3zmNl8j1sr/vwfPsueFzkbmF6ZnLDBL1vapn8MzSRFsp3lJoH/mStDZ3uf3+S1L17g==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 63ab8bf07..802c9f138 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.18", + "@grnsft/if-core": "^0.0.20", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -86,7 +86,6 @@ "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", - "prepublish": "npm run build", "release": "release-it", "test": "jest --verbose --testPathPattern=src/__tests__/" }, From 8b7014c9a8ba2b524b18d49afb286209f2cc428a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:57:27 +0400 Subject: [PATCH 675/863] feat(types): use aggregation from if core --- src/if-run/types/aggregation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts index c3b143a1f..5315b298f 100644 --- a/src/if-run/types/aggregation.ts +++ b/src/if-run/types/aggregation.ts @@ -1,7 +1,7 @@ +import {AggregationMethodTypes} from '@grnsft/if-core/types'; + export type AggregationResult = Record; export const AGGREGATION_TYPES = ['horizontal', 'vertical', 'both'] as const; -export const AGGREGATION_METHODS = ['sum', 'avg', 'none'] as const; -export type AggregationMethodTypes = 'sum' | 'avg' | 'none'; export type AggregationMetric = Record; From 7031c76a3615ce90dd277b27c9ba01142bf5321a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:58:03 +0400 Subject: [PATCH 676/863] feat(util): introduce copy and none methods to aggregation helper --- src/if-run/util/aggregation-helper.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index e8fe63de5..4629d9bc4 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -12,8 +12,8 @@ const {METRIC_MISSING} = STRINGS; const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; /** - * Aggregates child node level metrics. Validates if metric aggregation type is `none`, then rejects with error. - * Appends aggregation additional params to metrics. Otherwise iterates over inputs by aggregating per given `metrics`. + * Aggregates child node level metrics. Appends aggregation additional params to metrics. + * Otherwise iterates over inputs by aggregating per given `metrics`. */ export const aggregateInputsIntoOne = ( inputs: PluginParams[], @@ -23,6 +23,8 @@ export const aggregateInputsIntoOne = ( const metricsKeys: string[] = metrics.map(metric => Object.keys(metric)[0]); const extendedMetrics = [...metricsKeys, ...AGGREGATION_ADDITIONAL_PARAMS]; + console.log(extendedMetrics); + return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { if (!(metric in input)) { @@ -37,7 +39,12 @@ export const aggregateInputsIntoOne = ( } else { const method = getAggregationMethod(metric); - if (!method) { + if (method === 'none') { + return acc; + } + + if (method === 'copy') { + acc[metric] = input[metric]; return acc; } From d04de7e5a32128d4c7aab757dcbeadff0d79c88f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:58:20 +0400 Subject: [PATCH 677/863] feat(lib): return none aggregation method --- src/if-run/lib/aggregate.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index cd19b00e9..43b84fcf6 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -1,3 +1,4 @@ +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {PluginParams} from '@grnsft/if-core/types'; import {debugLogger} from '../../common/util/debug-logger'; @@ -158,5 +159,5 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - return undefined; + return AGGREGATION_METHODS[2]; }; From f742a0ba1b124f9195d7d50c2bf5ee348a030853 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:58:43 +0400 Subject: [PATCH 678/863] revert(config): drop sci embodied message from strings --- src/if-run/config/strings.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 82208f621..e549c3b72 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -97,8 +97,6 @@ https://if.greensoftware.foundation/major-concepts/manifest-file`, '`functional-unit` value is missing from input data or it is not a positive integer', REGEX_MISMATCH: (input: any, match: string) => `\`${input}\` does not match the ${match} regex expression`, - SCI_EMBODIED_ERROR: (unit: string) => - `invalid number. please provide it as \`${unit}\` to input`, MISSING_MIN_MAX: 'Config is missing min or max value', INVALID_MIN_MAX: (name: string) => `Min value should not be greater than or equal to max value of ${name}`, From 71863653570b5981d725f2856673269ca34e74a2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:59:06 +0400 Subject: [PATCH 679/863] feat(builtins): introduce none and copy aggregation methods --- src/if-run/builtins/time-sync/index.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index f72cae045..d85f08c32 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -265,6 +265,12 @@ export const TimeSync = ( return acc; } + if (method === 'none') { + acc[key] = null; + + return acc; + } + acc[key] = method === 'sum' ? convertPerInterval(input[key], input['duration']) @@ -310,13 +316,22 @@ export const TimeSync = ( const method = getAggregationMethod(metric); + if (method === 'none') { + acc[metric] = null; + + return acc; + } + if (method === 'avg' || method === 'sum') { acc[metric] = 0; return acc; } - acc[metric] = input[metric]; + if (method === 'copy') { + acc[metric] = input[metric]; + return acc; + } return acc; }, {} as PluginParams); @@ -379,7 +394,8 @@ export const TimeSync = ( method = 'sum'; } - if (!method) { + if (method === 'none') { + acc[metric] = null; return; } @@ -391,7 +407,7 @@ export const TimeSync = ( return; } - if (method === 'none') { + if (method === 'copy') { acc[metric] = input[metric]; return; From 115c81353b995fc1df7e3ad0f7fca7ce4d12e94a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:59:28 +0400 Subject: [PATCH 680/863] doc(builtins): introduce documentation for sci embodied --- src/if-run/builtins/sci-embodied/README.md | 126 ++++++++------------- 1 file changed, 45 insertions(+), 81 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 8933de211..c80462db8 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -2,28 +2,27 @@ Software systems cause emissions through the hardware that they operate on, both through the energy that the physical hardware consumes and the emissions associated with manufacturing the hardware. Embodied carbon refers to the carbon emitted during the manufacture and eventual disposal of a component. It is added to the operational carbon (carbon emitted when a component is used) to give an overall SCI score. -Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions) +Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions). ## Parameters -### Plugin config +### Plugin Configuration -Not Needed +The `SciEmbodied` plugin requires a configuration object and parameter metadata (optional) to do the calculation. -### Plugin parameter metadata +### Plugin Parameter Metadata -The `parameter-metadata` section contains information about `description`, `unit` and `aggregation-method` of the parameters of the inputs and outputs +The `parameter-metadata` section contains information about the `description`, `unit`, and `aggregation-method` of the input and output parameters. -- `inputs`: describe the parameters of the `inputs`. Each parameter has: +- `inputs`: Describes the parameters for the input data. Each parameter includes: + - `description`: A brief description of the parameter. + - `unit`: The unit of measurement for the parameter. + - `aggregation-method`: The method used to aggregate this parameter (`sum`, `avg`, or `none`). - - `description`: description of the parameter - - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - -- `outputs`: describe the `carbon-embodied` parameter. The parameter has the following attributes: - - `description`: description of the parameter - - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) +- `outputs`: Describes the `carbon-embodied` parameter, which includes: + - `description`: A brief description of the parameter. + - `unit`: The unit of measurement for the parameter. + - `aggregation-method`: The method used to aggregate this parameter (`sum`, `avg`, or `none`). ### Mapping @@ -39,73 +38,57 @@ sci-embodied: ### Inputs -- `device/emissions-embodied`: the sum of Life Cycle Assessment (LCA) emissions for the component -- `device/expected-lifespan`: the length of time, in seconds, between a component's manufacture and its disposal -- `resources-reserved`: the number of resources reserved for use by the software -- `resources-total`: the total number of resources available -- `duration`: the amount of time covered by an observation, in this context it is used as the share of the total life span of the hardware reserved for use by an application, in seconds. - -> Note that if you have a plugin pipeline that adds `vcpus-allocated` and `vcpus-total` to each observation, such as the `cloud-metadata` plugin, those values will be used **in preference** to the given `resources-reserved` and `resources-total` fields. +- `device/emissions-embodied`: The total embodied emissions for the component, measured in gCO2e. +- `device/expected-lifespan`: The expected lifespan of the component, in seconds. +- `resources-reserved`: The number of resources reserved for use by the software. +- `resources-total`: The total number of resources available. +- `vcpus-allocated`: The number of virtual CPUs allocated to a particular resource. +- `vcpus-total`: The total number of virtual CPUs available on a particular resource. +- `duration`: The length of time the hardware is reserved for use by the software, in seconds. -## Returns +### Outputs -- `carbon-embodied`: the carbon emitted in manufacturing and disposing of a component, in gCO2eq +- `carbon-embodied`: The total embodied emissions for the component, measured in gCO2e. ## Calculation -To calculate the embodied carbon, `m` for a software application, use the equation: - -``` -m = te * ts * rs -``` - -Where: - -- `device/emissions-embodied` = Total embodied emissions; the sum of Life Cycle Assessment (LCA) emissions for the component. - -- `timeShare` = Time-share; the share of the total life span of the hardware reserved for use by an application. +The plugin calculates the total embodied carbon emissions using the following steps: - - `timeShare` is calculated as `duration/'device/expected-lifespan'`, where: - - `duration` = the length of time the hardware is reserved for use by the software. - - `device/expected-lifespan` = Expected lifespan: the length of time, in seconds, between a component's manufacture and its disposal. - -- `resourceShare` = Resource-share; the share of the total available resources of the hardware reserved for use by an application. - - `resourceShare` is calculated as `resources-reserved/resources-total`, where: - - `resources-reserved` = Resources reserved; the number of resources reserved for use by the software. - - `resources-total` = Total Resources; the total number of resources available. + - CPU emissions (`cpuE`) are calculated based on the difference between allocated vCPUs and baseline vCPUs. + - Memory emissions (`memoryE`) are calculated based on the difference between allocated memory and baseline memory. + - Emissions for HDD, SSD, and GPU are also calculated based on their respective differences from baseline values. + - The total embodied emissions are calculated by summing the baseline emissions with the above components and adjusting for the lifespan and time duration. ## Implementation -IF implements the plugin based on the logic described above. To run the plugin, you must first create an instance of `SciEmbodied`. Then, you can call `execute()` to return `m`. - -## Usage - -The following snippet demonstrates how to call the `sci-embodied` plugin from Typescript. +The plugin can be instantiated and executed as follows: ```typescript import {SciEmbodied} from 'builtins'; -const parametersMetadata = {inputs: {}, outputs: {}}; -const mapping = {}; -const sciEmbodied = SciEmbodied(undefined, parametersMetadata, mapping); +const sciEmbodied = SciEmbodied(config, parametersMetadata, {}); const results = await sciEmbodied.execute([ { - 'device/emissions-embodied': 200, // in gCO2e for total resource units - duration: 60 * 60 * 24 * 30, // time reserved in seconds, can point to another field "duration" - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, // lifespan in seconds (4 years) - 'resources-reserved': 1, // resource units reserved / used - 'resources-total': 1, // total resource units available + duration: 3600, // time reserved in seconds + vCPUs: 2, // allocated vCPUs + memory: 32, // allocated memory in GB + ssd: 100, // allocated SSD storage in GB + hdd: 1000, // allocated HDD storage in GB + gpu: 1, // allocated GPUs + 'total-vcpus': 8, // total available vCPUs }, ]); + +console.log(results); ``` -## Example manifest +# 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 `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 -description: simple demo invoking sci-embodied +description: demo invoking sci-embodied tags: initialize: plugins: @@ -119,34 +102,15 @@ tree: child: pipeline: compute: - - sci-embodied # duration & config -> embodied - defaults: - device/carbon-footprint: 1533.120 # gCO2eq - device/expected-lifespan: 3 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 + - sci-embodied inputs: - - timestamp: 2023-07-06T00:00 + - timestamp: 2024-08-19T00:00 duration: 3600 ``` -You can run this example `manifest` by executing the following command from the project root: +To run this example manifest, use the following command: -```sh +```bash npm i -g @grnsft/if -if-run --manifest manifests/plugins/sci-embodied.yml --output manifests/outputs/sci-embodied.yml +if-run --manifest manifests/plugins/sci-embodied/success.yml --output manifests/outputs/success.yml ``` - -The results will be saved to a new `yaml` file in `./examples/outputs`. - -## Errors - -`SciEmbodied` uses one of IF's error classes - -### `SciEmbodiedError` - -This error class is used to describe a problem with one of the input values to `sci-embodied`. This is typically due to an incorrect type or a reference to a value that is not available. - -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) From 3697ae30fba983787539467002df3a153245dec8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 18:59:49 +0400 Subject: [PATCH 681/863] feat(builtins): implement upgraded version of sci embodied --- src/if-run/builtins/sci-embodied/index.ts | 234 ++++++++++------------ 1 file changed, 104 insertions(+), 130 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index c6c953b50..a8f511066 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,24 +1,23 @@ -import {z} from 'zod'; +import {z, ZodType} from 'zod'; + import { + mapConfigIfNeeded, mapInputIfNeeded, mapOutputIfNeeded, } from '@grnsft/if-core/utils/helpers'; import { ExecutePlugin, + ConfigParams, ParameterMetadata, MappingParams, PluginParametersMetadata, PluginParams, } from '@grnsft/if-core/types'; -import {validate, allDefined} from '../../../common/util/validations'; - -import {STRINGS} from '../../config'; - -const {SCI_EMBODIED_ERROR} = STRINGS; +import {validate} from '../../../common/util/validations'; export const SciEmbodied = ( - _config: undefined, + config: ConfigParams = {}, parametersMetadata: PluginParametersMetadata, mapping: MappingParams ): ExecutePlugin => { @@ -26,165 +25,140 @@ export const SciEmbodied = ( kind: 'execute', inputs: { ...({ - 'device/emissions-embodied': { - description: 'total embodied emissions of some component', - unit: 'gCO2e', - 'aggregation-method': 'sum', + vCPUs: { + description: 'number of CPUs allocated to an application', + unit: 'CPUs', + 'aggregation-method': 'copy', }, - 'device/expected-lifespan': { - description: 'Total Expected Lifespan of the Component in Seconds', - unit: 'seconds', - 'aggregation-method': 'sum', + memory: { + description: 'RAM available for a resource, in GB', + unit: 'GB', + 'aggregation-method': 'copy', }, - 'resources-reserved': { - description: 'resources reserved for an application', - unit: 'count', - 'aggregation-method': 'none', + ssd: { + description: 'number of SSDs available for a resource', + unit: 'SSDs', + 'aggregation-method': 'copy', }, - 'resources-total': { - description: 'total resources available', - unit: 'count', - 'aggregation-method': 'none', + hdd: { + description: 'number of HDDs available for a resource', + unit: 'HDDs', + 'aggregation-method': 'copy', }, - 'vcpus-allocated': { - description: 'number of vcpus allocated to particular resource', - unit: 'count', - 'aggregation-method': 'none', + gpu: { + description: 'number of GPUs available for a resource', + unit: 'GPUs', + 'aggregation-method': 'copy', }, - 'vcpus-total': { - description: - 'total number of vcpus available on a particular resource', - unit: 'count', - 'aggregation-method': 'none', + 'total-vcpus': { + description: 'total number of CPUs or vCPUs available for a resource', + unit: 'CPUs', + 'aggregation-method': 'copy', }, } as ParameterMetadata), ...parametersMetadata?.inputs, }, outputs: parametersMetadata?.outputs || { - 'carbon-embodied': { - description: 'embodied emissions of the component', + 'embodied-carbon': { + description: 'embodied carbon for a resource, scaled by usage', unit: 'gCO2e', 'aggregation-method': 'sum', }, }, }; - const METRICS = [ - 'device/emissions-embodied', - 'device/expected-lifespan', - 'resources-reserved', - 'vcpus-allocated', - 'resources-total', - 'vcpus-total', - ]; - /** - * Calculate the Embodied carbon for a list of inputs. + * Checks for required fields in input. */ - const execute = (inputs: PluginParams[]) => - inputs.map(input => { - const mappedInput = mapInputIfNeeded(input, mapping); - const safeInput = validateInput(mappedInput); - - const result = { - ...input, - 'carbon-embodied': calculateEmbodiedCarbon(safeInput), - }; - - return mapOutputIfNeeded(result, mapping); + const validateConfig = () => { + const schema = z.object({ + 'baseline-vcpus': z.number().gte(0).default(1), + 'baseline-memory': z.number().gte(0).default(16), + 'baseline-emissions': z.number().gte(0).default(1000000), + lifespan: z.number().gt(0).default(126144000), + time: z.number().gt(0).optional(), + 'vcpu-emissions-constant': z.number().gte(0).default(100000), + 'memory-emissions-constant': z + .number() + .gte(0) + .default(533 / 384), + 'ssd-emissions-constant': z.number().gte(0).default(50000), + 'hdd-emissions-constant': z.number().gte(0).default(100000), + 'gpu-emissions-constant': z.number().gte(0).default(150000), + 'output-parameter': z.string().optional(), }); - /** - * Calculate the Embodied carbon for the input. - * M = totalEmissions * (duration/ExpectedLifespan) * (resourcesReserved/totalResources) - */ - const calculateEmbodiedCarbon = (input: PluginParams) => { - const totalEmissions = input['device/emissions-embodied']; - const duration = input['duration']; - const expectedLifespan = input['device/expected-lifespan']; - const resourcesReserved = - input['vcpus-allocated'] || input['resources-reserved']; - const totalResources = input['vcpus-total'] || input['resources-total']; + const mappedConfig = mapConfigIfNeeded(config, mapping); - return ( - totalEmissions * - (duration / expectedLifespan) * - (resourcesReserved / totalResources) + return validate>( + schema as ZodType, + mappedConfig ); }; /** - * Checks for required fields in input. + * Validates single observation for safe calculation. */ const validateInput = (input: PluginParams) => { - const commonSchemaPart = (errorMessage: (unit: string) => string) => ({ - 'device/emissions-embodied': z - .number({ - invalid_type_error: errorMessage('gCO2e'), - }) - .gte(0) - .min(0), - 'device/expected-lifespan': z - .number({ - invalid_type_error: errorMessage('gCO2e'), - }) - .gte(0) - .min(0), - duration: z - .number({ - invalid_type_error: errorMessage('seconds'), - }) - .gte(1), + const schema = z.object({ + duration: z.number().gt(0), + vCPUs: z.number().gt(0).default(1), + memory: z.number().gt(0).default(16), + ssd: z.number().gte(0).default(0), + hdd: z.number().gte(0).default(0), + gpu: z.number().gte(0).default(0), + 'total-vcpus': z.number().gte(0).default(8), }); - const vcpusSchemaPart = { - 'vcpus-allocated': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - 'vcpus-total': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - }; + return validate>(schema as ZodType, input); + }; - const resourcesSchemaPart = { - 'resources-reserved': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - 'resources-total': z - .number({ - invalid_type_error: SCI_EMBODIED_ERROR('count'), - }) - .gte(0) - .min(0), - }; + /** + * 1. Validates configuration and assigns defaults values if not provided. + * 2. Maps through observations and validates them. + * 3. Calculates total embodied carbon by substracting and the difference between baseline server and given one. + */ + const execute = (inputs: PluginParams[]) => { + const safeConfig = validateConfig(); - const schemaWithVcpus = z.object({ - ...commonSchemaPart(SCI_EMBODIED_ERROR), - ...vcpusSchemaPart, - }); - const schemaWithResources = z.object({ - ...commonSchemaPart(SCI_EMBODIED_ERROR), - ...resourcesSchemaPart, - }); + return inputs.map(input => { + const mappedInput = mapInputIfNeeded(input, mapping); + const safeInput = validateInput(mappedInput); - const schema = schemaWithVcpus.or(schemaWithResources).refine(allDefined, { - message: `All ${METRICS} should be present.`, - }); + const cpuE = + (safeInput.vCPUs - safeConfig['baseline-vcpus']) * + safeConfig['vcpu-emissions-constant']; + const memoryE = + (safeInput.memory - safeConfig['baseline-memory']) * + safeConfig['memory-emissions-constant']; + const hddE = safeInput.hdd - safeConfig['hdd-emissions-constant']; + const gpuE = safeInput.gpu - safeConfig['gpu-emissions-constant']; + const ssdE = safeInput.ssd - safeConfig['ssd-emissions-constant']; + const time = safeConfig['time'] || safeInput.duration; + + const totalEmbodied = + (safeConfig['baseline-emissions'] + + cpuE + + memoryE + + ssdE + + hddE + + gpuE) * + (safeInput.vCPUs / safeInput['total-vcpus']) * + (time / safeConfig['lifespan']); + + const embodiedCarbonKey = + safeConfig['output-parameter'] || 'embodied-carbon'; + const result = { + ...input, + [embodiedCarbonKey]: totalEmbodied, + }; - return validate>(schema, input); + return mapOutputIfNeeded(result, mapping); + }); }; return { - metadata, execute, + metadata, }; }; From 06d4045b37eeb3ab932f920b0f089039192ee5de Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:00:15 +0400 Subject: [PATCH 682/863] feat(src): use aggregation methods from if core --- src/if-run/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 6d9f61a78..5607df6b6 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -1,4 +1,6 @@ #!/usr/bin/env node +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; + import {STRINGS as COMMON_STRINGS} from '../common/config'; import {validateManifest} from '../common/util/validations'; import {debugLogger} from '../common/util/debug-logger'; @@ -12,8 +14,6 @@ import {compute} from './lib/compute'; import {exhaust} from './lib/exhaust'; import {explain} from './lib/explain'; -import {AGGREGATION_METHODS} from './types/aggregation'; - import {parseIfRunProcessArgs} from './util/args'; import {andHandle} from './util/helpers'; From 5dd9f00b1f664c8e1babb0e91f3379def53da91c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:00:30 +0400 Subject: [PATCH 683/863] fix(util): fix console log issue in debug logger --- src/common/util/debug-logger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts index 1a9a614d9..488903c96 100644 --- a/src/common/util/debug-logger.ts +++ b/src/common/util/debug-logger.ts @@ -99,7 +99,7 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { return; } - if (args[0].includes('# start')) { + if (typeof args[0] === 'string' && args[0].includes('# start')) { originalConsole.log(...args); return; } From 5cd992bc7589bb0015995bd16b7b2dc4dcde139d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:00:44 +0400 Subject: [PATCH 684/863] feat(types): use aggregation methods from if core --- src/common/types/manifest.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 1efab523d..488d8eeb5 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -1,6 +1,5 @@ import {z} from 'zod'; - -import {AggregationMethodTypes} from '../../if-run/types/aggregation'; +import {AggregationMethodTypes} from '@grnsft/if-core/types'; import {manifestSchema} from '../util/validations'; From 6a31dbffd8dabd5b70e61452df82d7490ff2c818 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:01:08 +0400 Subject: [PATCH 685/863] test(util): update aggregation usage in aggregation helper --- src/__tests__/if-run/util/aggregation-helper.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index f83536f39..d76fcbb94 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -1,13 +1,11 @@ +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {ERRORS} from '@grnsft/if-core/utils'; import {PluginParams} from '@grnsft/if-core/types'; import {AggregationParams} from '../../../common/types/manifest'; import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; -import { - AGGREGATION_METHODS, - AggregationMetric, -} from '../../../if-run/types/aggregation'; +import {AggregationMetric} from '../../../if-run/types/aggregation'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -25,6 +23,7 @@ describe('util/aggregation-helper: ', () => { [metric]: AGGREGATION_METHODS[2], })); storeAggregationMetrics(...convertedMetrics); + storeAggregationMetrics({carbon: 'sum'}); }); describe('aggregateInputsIntoOne(): ', () => { @@ -47,6 +46,7 @@ describe('util/aggregation-helper: ', () => { }); it('passes `timestamp`, `duration` to aggregator if aggregation is temporal.', () => { + storeAggregationMetrics({carbon: 'sum'}); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, From c96a03de5a1b555d2c0509466b0585670323200c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:01:29 +0400 Subject: [PATCH 686/863] tesst(lib): remove skip from environment, fix typo --- src/__tests__/if-run/lib/environment.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/lib/environment.test.ts b/src/__tests__/if-run/lib/environment.test.ts index 63127fd5a..b7b6ab60b 100644 --- a/src/__tests__/if-run/lib/environment.test.ts +++ b/src/__tests__/if-run/lib/environment.test.ts @@ -2,7 +2,7 @@ import {injectEnvironment} from '../../../if-run/lib/environment'; -describe.skip('lib/envirnoment: ', () => { +describe('lib/environment: ', () => { describe('injectEnvironment(): ', () => { const context = {}; From f557eb787b4892fe299e176996960670da703cd2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:01:38 +0400 Subject: [PATCH 687/863] test(lib): update aggregation usage in aggregation --- src/__tests__/if-run/lib/aggregate.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index 00d9c6d0e..d053fea9f 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {AggregationParams} from '../../../common/types/manifest'; @@ -6,7 +7,6 @@ import { aggregate, storeAggregationMetrics, } from '../../../if-run/lib/aggregate'; -import {AGGREGATION_METHODS} from '../../../if-run/types/aggregation'; describe('lib/aggregate: ', () => { beforeAll(() => { @@ -22,6 +22,10 @@ describe('lib/aggregate: ', () => { }); describe('aggregate(): ', () => { + beforeAll(() => { + storeAggregationMetrics({carbon: 'sum'}); + }); + it('returns tree if aggregation is missing.', () => { const tree = {}; const aggregation = undefined; From 387801c93b8e3c5efa43b2588dab5d5129b49da5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:01:53 +0400 Subject: [PATCH 688/863] test(builtins): update time sync units --- src/__tests__/if-run/builtins/time-sync.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index b3350fbe0..0bfc59b5a 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -1,3 +1,4 @@ +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {ERRORS} from '@grnsft/if-core/utils'; import {Settings, DateTime} from 'luxon'; @@ -7,7 +8,6 @@ import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {TimeSync} from '../../../if-run/builtins/time-sync'; import {STRINGS} from '../../../if-run/config'; -import {AGGREGATION_METHODS} from '../../../if-run/types/aggregation'; Settings.defaultZone = 'utc'; const { @@ -463,10 +463,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 1, + 'cpu/utilization': null, }, { timestamp: '2023-12-12T00:00:01.000Z', duration: 1, + 'cpu/utilization': null, }, ]; @@ -576,10 +578,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, + 'resources-total': null, }, { timestamp: '2023-12-12T00:00:05.000Z', duration: 5, + 'resources-total': null, }, ]; @@ -739,12 +743,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, - 'resources-total': 10, + 'resources-total': null, }, { timestamp: '2023-12-12T00:00:05.000Z', duration: 5, - 'resources-total': 10, + 'resources-total': null, }, ]; From 2365c4cf972d1cf4875dd6d29578161504fa4df9 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:02:10 +0400 Subject: [PATCH 689/863] test(builtins): implement units for sci embodied --- .../if-run/builtins/sci-embodied.test.ts | 312 +++--------------- 1 file changed, 45 insertions(+), 267 deletions(-) diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 40670a821..a1865f4d5 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -2,10 +2,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {SciEmbodied} from '../../../if-run/builtins/sci-embodied'; -import {STRINGS} from '../../../if-run/config'; - const {InputValidationError} = ERRORS; -const {SCI_EMBODIED_ERROR} = STRINGS; describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { @@ -13,7 +10,7 @@ describe('builtins/sci-embodied:', () => { inputs: {}, outputs: {}, }; - const sciEmbodied = SciEmbodied(undefined, parametersMetadata, {}); + const sciEmbodied = SciEmbodied({}, parametersMetadata, {}); describe('init: ', () => { it('successfully initalized.', () => { @@ -27,19 +24,13 @@ describe('builtins/sci-embodied:', () => { 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, + duration: 3600, + vCPUs: 2, }, { 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, + duration: 3600, + vCPUs: 4, }, ]; @@ -50,46 +41,33 @@ describe('builtins/sci-embodied:', () => { expect(result).toStrictEqual([ { 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, - 'carbon-embodied': 4.10958904109589, + duration: 3600, + vCPUs: 2, + 'embodied-carbon': 5.707762557077626, }, { 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, - 'carbon-embodied': 4.10958904109589 * 2, + duration: 3600, + vCPUs: 4, + 'embodied-carbon': 14.269406392694064, }, ]); }); it('executes when `mapping` has valid data.', async () => { const mapping = { - 'device/emissions-embodied': 'device/carbon-footprint', + vCPUs: 'device/cpu-cores', }; - const sciEmbodied = SciEmbodied(undefined, parametersMetadata, mapping); + const sciEmbodied = SciEmbodied({}, parametersMetadata, mapping); const inputs = [ { 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, + duration: 3600, }, { 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, + duration: 3600, + 'device/cpu-cores': 2, }, ]; @@ -100,46 +78,32 @@ describe('builtins/sci-embodied:', () => { 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-embodied': 4.10958904109589, + duration: 3600, + 'embodied-carbon': 2.497146118721461, }, { 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-embodied': 4.10958904109589 * 2, + duration: 3600, + 'device/cpu-cores': 2, + 'embodied-carbon': 5.707762557077626, }, ]); }); it('executes when the `mapping` maps output parameter.', async () => { const mapping = { - 'carbon-embodied': 'carbon', + 'embodied-carbon': 'carbon', }; - const sciEmbodied = SciEmbodied(undefined, parametersMetadata, mapping); + 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, + duration: 3600, }, { 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, + duration: 3600, + 'device/cpu-cores': 2, }, ]; @@ -150,75 +114,32 @@ describe('builtins/sci-embodied:', () => { expect(result).toStrictEqual([ { 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, - carbon: 4.10958904109589, + duration: 3600, + carbon: 2.497146118721461, }, { 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, - carbon: 4.10958904109589 * 2, + duration: 3600, + 'device/cpu-cores': 2, + carbon: 2.497146118721461, }, ]); }); - it('returns a result when `vcpus-allocated` and `vcpus-total` are in the input.', async () => { - 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, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - }, - ]; - - const result = await sciEmbodied.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([ + it('returns a result with `vCPUs` in input and `total-vcpus` in config.', async () => { + const sciEmbodied = SciEmbodied( { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589, + 'total-vcpus': 1, + lifespan: 60 * 60 * 24 * 365 * 4, }, - ]); - }); - - it('returns a result when `vcpus-allocated` and `vcpus-total` are preferred to `resources-reserved` and `resources-total`.', async () => { + parametersMetadata, + {} + ); 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': 2, - 'resources-total': 2, - 'vcpus-allocated': 1, - 'vcpus-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, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'resources-reserved': 2, - 'resources-total': 2, + vCPUs: 1, }, ]; @@ -230,91 +151,23 @@ describe('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589, - 'resources-reserved': 2, - 'resources-total': 2, - }, - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30 * 2, - 'device/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - 'carbon-embodied': 4.10958904109589 * 2, - 'resources-reserved': 2, - 'resources-total': 2, + vCPUs: 1, + 'embodied-carbon': 1797.945205479452, }, ]); }); - it('returns a result when `vcpus-allocated` and `vcpus-total` are miised.', async () => { + it('throws an error when `vCPUs` is string.', async () => { 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, + vCPUs: 'string', }, { 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/emissions-embodied': 200, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'carbon-embodied': 4.10958904109589, - '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, - 'carbon-embodied': 4.10958904109589 * 2, - 'resources-reserved': 1, - 'resources-total': 1, - }, - ]); - }); - - it('throws an error when `device/emissions-embodied` is string.', async () => { - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': '10,00', - '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, + vCPUs: 'string', }, ]; @@ -324,87 +177,12 @@ describe('builtins/sci-embodied:', () => { } catch (error) { expect(error).toStrictEqual( new InputValidationError( - `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( - 'gco2e' - )}. Error code: invalid_union.` + '"vCPUs" parameter is expected number, received string. Error code: invalid_type.' ) ); expect(error).toBeInstanceOf(InputValidationError); } }); - - it('throws an exception on missing `device/emissions-embodied`.', async () => { - const errorMessage = - '"device/emissions-embodied" parameter is required. Error code: invalid_union.'; - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/expected-lifespan': 60 * 60 * 24 * 365 * 4, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); - expect(error).toBeInstanceOf(InputValidationError); - } - }); - - it('throws an exception on missing `device/expected-lifespan`.', async () => { - const errorMessage = - '"device/expected-lifespan" parameter is required. Error code: invalid_union.'; - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': 200, - 'vcpus-allocated': 1, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toStrictEqual(new InputValidationError(errorMessage)); - expect(error).toBeInstanceOf(InputValidationError); - } - }); - - it('throws an exception on invalid values.', async () => { - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - 'device/emissions-embodied': '200', - 'vcpus-allocated': true, - 'vcpus-total': 1, - }, - ]; - - expect.assertions(2); - - try { - await sciEmbodied.execute(inputs); - } catch (error) { - expect(error).toBeInstanceOf(InputValidationError); - expect(error).toStrictEqual( - new InputValidationError( - `"device/emissions-embodied" parameter is ${SCI_EMBODIED_ERROR( - 'gco2e' - )}. Error code: invalid_union.` - ) - ); - } - }); }); }); }); From c43c5eb06fd68ab59a89414fd73811cc920ed16b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 27 Aug 2024 19:05:01 +0400 Subject: [PATCH 690/863] revert(util): remove conole.log from aggregation helper --- src/if-run/util/aggregation-helper.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index 4629d9bc4..e573720b1 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -23,8 +23,6 @@ export const aggregateInputsIntoOne = ( const metricsKeys: string[] = metrics.map(metric => Object.keys(metric)[0]); const extendedMetrics = [...metricsKeys, ...AGGREGATION_ADDITIONAL_PARAMS]; - console.log(extendedMetrics); - return inputs.reduce((acc, input, index) => { for (const metric of extendedMetrics) { if (!(metric in input)) { From 9386f384f0c96fbd7c30056a6c1d411c3b6433e7 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:17:13 +0100 Subject: [PATCH 691/863] feat(lib): update sci-embodied touse usage-ratio instea of total-vcpus --- src/if-run/builtins/sci-embodied/index.ts | 49 ++++++++++++++--------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index a8f511066..c162df1a6 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -50,9 +50,16 @@ export const SciEmbodied = ( unit: 'GPUs', 'aggregation-method': 'copy', }, - 'total-vcpus': { - description: 'total number of CPUs or vCPUs available for a resource', - unit: 'CPUs', + 'usage-ratio': { + description: + 'a scaling factor that can be used to describe the ratio of actual resource usage comapred to real device usage, e.g. 0.25 if you are using 2 out of 8 vCPUs, 0.1 if you are responsible for 1 out of 10 GB of storage, etc', + unit: 'dimensionless', + 'aggregation-method': 'copy', + }, + time: { + description: + 'a time unit to scale the embodied carbon by, in seconds. If not provided,time defaults to the value of the timestep duration.', + unit: 'seconds', 'aggregation-method': 'copy', }, } as ParameterMetadata), @@ -76,7 +83,6 @@ export const SciEmbodied = ( 'baseline-memory': z.number().gte(0).default(16), 'baseline-emissions': z.number().gte(0).default(1000000), lifespan: z.number().gt(0).default(126144000), - time: z.number().gt(0).optional(), 'vcpu-emissions-constant': z.number().gte(0).default(100000), 'memory-emissions-constant': z .number() @@ -107,7 +113,8 @@ export const SciEmbodied = ( ssd: z.number().gte(0).default(0), hdd: z.number().gte(0).default(0), gpu: z.number().gte(0).default(0), - 'total-vcpus': z.number().gte(0).default(8), + 'usage-ratio': z.number().gt(0).default(1), + time: z.number().gt(0).optional(), }); return validate>(schema as ZodType, input); @@ -130,27 +137,31 @@ export const SciEmbodied = ( safeConfig['vcpu-emissions-constant']; const memoryE = (safeInput.memory - safeConfig['baseline-memory']) * - safeConfig['memory-emissions-constant']; - const hddE = safeInput.hdd - safeConfig['hdd-emissions-constant']; - const gpuE = safeInput.gpu - safeConfig['gpu-emissions-constant']; - const ssdE = safeInput.ssd - safeConfig['ssd-emissions-constant']; - const time = safeConfig['time'] || safeInput.duration; + ((safeConfig['memory-emissions-constant'] * + safeConfig['baseline-memory']) / + 16) * + 1000; + // (safeInput.memory - safeConfig['baseline-memory']) * + // safeConfig['memory-emissions-constant']; + const hddE = safeInput.hdd * safeConfig['hdd-emissions-constant']; + const gpuE = safeInput.gpu * safeConfig['gpu-emissions-constant']; + const ssdE = safeInput.ssd * safeConfig['ssd-emissions-constant']; + const time = safeInput['time'] || safeInput.duration; const totalEmbodied = - (safeConfig['baseline-emissions'] + - cpuE + - memoryE + - ssdE + - hddE + - gpuE) * - (safeInput.vCPUs / safeInput['total-vcpus']) * - (time / safeConfig['lifespan']); + safeConfig['baseline-emissions'] + cpuE + memoryE + ssdE + hddE + gpuE; + + const totalEmbodiedScaledByUsage = + totalEmbodied * safeInput['usage-ratio']; + + const totalEmbodiedScaledByUsageAndTime = + totalEmbodiedScaledByUsage * (time / safeConfig['lifespan']); const embodiedCarbonKey = safeConfig['output-parameter'] || 'embodied-carbon'; const result = { ...input, - [embodiedCarbonKey]: totalEmbodied, + [embodiedCarbonKey]: totalEmbodiedScaledByUsageAndTime, }; return mapOutputIfNeeded(result, mapping); From cf2b053e64d4df6f92766ed65d760b6dd09a6416 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:19:11 +0100 Subject: [PATCH 692/863] feat(lib): update sci-embodied unit tests --- .../if-run/builtins/sci-embodied.test.ts | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index a1865f4d5..9014a0982 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -43,13 +43,13 @@ describe('builtins/sci-embodied:', () => { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 2, - 'embodied-carbon': 5.707762557077626, + 'embodied-carbon': 31.39269406392694, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 4, - 'embodied-carbon': 14.269406392694064, + 'embodied-carbon': 37.10045662100457, }, ]); }); @@ -79,13 +79,13 @@ describe('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - 'embodied-carbon': 2.497146118721461, + 'embodied-carbon': 28.538812785388128, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, 'device/cpu-cores': 2, - 'embodied-carbon': 5.707762557077626, + 'embodied-carbon': 31.39269406392694, }, ]); }); @@ -115,44 +115,13 @@ describe('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - carbon: 2.497146118721461, + carbon: 28.538812785388128, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, 'device/cpu-cores': 2, - carbon: 2.497146118721461, - }, - ]); - }); - - it('returns a result with `vCPUs` in input and `total-vcpus` in config.', async () => { - const sciEmbodied = SciEmbodied( - { - 'total-vcpus': 1, - lifespan: 60 * 60 * 24 * 365 * 4, - }, - parametersMetadata, - {} - ); - const inputs = [ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - vCPUs: 1, - }, - ]; - - const result = await sciEmbodied.execute(inputs); - - expect.assertions(1); - - expect(result).toStrictEqual([ - { - timestamp: '2021-01-01T00:00:00Z', - duration: 60 * 60 * 24 * 30, - vCPUs: 1, - 'embodied-carbon': 1797.945205479452, + carbon: 28.538812785388128, }, ]); }); From cc174288044a7ab4ca88c186edeca767fdc24538 Mon Sep 17 00:00:00 2001 From: jmc <33655003+jmcook1186@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:19:35 +0100 Subject: [PATCH 693/863] feat(lib): update sci-embodied readme --- src/if-run/builtins/sci-embodied/README.md | 39 +++++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index c80462db8..8363abbe5 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -4,6 +4,9 @@ Software systems cause emissions through the hardware that they operate on, both Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions). +Our plugin follows the Cloud Carbon Footprint methodology for calculating embodied carbon and extends it to scale down the total embodied carbon for a poiece of hardware by the portion of it that should be allocated to a particular application, using a `usage-ratio` and `time`. The `usage-ratio` is a term that can be used to scale by, for example, the storage you actually use on a shared server, rather than the total storage available fir that hardware, or the time you are active compared to the hardware lifespan. + + ## Parameters ### Plugin Configuration @@ -36,19 +39,38 @@ sci-embodied: 'parameter-name-in-the-plugin': 'parameter-name-in-the-input' ``` +### Config + +`baseline-vcpus`: the number of CPUs to use in the baseline server, defaults tothe CCF value of 1, +`baseline-memory`: the amount of memory to use in the baseline server, defaults tothe CCF value of 16, +`baseline-emissions`: the embodied carbon assumed to represent a baseline server, in g +`lifespan`: the lifespan of the device, in seconds. Defaults to 4 years (126144000 seconds), +`time`: the time to consider when scaling the total device embodied carbon, if not given defaults to `duration` +`vcpu-emissions-constant`: emissions for a CPU in gCO2e. Defaults tothe CCF value (100000), +`memory-emissions-constant`: value used in calculating emissions due to memory, defaults to the CCf value of 533/384 +`ssd-emissions-constant`: emissions for a SSD in gCO2e. Defaults tothe CCF value (50000), +`hdd-emissions-constant`: emissions for a CPU in gCO2e. Defaults tothe CCF value (100000), +`gpu-emissions-constant`: emissions for a GPU in gCO2e. Defaults tothe CCF value (150000), +`output-parameter`: name to give the output value, defaults to `embodied-carbon` + +Note that if you do not provide any config at all, we will fallback to defaults for everything, equivalen to setting the baseline server equal to the CCF version, which has 1000000g of embnodied emissions. + ### Inputs -- `device/emissions-embodied`: The total embodied emissions for the component, measured in gCO2e. -- `device/expected-lifespan`: The expected lifespan of the component, in seconds. -- `resources-reserved`: The number of resources reserved for use by the software. -- `resources-total`: The total number of resources available. -- `vcpus-allocated`: The number of virtual CPUs allocated to a particular resource. -- `vcpus-total`: The total number of virtual CPUs available on a particular resource. +- `vCPUs`: number of CPUs available on device +- `memory`: amount of RAM available on device, in GB +- `ssd`: number of SSD drives mounted on device +- `hdd`: number of HDD drives mounted on device +- `gpu`: number of GPUs available on device - `duration`: The length of time the hardware is reserved for use by the software, in seconds. +- `time`: the time to use for scalign the total embodied carbon per timestap, if you do not want to use `duration` +- `usage-ratio`: the ratio by which to scale down the total embodied carbon according to your usage, e.g. for a shared storage server the total storage divided by your actual storage. + +Note that if you do not provide any inputs at all, we fall back to defaults that are equivalent to using the full resources of the baseline server, scaled only by `duration`. ### Outputs -- `carbon-embodied`: The total embodied emissions for the component, measured in gCO2e. +- `carbon-embodied`: The total embodied emissions for the component, measured in gCO2e, per timestep. ## Calculation @@ -57,7 +79,7 @@ The plugin calculates the total embodied carbon emissions using the following st - CPU emissions (`cpuE`) are calculated based on the difference between allocated vCPUs and baseline vCPUs. - Memory emissions (`memoryE`) are calculated based on the difference between allocated memory and baseline memory. - Emissions for HDD, SSD, and GPU are also calculated based on their respective differences from baseline values. - - The total embodied emissions are calculated by summing the baseline emissions with the above components and adjusting for the lifespan and time duration. + - The total embodied emissions are calculated by summing the baseline emissions with the above components scaling by the usage ratio and time. ## Implementation @@ -75,7 +97,6 @@ const results = await sciEmbodied.execute([ ssd: 100, // allocated SSD storage in GB hdd: 1000, // allocated HDD storage in GB gpu: 1, // allocated GPUs - 'total-vcpus': 8, // total available vCPUs }, ]); From b2c4f2227a6233ad96fd1df0c629ccca9015622b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 14:33:14 +0400 Subject: [PATCH 694/863] feat(manifets): init updated sci embodied samples --- ...failure-invalid-default-emission-value.yml | 23 ------------ .../failure-missing-expected-lifespan.yml | 23 ------------ .../builtins/sci-embodied/scenario-1.yml | 27 ++++++++++++++ .../builtins/sci-embodied/scenario-2.yml | 37 +++++++++++++++++++ .../builtins/sci-embodied/success.yml | 12 +++++- 5 files changed, 75 insertions(+), 47 deletions(-) delete mode 100644 manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml delete mode 100644 manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml create mode 100644 manifests/examples/builtins/sci-embodied/scenario-1.yml create mode 100644 manifests/examples/builtins/sci-embodied/scenario-2.yml diff --git a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml b/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml deleted file mode 100644 index 503300f84..000000000 --- a/manifests/examples/builtins/sci-embodied/failure-invalid-default-emission-value.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: sci-embodied -description: failure with `defaults.device/emissions-embodied` being string instead of number -tags: -initialize: - plugins: - "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor - method: SciEmbodied - path: "builtin" -tree: - children: - child: - pipeline: - compute: - - sci-embodied # duration & config -> embodied - defaults: - device/emissions-embodied: "fail" # gCO2eq - time-reserved: 3600 # 1hr in seconds - device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml b/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml deleted file mode 100644 index 8fd3e5784..000000000 --- a/manifests/examples/builtins/sci-embodied/failure-missing-expected-lifespan.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: sci-embodied -description: missing device/expected-lifespan -tags: -initialize: - plugins: - "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor - method: SciEmbodied - path: "builtin" -tree: - children: - child: - pipeline: - compute: - - sci-embodied # duration & config -> embodied - defaults: - device/emissions-embodied: 1533.120 # gCO2eq - time-reserved: 3600 # 1hr in seconds - #device/expected-lifespan: 94608000 # 3 years in seconds - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/examples/builtins/sci-embodied/scenario-1.yml b/manifests/examples/builtins/sci-embodied/scenario-1.yml new file mode 100644 index 000000000..93edd3d7d --- /dev/null +++ b/manifests/examples/builtins/sci-embodied/scenario-1.yml @@ -0,0 +1,27 @@ +name: embodied-carbon demo +description: +tags: +aggregation: + metrics: + - embodied-carbon + type: "both" +initialize: + plugins: + embodied-carbon: + method: SciEmbodied + path: builtin + global-config: + output-parameter: "embodied-carbon" +tree: + children: + child: + pipeline: + compute: + - embodied-carbon + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + hdd: 2 + - timestamp: 2023-08-06T10:00 + duration: 3600 + hdd: 2 diff --git a/manifests/examples/builtins/sci-embodied/scenario-2.yml b/manifests/examples/builtins/sci-embodied/scenario-2.yml new file mode 100644 index 000000000..2c2363a76 --- /dev/null +++ b/manifests/examples/builtins/sci-embodied/scenario-2.yml @@ -0,0 +1,37 @@ +name: embodied-carbon demo +description: +tags: +initialize: + plugins: + embodied-carbon: + method: SciEmbodied + path: builtin + global-config: + baseline-vcpus: 1 + baseline-memory: 16 + lifespan: 157680000 + baseline-emissions: 2000000 + vcpu-emissions-constant: 100000 + memory-emissions-constant: 1172 + ssd-emissions-constant: 50000 + hdd-emissions-constant: 100000 + gpu-emissions-constant: 150000 + output-parameter: "embodied-carbon" +tree: + children: + child: + pipeline: + compute: + - embodied-carbon + defaults: + vCPUs: 4 + memory: 32 + ssd: 1 + hdd: 1 + gpu: 1 + total-vcpus: 16 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + - timestamp: 2023-08-06T10:00 + duration: 3600 diff --git a/manifests/examples/builtins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml index 991569404..c37677931 100644 --- a/manifests/examples/builtins/sci-embodied/success.yml +++ b/manifests/examples/builtins/sci-embodied/success.yml @@ -3,7 +3,16 @@ description: successful path tags: initialize: plugins: - "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor + "csv-lookup": + path: builtin + method: CSVLookup + config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: ["cpu-cores-utilized", "vcpus-allocated"] + "sci-embodied-new": # a model that calculates m from te, tir, el, rr and rtor method: SciEmbodied path: "builtin" tree: @@ -11,6 +20,7 @@ tree: child: pipeline: compute: + - csv-lookup - sci-embodied # duration & config -> embodied defaults: device/emissions-embodied: 1533.120 # gCO2eq From 8f3d5ea9ed4634a87cd522cbf3b8bbe0a66696a1 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:03:57 +0400 Subject: [PATCH 695/863] feat(config): add strings for explain feature --- src/common/config/strings.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/config/strings.ts b/src/common/config/strings.ts index 82592463f..e5884852b 100644 --- a/src/common/config/strings.ts +++ b/src/common/config/strings.ts @@ -10,4 +10,8 @@ Incubation projects are experimental, offer no support guarantee, have minimal g SUCCESS_MESSAGE: 'The environment is successfully setup!', MANIFEST_IS_MISSING: 'Manifest is missing.', DIRECTORY_NOT_FOUND: 'Directory not found.', + AGGREGATION_UNITS_NOT_MATCH: (param: string) => + `Your manifest uses two instances of ${param} with different units. Please check that you are using consistent units for ${param} throughout your manifest.`, + AGGREGATION_METHODS_NOT_MATCH: (param: string) => + `Your manifest uses two instances of ${param} with different 'aggregation-method'. Please check that you are using right 'aggregation-method' for ${param} throughout your manifest.`, }; From 428196f6e75087d7065338b67f68cb0509fc681a Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:06:52 +0400 Subject: [PATCH 696/863] feat(lib): update explain feature logic --- src/if-run/lib/explain.ts | 73 +++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index dce49b75a..eb42cfd49 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -1,26 +1,33 @@ -import {ExplainParams} from '../types/explain'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../common/config'; + +import {ExplainParams, ExplainStorageType} from '../types/explain'; + +const {ManifestValidationError} = ERRORS; +const {AGGREGATION_UNITS_NOT_MATCH, AGGREGATION_METHODS_NOT_MATCH} = STRINGS; /** * Retrieves stored explain data. */ -export const explain = () => storeExplainData.plugins; +export const explain = () => storeExplainData.parameters; /** * Manages the storage of explain data. */ const storeExplainData = (() => { - let plugin = {}; + let parameter: ExplainStorageType = {}; - const pluginManager = { - get plugins() { - return plugin; + const parameterManager = { + get parameters() { + return parameter; }, - set plugins(value: object) { - plugin = value; + set parameters(value: ExplainStorageType) { + parameter = value; }, }; - return pluginManager; + return parameterManager; })(); /** @@ -28,17 +35,45 @@ const storeExplainData = (() => { */ export const addExplainData = (params: ExplainParams) => { const {pluginName, pluginData, metadata} = params; - const plugin = { - [pluginName]: { - method: pluginData!.method, - path: pluginData!.path, - inputs: metadata?.inputs || 'undefined', - outputs: metadata?.outputs || 'undefined', - }, + const parameterMetadata = pluginData?.['parameter-metadata'] || metadata; + const parameters = storeExplainData.parameters; + const allParameters = { + ...parameterMetadata?.inputs, + ...parameterMetadata?.outputs, }; - storeExplainData.plugins = { - ...storeExplainData.plugins, - ...plugin, + Object.entries(allParameters).forEach(([name, meta]) => { + const existingParameter = parameters[name]; + + if (parameters[name]?.plugins?.includes(pluginName)) { + return; + } + + if (existingParameter) { + if (meta.unit !== existingParameter.unit) { + throw new ManifestValidationError(AGGREGATION_UNITS_NOT_MATCH(name)); + } + + if ( + meta['aggregation-method'] !== existingParameter['aggregation-method'] + ) { + throw new ManifestValidationError(AGGREGATION_METHODS_NOT_MATCH(name)); + } + + existingParameter.plugins.push(pluginName); + existingParameter.description = + meta.description || existingParameter.description; + } else { + parameters[name] = { + plugins: [pluginName], + unit: meta.unit, + description: meta.description, + 'aggregation-method': meta['aggregation-method'], + }; + } + }); + + storeExplainData.parameters = { + ...parameters, }; }; From 2a286a210106d227aafe6a9668be5dc27652fe3b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:11:05 +0400 Subject: [PATCH 697/863] feat(types): add `ExplainStorageType` type --- src/if-run/types/explain.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index c7f1a6d38..c32f91325 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -7,3 +7,13 @@ export type ExplainParams = { pluginData: PluginOptions; metadata: {inputs?: ParameterMetadata; outputs?: ParameterMetadata}; }; + +export type ExplainStorageType = Record< + string, + { + plugins: string[]; + unit: string; + description: string; + 'aggregation-method': string; + } +>; From ee33f3e1e30e93a7874da8c3885e614308380402 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:13:53 +0400 Subject: [PATCH 698/863] test(lib): update tests and add new ones --- src/__tests__/if-run/lib/explain.test.ts | 196 ++++++++++++++++++++--- 1 file changed, 175 insertions(+), 21 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 506c62669..8178bf07d 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -1,8 +1,15 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../../common/config'; + import {explain, addExplainData} from '../../../if-run/lib/explain'; +const {ManifestValidationError} = ERRORS; +const {AGGREGATION_UNITS_NOT_MATCH, AGGREGATION_METHODS_NOT_MATCH} = STRINGS; + describe('lib/explain: ', () => { - it('successfully adds explain data if `inputs` and `outputs` of `metadata` are `undefined`.', () => { + it('missing explain data if `inputs` and `outputs` of `metadata` are `undefined`.', () => { const mockData = { pluginName: 'divide', metadata: {kind: 'execute', inputs: undefined, outputs: undefined}, @@ -11,19 +18,11 @@ describe('lib/explain: ', () => { method: 'Divide', }, }; - const expectedResult = { - divide: { - method: 'Divide', - path: 'builtin', - inputs: 'undefined', - outputs: 'undefined', - }, - }; addExplainData(mockData); const result = explain(); expect.assertions(1); - expect(result).toEqual(expectedResult); + expect(result).toEqual({}); }); it('successfully adds explain data if `inputs` and `outputs` of `metadata` are valid data.', () => { @@ -56,36 +55,99 @@ describe('lib/explain: ', () => { method: 'Sum', }, }; + const expectedResult = { - divide: { - method: 'Divide', - path: 'builtin', - inputs: 'undefined', - outputs: 'undefined', + 'cpu/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', }, - sum: { - method: 'Sum', - path: 'builtin', + 'network/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', + }, + 'energy-sum': { + plugins: ['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); + }); + + it('successfully adds explain data if the parameter is using more than one plugin.', () => { + const mockData = { + pluginName: 'sum-energy', + metadata: { + kind: 'execute', inputs: { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', 'aggregation-method': 'sum', }, - 'network/energy': { + 'memory/energy': { unit: 'kWh', - description: 'energy consumed by data ingress and egress', + description: 'energy consumed by data from memory', 'aggregation-method': 'sum', }, }, outputs: { - 'energy-sum': { + 'total/energy': { unit: 'kWh', description: 'sum of energy components', 'aggregation-method': 'sum', }, }, }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + const expectedResult = { + 'cpu/energy': { + plugins: ['sum', 'sum-energy'], + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', + }, + 'network/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', + }, + 'energy-sum': { + plugins: ['sum'], + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + 'memory/energy': { + plugins: ['sum-energy'], + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + 'total/energy': { + plugins: ['sum-energy'], + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, }; // @ts-ignore @@ -96,4 +158,96 @@ describe('lib/explain: ', () => { expect.assertions(1); expect(result).toEqual(expectedResult); }); + + it('throws an error if `unit` of the parameter is not matched.', () => { + const mockData = { + pluginName: 'sum-of-energy', + metadata: { + kind: 'execute', + inputs: { + 'cpu/energy': { + unit: 'co2q', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', + }, + 'memory/energy': { + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + }, + outputs: { + 'total/energy': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + }, + }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + expect.assertions(2); + try { + // @ts-ignore + addExplainData(mockData); + explain(); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ManifestValidationError); + expect(error.message).toEqual( + AGGREGATION_UNITS_NOT_MATCH('cpu/energy') + ); + } + } + }); + + it('throws an error if `aggregation-method` of the parameter is not matched.', () => { + const mockData = { + pluginName: 'sum-of-energy', + metadata: { + kind: 'execute', + inputs: { + 'cpu/energy': { + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'avg', + }, + 'memory/energy': { + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + }, + outputs: { + 'total/energy': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + }, + }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + expect.assertions(2); + try { + // @ts-ignore + addExplainData(mockData); + explain(); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ManifestValidationError); + expect(error.message).toEqual( + AGGREGATION_METHODS_NOT_MATCH('cpu/energy') + ); + } + } + }); }); From 314e24afe5bfb37dbd0c1ef9aad3f73667f9d2b2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 17:02:51 +0400 Subject: [PATCH 699/863] Update src/if-run/builtins/sci-embodied/README.md Co-authored-by: Manushak Keramyan Signed-off-by: Narek Hovhannisyan --- src/if-run/builtins/sci-embodied/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 8363abbe5..1b9ef57f8 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -4,7 +4,7 @@ Software systems cause emissions through the hardware that they operate on, both Read more on [embodied carbon](https://github.com/Green-Software-Foundation/sci/blob/main/Software_Carbon_Intensity/Software_Carbon_Intensity_Specification.md#embodied-emissions). -Our plugin follows the Cloud Carbon Footprint methodology for calculating embodied carbon and extends it to scale down the total embodied carbon for a poiece of hardware by the portion of it that should be allocated to a particular application, using a `usage-ratio` and `time`. The `usage-ratio` is a term that can be used to scale by, for example, the storage you actually use on a shared server, rather than the total storage available fir that hardware, or the time you are active compared to the hardware lifespan. +Our plugin follows the Cloud Carbon Footprint methodology for calculating embodied carbon and extends it to scale down the total embodied carbon for a piece of hardware by the portion of it that should be allocated to a particular application, using a `usage-ratio` and `time`. The `usage-ratio` is a term that can be used to scale by, for example, the storage you actually use on a shared server, rather than the total storage available for that hardware, or the time you are active compared to the hardware lifespan. ## Parameters From bfc001c310a99748ced8228b56fe91fa6e9cf399 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 17:03:04 +0400 Subject: [PATCH 700/863] Update src/if-run/builtins/sci-embodied/README.md Co-authored-by: Manushak Keramyan Signed-off-by: Narek Hovhannisyan --- src/if-run/builtins/sci-embodied/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index 1b9ef57f8..a40072278 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -53,7 +53,7 @@ sci-embodied: `gpu-emissions-constant`: emissions for a GPU in gCO2e. Defaults tothe CCF value (150000), `output-parameter`: name to give the output value, defaults to `embodied-carbon` -Note that if you do not provide any config at all, we will fallback to defaults for everything, equivalen to setting the baseline server equal to the CCF version, which has 1000000g of embnodied emissions. +Note that if you do not provide any config at all, we will fallback to defaults for everything, equivalent to setting the baseline server equal to the CCF version, which has 1000000g of embodied emissions. ### Inputs From 23b0b3122a91e86c3e50567e0384b122b1676af6 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 17:04:40 +0400 Subject: [PATCH 701/863] fix(manifests): update sci embodied configs --- manifests/examples/builtins/sci-embodied/scenario-1.yml | 2 +- manifests/examples/builtins/sci-embodied/scenario-2.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/examples/builtins/sci-embodied/scenario-1.yml b/manifests/examples/builtins/sci-embodied/scenario-1.yml index 93edd3d7d..57bfdd5cf 100644 --- a/manifests/examples/builtins/sci-embodied/scenario-1.yml +++ b/manifests/examples/builtins/sci-embodied/scenario-1.yml @@ -10,7 +10,7 @@ initialize: embodied-carbon: method: SciEmbodied path: builtin - global-config: + config: output-parameter: "embodied-carbon" tree: children: diff --git a/manifests/examples/builtins/sci-embodied/scenario-2.yml b/manifests/examples/builtins/sci-embodied/scenario-2.yml index 2c2363a76..da8deb5cd 100644 --- a/manifests/examples/builtins/sci-embodied/scenario-2.yml +++ b/manifests/examples/builtins/sci-embodied/scenario-2.yml @@ -6,7 +6,7 @@ initialize: embodied-carbon: method: SciEmbodied path: builtin - global-config: + config: baseline-vcpus: 1 baseline-memory: 16 lifespan: 157680000 From df91712acee2ca2270b652ea3041e6aa86e7f4b1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 17:13:08 +0400 Subject: [PATCH 702/863] revert(builtins): remove comment from sci embodied --- src/if-run/builtins/sci-embodied/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index c162df1a6..2b3c4ccfa 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -141,8 +141,6 @@ export const SciEmbodied = ( safeConfig['baseline-memory']) / 16) * 1000; - // (safeInput.memory - safeConfig['baseline-memory']) * - // safeConfig['memory-emissions-constant']; const hddE = safeInput.hdd * safeConfig['hdd-emissions-constant']; const gpuE = safeInput.gpu * safeConfig['gpu-emissions-constant']; const ssdE = safeInput.ssd * safeConfig['ssd-emissions-constant']; From 1e89d1c24dca06fc9a68f779093a139c680ac28a Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 17:42:29 +0400 Subject: [PATCH 703/863] fix(manifests): fix broken manifests --- .../builtins/time-converter/success.yaml | 4 +- .../examples/features/regroup/success.yml | 2 +- .../pipelines/pipeline-with-mocks.yml | 2 + .../builtins/time-converter/success.yaml | 79 +++++++++++++++++++ 4 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 manifests/outputs/builtins/time-converter/success.yaml diff --git a/manifests/examples/builtins/time-converter/success.yaml b/manifests/examples/builtins/time-converter/success.yaml index 9245562fa..7b2fa1a61 100644 --- a/manifests/examples/builtins/time-converter/success.yaml +++ b/manifests/examples/builtins/time-converter/success.yaml @@ -15,8 +15,8 @@ tree: children: child: pipeline: - - time-converter - config: + compute: + - time-converter defaults: energy-per-year: 10000 inputs: diff --git a/manifests/examples/features/regroup/success.yml b/manifests/examples/features/regroup/success.yml index 6863dc0d6..de6571919 100644 --- a/manifests/examples/features/regroup/success.yml +++ b/manifests/examples/features/regroup/success.yml @@ -1,7 +1,7 @@ name: regroup description: successful path initialize: - plugins: + plugins: {} tree: children: my-app: diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index b27b9bb04..3e3ce92d8 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -266,6 +266,7 @@ tree: device/expected-lifespan: 94608000 # 3 years in seconds vcpus-total: 8 vcpus-allocated: 1 + requests: 50 inputs: child-2: pipeline: @@ -294,4 +295,5 @@ tree: device/expected-lifespan: 94608000 # 3 years in seconds vcpus-total: 8 vcpus-allocated: 1 + requests: 50 inputs: diff --git a/manifests/outputs/builtins/time-converter/success.yaml b/manifests/outputs/builtins/time-converter/success.yaml new file mode 100644 index 000000000..33ae5d503 --- /dev/null +++ b/manifests/outputs/builtins/time-converter/success.yaml @@ -0,0 +1,79 @@ +name: time-converter demo +description: successful path +tags: null +initialize: + plugins: + time-converter: + path: builtin + method: TimeConverter + config: + input-parameter: energy-per-year + original-time-unit: year + new-time-unit: duration + output-parameter: energy-per-duration +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/time-converter/success.yaml -o + manifests/outputs/time-converter/success + environment: + if-version: 0.6.0 + os: macOS + os-version: 13.6.7 + node-version: 18.20.0 + date-time: 2024-08-28T13:04:25.498Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.18' + - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models' + - >- + @grnsft/if-unofficial-plugins@v0.3.0 extraneous -> + file:../../../if-unofficial-models + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - if-eco-ci-plugin@v0.0.1 extraneous -> file:../../if-eco-ci-plugin + - if-github-plugin@v0.0.1 extraneous -> file:../../if-github-plugin + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child: + pipeline: + compute: + - time-converter + defaults: + energy-per-year: 10000 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + energy-per-year: 10000 + energy-per-duration: 1.140795 From 2e05ea600ce0d61589f1eb729305fedfd9aa6f7f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 28 Aug 2024 18:24:33 +0400 Subject: [PATCH 704/863] fix(manifests): fix indentation of default in sci embodied --- .../examples/builtins/sci-embodied/scenario-2.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/manifests/examples/builtins/sci-embodied/scenario-2.yml b/manifests/examples/builtins/sci-embodied/scenario-2.yml index da8deb5cd..d4c2640ff 100644 --- a/manifests/examples/builtins/sci-embodied/scenario-2.yml +++ b/manifests/examples/builtins/sci-embodied/scenario-2.yml @@ -23,13 +23,13 @@ tree: pipeline: compute: - embodied-carbon - defaults: - vCPUs: 4 - memory: 32 - ssd: 1 - hdd: 1 - gpu: 1 - total-vcpus: 16 + defaults: + vCPUs: 4 + memory: 32 + ssd: 1 + hdd: 1 + gpu: 1 + total-vcpus: 16 inputs: - timestamp: 2023-08-06T00:00 duration: 3600 From 5b3e810264518a94a2e05267ba2c9929210a572e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:34:31 +0400 Subject: [PATCH 705/863] fix(lib): change default aggregation method --- src/if-run/lib/aggregate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 43b84fcf6..a810ecc47 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -159,5 +159,5 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - return AGGREGATION_METHODS[2]; + return AGGREGATION_METHODS[AGGREGATION_METHODS.length - 1]; }; From 18dd4c11b9edfd2548a1573e75a570185102cd32 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:36:07 +0400 Subject: [PATCH 706/863] fix(builtins): add a bit of doc, remove additional 1 second --- src/if-run/builtins/time-sync/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index d85f08c32..02352212d 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -482,7 +482,7 @@ export const TimeSync = ( paddedArray.push( ...getZeroishInputPerSecondBetweenRange( lastInputEnd, - params.endTime.plus({seconds: 1}), + params.endTime, lastInput ) ); @@ -491,6 +491,9 @@ export const TimeSync = ( return paddedArray; }; + /** + * Brakes down the given range by 1 second, and generates zeroish values. + */ const getZeroishInputPerSecondBetweenRange = ( startDate: DateTimeMaybeValid, endDate: DateTimeMaybeValid, From 359e60005f3e18d3e220a5cb13aa2c829a7cc568 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:46:48 +0400 Subject: [PATCH 707/863] test(builtins): update time sync --- .../if-run/builtins/time-sync.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 0bfc59b5a..f3b268034 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -463,12 +463,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 1, - 'cpu/utilization': null, + 'cpu/utilization': 10, }, { timestamp: '2023-12-12T00:00:01.000Z', duration: 1, - 'cpu/utilization': null, + 'cpu/utilization': 10, }, ]; @@ -578,12 +578,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, - 'resources-total': null, + 'resources-total': 10, }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, - 'resources-total': null, + duration: 4, + 'resources-total': 10, }, ]; @@ -627,9 +627,9 @@ describe('builtins/time-sync:', () => { }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, + duration: 4, 'resources-total': 10, - 'time-reserved': 3.2, + 'time-reserved': 3.75, }, ]; @@ -676,9 +676,9 @@ describe('builtins/time-sync:', () => { }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, + duration: 4, 'resources-total': 10, - 'time-allocated': 3.2, + 'time-allocated': 3.75, }, ]; From 098a23ed0893d1023ab9bab0591e4e80770876ff Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:55:10 +0400 Subject: [PATCH 708/863] feat(util): enable granular aggregation in helper --- src/if-run/util/aggregation-helper.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index e573720b1..211364f1a 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -3,13 +3,13 @@ import {PluginParams} from '@grnsft/if-core/types'; import {CONFIG, STRINGS} from '../config'; -import {AggregationMetric, AggregationResult} from '../types/aggregation'; +import {AggregationResult} from '../types/aggregation'; -import {getAggregationMethod} from '../lib/aggregate'; +import {getAggregationInfoFor} from '../lib/aggregate'; const {MissingAggregationParamError} = ERRORS; const {METRIC_MISSING} = STRINGS; -const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; +const {AGGREGATION_TIME_METRICS} = CONFIG; /** * Aggregates child node level metrics. Appends aggregation additional params to metrics. @@ -17,31 +17,32 @@ const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; */ export const aggregateInputsIntoOne = ( inputs: PluginParams[], - metrics: AggregationMetric[], + metrics: string[], isTemporal?: boolean ) => { - const metricsKeys: string[] = metrics.map(metric => Object.keys(metric)[0]); - const extendedMetrics = [...metricsKeys, ...AGGREGATION_ADDITIONAL_PARAMS]; + const metricsWithTime = metrics.concat(AGGREGATION_TIME_METRICS); return inputs.reduce((acc, input, index) => { - for (const metric of extendedMetrics) { + for (const metric of metricsWithTime) { if (!(metric in input)) { throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); } /** Checks if metric is timestamp or duration, then adds to aggregated value. */ - if (AGGREGATION_ADDITIONAL_PARAMS.includes(metric)) { + if (AGGREGATION_TIME_METRICS.includes(metric)) { if (isTemporal) { acc[metric] = input[metric]; } } else { - const method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); + /** Checks either its a temporal aggregation (vertical), then chooses `component`, otherwise `time`. */ + const aggregationType = isTemporal ? 'component' : 'time'; - if (method === 'none') { + if (aggregationParams[aggregationType] === 'none') { return acc; } - if (method === 'copy') { + if (aggregationParams[aggregationType] === 'copy') { acc[metric] = input[metric]; return acc; } @@ -51,7 +52,7 @@ export const aggregateInputsIntoOne = ( /** Checks for the last iteration. */ if (index === inputs.length - 1) { - if (method === 'avg') { + if (aggregationParams[aggregationType] === 'avg') { acc[metric] /= inputs.length; } } From 5f6b05528b4dfab365f1399c74c79e64035f9f8f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:56:08 +0400 Subject: [PATCH 709/863] feat(types): use aggregation options as method --- src/if-run/types/explain.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index c32f91325..caedd3992 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -1,4 +1,4 @@ -import {ParameterMetadata} from '@grnsft/if-core/types'; +import {AggregationOptions, ParameterMetadata} from '@grnsft/if-core/types'; import {PluginOptions} from '../../common/types/manifest'; @@ -14,6 +14,6 @@ export type ExplainStorageType = Record< plugins: string[]; unit: string; description: string; - 'aggregation-method': string; + 'aggregation-method': AggregationOptions; } >; From ea5270f50cb0eaf2b6b5405515d45a3c0601c1ed Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:57:00 +0400 Subject: [PATCH 710/863] feat(types): enable time and component aggregations --- src/if-run/types/aggregation.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts index 5315b298f..811833c7b 100644 --- a/src/if-run/types/aggregation.ts +++ b/src/if-run/types/aggregation.ts @@ -1,7 +1,9 @@ -import {AggregationMethodTypes} from '@grnsft/if-core/types'; - export type AggregationResult = Record; -export const AGGREGATION_TYPES = ['horizontal', 'vertical', 'both'] as const; - -export type AggregationMetric = Record; +export const AGGREGATION_TYPES = [ + 'horizontal', + 'time', + 'vertical', + 'component', + 'both', +] as const; From e4e01e2b50882a0ebe62555c114433f3a2e641b1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:57:48 +0400 Subject: [PATCH 711/863] fix(lib): update docs, improve readablity in initialize --- src/if-run/lib/initialize.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 6deb73ce2..9239fe3d1 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -103,6 +103,10 @@ const initPlugin = async ( /** * Registers all plugins from `manifest`.`initialize` property. + * 1. Initalizes plugin storage. + * 2. Iterates over plugin names array. + * 3. While iteration, initalizes current plugin, gathers it's parameters (input/output). + * Then stores the aggregation metrics for each parameter to override stub values. */ export const initialize = async ( context: Context @@ -117,9 +121,9 @@ export const initialize = async ( const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; - Object.keys(parameters).forEach(key => { + Object.keys(parameters).forEach(current => { storeAggregationMetrics({ - [key]: parameters[key]['aggregation-method'], + [current]: parameters[current]['aggregation-method'], }); }); From bca762906d27f03e4f30aae20b5979dd65d30e8a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:58:36 +0400 Subject: [PATCH 712/863] feat(lib): use granular aggregation in explain --- src/if-run/lib/explain.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index eb42cfd49..470eed2e7 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -40,7 +40,7 @@ export const addExplainData = (params: ExplainParams) => { const allParameters = { ...parameterMetadata?.inputs, ...parameterMetadata?.outputs, - }; + } as ExplainStorageType; Object.entries(allParameters).forEach(([name, meta]) => { const existingParameter = parameters[name]; @@ -55,7 +55,10 @@ export const addExplainData = (params: ExplainParams) => { } if ( - meta['aggregation-method'] !== existingParameter['aggregation-method'] + meta['aggregation-method'].component !== + existingParameter['aggregation-method'].component || + meta['aggregation-method'].time !== + existingParameter['aggregation-method'].time ) { throw new ManifestValidationError(AGGREGATION_METHODS_NOT_MATCH(name)); } From d4567890921c0d4a736e60bfbcbad5f681ff28da Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:59:30 +0400 Subject: [PATCH 713/863] feat(lib): introduce granular aggregation to aggregate --- src/if-run/lib/aggregate.ts | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index a810ecc47..bee7d3031 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -12,8 +12,6 @@ import { import {aggregateInputsIntoOne} from '../util/aggregation-helper'; import {memoizedLog} from '../util/log-memoize'; -import {AggregationMetric} from '../types/aggregation'; - import {STRINGS} from '../config/strings'; const { @@ -40,7 +38,7 @@ const getIthElementsFromChildren = (children: any, i: number) => { * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. */ -const temporalAggregation = (node: any, metrics: AggregationMetric[]) => { +const temporalAggregation = (node: any, metrics: string[]) => { const outputs: PluginParams[] = []; const values: any = Object.values(node.children); @@ -64,9 +62,7 @@ const temporalAggregation = (node: any, metrics: AggregationMetric[]) => { * 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them. */ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { - const metrics: AggregationMetric[] = aggregationParams!.metrics.map( - metric => ({[metric]: 'none'}) - ); + const metrics = aggregationParams!.metrics; const type = aggregationParams!.type; if (node.children) { @@ -78,11 +74,13 @@ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { } if (!node.children) { - if (type === 'horizontal' || type === 'both') { + /** `time` aggregation is the new name of `horizontal`. */ + if (type === 'horizontal' || type === 'time' || type === 'both') { node.aggregated = aggregateInputsIntoOne(node.outputs, metrics); } } else { - if (type === 'vertical' || type === 'both') { + /** `component` aggregation is the new name of `vertical`. */ + if (type === 'vertical' || type === 'component' || type === 'both') { const outputs = temporalAggregation(node, metrics); node.outputs = outputs; node.aggregated = aggregateInputsIntoOne(outputs, metrics); @@ -127,13 +125,13 @@ export const storeAggregationMetrics = ( * Creates an encapsulated object to retrieve the metrics. */ const metricManager = (() => { - let metric: AggregationMetric; + let metric: AggregationMetricsWithMethod; const manager = { get metrics() { return metric; }, - set metrics(value: AggregationMetric) { + set metrics(value: AggregationMetricsWithMethod) { metric = value; }, }; @@ -142,22 +140,25 @@ const metricManager = (() => { })(); /** - * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. + * Returns aggregation method for given `metric`. */ -export const getAggregationMethod = (unitName: string) => { +export const getAggregationInfoFor = (metric: string) => { debugLogger.setExecutingPluginName(); memoizedLog(console.debug, '\n'); - memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); + memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(metric)); const aggregationMetricsStorage = storeAggregationMetrics(); if ( aggregationMetricsStorage && - Object.keys(aggregationMetricsStorage).includes(unitName) + Object.keys(aggregationMetricsStorage).includes(metric) ) { - return aggregationMetricsStorage[unitName]; + return aggregationMetricsStorage[metric]; } - memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); + memoizedLog(logger.warn, UNKNOWN_PARAM(metric)); - return AGGREGATION_METHODS[AGGREGATION_METHODS.length - 1]; + return { + time: AGGREGATION_METHODS[3], + component: AGGREGATION_METHODS[3], + }; }; From 668dfbab8008ad680b012e716df3605b894a7c88 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:00:06 +0400 Subject: [PATCH 714/863] feat(config): rename additional params to time metrics --- src/if-run/config/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index 9bd39d89f..d151a0389 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -71,5 +71,5 @@ export const CONFIG = { } as ParseOptions, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', - AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], + AGGREGATION_TIME_METRICS: ['timestamp', 'duration'], }; From dc840e678f91f413f44bfb0786e319940a62f429 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:00:55 +0400 Subject: [PATCH 715/863] feat(builtins): use granular aggregation in time sync --- src/if-run/builtins/time-sync/index.ts | 59 +++++++++++++++----------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 02352212d..e34c4ca36 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -21,7 +21,7 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {getAggregationMethod} from '../../lib/aggregate'; +import {getAggregationInfoFor} from '../../lib/aggregate'; Settings.defaultZone = 'utc'; @@ -69,12 +69,18 @@ export const TimeSync = ( timestamp: { description: 'refers to the time of occurrence of the input', unit: 'RFC3339', - 'aggregation-method': 'none', + 'aggregation-method': { + time: 'none', + component: 'none', + }, }, duration: { description: 'refers to the duration of the input', unit: 'seconds', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'none', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, @@ -246,35 +252,35 @@ export const TimeSync = ( * Breaks down input per minimal time unit. */ const breakDownInput = (input: PluginParams, i: number) => { - const inputKeys = Object.keys(input); + const metrics = Object.keys(input); - return inputKeys.reduce((acc, key) => { - const method = getAggregationMethod(key); + return metrics.reduce((acc, metric) => { + const aggregationParams = getAggregationInfoFor(metric); - if (key === 'timestamp') { + if (metric === 'timestamp') { const perSecond = normalizeTimePerSecond(input.timestamp, i); - acc[key] = perSecond.toUTC().toISO() ?? ''; + acc[metric] = perSecond.toUTC().toISO() ?? ''; return acc; } /** @todo use user defined resolution later */ - if (key === 'duration') { - acc[key] = 1; + if (metric === 'duration') { + acc[metric] = 1; return acc; } - if (method === 'none') { - acc[key] = null; + if (aggregationParams.time === 'none') { + acc[metric] = null; return acc; } - acc[key] = - method === 'sum' - ? convertPerInterval(input[key], input['duration']) - : input[key]; + acc[metric] = + aggregationParams.time === 'sum' + ? convertPerInterval(input[metric], input['duration']) + : input[metric]; return acc; }, {} as PluginParams); @@ -314,21 +320,24 @@ export const TimeSync = ( return acc; } - const method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); - if (method === 'none') { + if (aggregationParams.time === 'none') { acc[metric] = null; return acc; } - if (method === 'avg' || method === 'sum') { + if ( + aggregationParams.time === 'avg' || + aggregationParams.time === 'sum' + ) { acc[metric] = 0; return acc; } - if (method === 'copy') { + if (aggregationParams.time === 'copy') { acc[metric] = input[metric]; return acc; } @@ -382,7 +391,7 @@ export const TimeSync = ( const metrics = Object.keys(input); metrics.forEach(metric => { - let method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); if (metric === 'timestamp') { acc[metric] = inputs[0][metric]; @@ -391,23 +400,23 @@ export const TimeSync = ( } if (metric === 'duration') { - method = 'sum'; + aggregationParams.time = 'sum'; } - if (method === 'none') { + if (aggregationParams.time === 'none') { acc[metric] = null; return; } acc[metric] = acc[metric] ?? 0; - if (method === 'sum') { + if (aggregationParams.time === 'sum') { acc[metric] += input[metric]; return; } - if (method === 'copy') { + if (aggregationParams.time === 'copy') { acc[metric] = input[metric]; return; From 2930d4315aa0fdce36a7055d818c810786b3d397 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:01:26 +0400 Subject: [PATCH 716/863] feat(builtins): use granular aggregation methods in sci embodied --- src/if-run/builtins/sci-embodied/index.ts | 35 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 2b3c4ccfa..657f68e86 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -28,39 +28,60 @@ export const SciEmbodied = ( vCPUs: { description: 'number of CPUs allocated to an application', unit: 'CPUs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, memory: { description: 'RAM available for a resource, in GB', unit: 'GB', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, ssd: { description: 'number of SSDs available for a resource', unit: 'SSDs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, hdd: { description: 'number of HDDs available for a resource', unit: 'HDDs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, gpu: { description: 'number of GPUs available for a resource', unit: 'GPUs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, 'usage-ratio': { description: 'a scaling factor that can be used to describe the ratio of actual resource usage comapred to real device usage, e.g. 0.25 if you are using 2 out of 8 vCPUs, 0.1 if you are responsible for 1 out of 10 GB of storage, etc', unit: 'dimensionless', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, time: { description: 'a time unit to scale the embodied carbon by, in seconds. If not provided,time defaults to the value of the timestep duration.', unit: 'seconds', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, From 3a9c12f9636546d2617b78dd3e65fc3ad0e0ef4a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:04:58 +0400 Subject: [PATCH 717/863] feat(builtins): use granular aggregation methods in sci --- src/if-run/builtins/sci/index.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 407621b86..81fd62d07 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -40,13 +40,19 @@ export const Sci = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, 'functional-unit': { description: 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', unit: 'none', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, @@ -55,7 +61,10 @@ export const Sci = ( sci: { description: 'carbon expressed in terms of the given functional unit', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'avg', + component: 'sum', + }, }, }, }; From 1fa4dec8ec045b8e491181a686114c4d8bcad1ec Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:07:37 +0400 Subject: [PATCH 718/863] feat(src): simplify if-run index --- src/if-run/index.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 5607df6b6..6b26b150a 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -1,13 +1,11 @@ #!/usr/bin/env node -import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; - import {STRINGS as COMMON_STRINGS} from '../common/config'; import {validateManifest} from '../common/util/validations'; import {debugLogger} from '../common/util/debug-logger'; import {logger} from '../common/util/logger'; import {load} from '../common/lib/load'; -import {aggregate, storeAggregationMetrics} from './lib/aggregate'; +import {aggregate} from './lib/aggregate'; import {injectEnvironment} from './lib/environment'; import {initialize} from './lib/initialize'; import {compute} from './lib/compute'; @@ -44,16 +42,6 @@ const impactEngine = async () => { try { const {tree, ...context} = validateManifest(envManifest); - if (context.aggregation) { - const convertMetrics = context.aggregation?.metrics.map( - (metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], - }) - ); - - storeAggregationMetrics(...convertMetrics); - } - const pluginStorage = await initialize(context); const computedTree = await compute(tree, { context, @@ -69,6 +57,7 @@ const impactEngine = async () => { await exhaust(aggregatedTree, context, outputOptions); } catch (error) { if (error instanceof Error) { + /** Execution block exists because manifest is already processed. Set's status to `fail`. */ envManifest.execution!.status = 'fail'; envManifest.execution!.error = error.toString(); logger.error(error); From 6938764e9e8392c444cf561b0b929eaae0fbfde3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:11:22 +0400 Subject: [PATCH 719/863] feat(util): introduce granular aggregation to validation --- src/common/util/validations.ts | 51 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 646aee3fc..5d0ac758b 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -1,4 +1,5 @@ import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../if-run/config'; @@ -22,32 +23,35 @@ export const allDefined = (obj: Record) => Object.values(obj).every(v => v !== undefined); /** - * Schema for parameter metadata. + * Reusabe aggregation method schema for parameter metadata. + */ +const aggregationMethodSchema = z.object({ + time: z.enum(AGGREGATION_METHODS), + component: z.enum(AGGREGATION_METHODS), +}); + +/** + * Reusable metadata schema. + */ +const metadataSchema = z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': aggregationMethodSchema, + }) + ) + .optional() + .nullable(); + +/** + * Reusable parameter metadata schema. */ const parameterMetadataSchema = z .object({ - inputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - outputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), + inputs: metadataSchema, + outputs: metadataSchema, }) .optional(); @@ -71,6 +75,7 @@ export const manifestSchema = z.object({ .object({ metrics: z.array(z.string()), type: z.enum(AGGREGATION_TYPES), + 'skip-components': z.array(z.string()).optional(), }) .optional() .nullable(), From 2d53237f628b686943b6e7fe7ed42e1d519a1528 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:17:54 +0400 Subject: [PATCH 720/863] feat(types): enable time and component aggregations in manifest --- src/common/types/manifest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 488d8eeb5..483af708c 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -1,5 +1,5 @@ import {z} from 'zod'; -import {AggregationMethodTypes} from '@grnsft/if-core/types'; +import {AggregationOptions} from '@grnsft/if-core/types'; import {manifestSchema} from '../util/validations'; @@ -11,7 +11,7 @@ export type PluginOptions = GlobalPlugins[string]; export type AggregationParams = Manifest['aggregation']; export type AggregationMetricsWithMethod = { - [key: string]: AggregationMethodTypes; + [key: string]: AggregationOptions; }; export type AggregationParamsSure = Extract; From c9aeaf9ae537eaae534e7942af48147c12b0e6d3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:19:06 +0400 Subject: [PATCH 721/863] test(util): tune aggregation helper units --- .../if-run/util/aggregation-helper.test.ts | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index d76fcbb94..32a749a47 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -5,7 +5,6 @@ import {PluginParams} from '@grnsft/if-core/types'; import {AggregationParams} from '../../../common/types/manifest'; import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; -import {AggregationMetric} from '../../../if-run/types/aggregation'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -20,16 +19,24 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); }); describe('aggregateInputsIntoOne(): ', () => { it('throws error if aggregation criteria is not found in input.', () => { const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; - const metrics: AggregationMetric[] = [{'cpu/utilization': 'sum'}]; + const metrics: string[] = ['cpu/utilization']; const isTemporal = false; expect.assertions(2); @@ -46,12 +53,17 @@ describe('util/aggregation-helper: ', () => { }); it('passes `timestamp`, `duration` to aggregator if aggregation is temporal.', () => { - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric[] = [{carbon: 'sum'}]; + const metrics: string[] = ['carbon']; const isTemporal = true; const expectedValue = { @@ -68,7 +80,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric[] = [{carbon: 'sum'}]; + const metrics: string[] = ['carbon']; const isTemporal = false; const expectedValue = { @@ -84,16 +96,24 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); - storeAggregationMetrics({'cpu/utilization': 'avg'}); + storeAggregationMetrics({ + 'cpu/utilization': { + time: 'avg', + component: 'avg', + }, + }); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, 'cpu/utilization': 10}, {timestamp: '', duration: 10, 'cpu/utilization': 90}, ]; - const metrics: AggregationMetric[] = [{'cpu/utilization': 'avg'}]; + const metrics: string[] = ['cpu/utilization']; const isTemporal = false; const expectedValue = { From a650544f7e06e31a25ecd07b335c1f31747611aa Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:19:43 +0400 Subject: [PATCH 722/863] test(lib): tune explain units --- src/__tests__/if-run/lib/explain.test.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 8178bf07d..df86448ac 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -214,19 +214,28 @@ describe('lib/explain: ', () => { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', - 'aggregation-method': 'avg', + 'aggregation-method': { + time: 'avg', + component: 'avg', + }, }, 'memory/energy': { unit: 'kWh', description: 'energy consumed by data from memory', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, outputs: { 'total/energy': { unit: 'kWh', description: 'sum of energy components', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, }, From 0113ed5db8b7c7be4be370f360b3213c652f1cfa Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:20:22 +0400 Subject: [PATCH 723/863] test(lib): tune aggregate units --- src/__tests__/if-run/lib/aggregate.test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index d053fea9f..f39efdfcd 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -15,7 +15,10 @@ describe('lib/aggregate: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); @@ -23,7 +26,12 @@ describe('lib/aggregate: ', () => { describe('aggregate(): ', () => { beforeAll(() => { - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); }); it('returns tree if aggregation is missing.', () => { From 79ead4c26c7b3789ded1bdd2ab5ce5843ae5d6ee Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:20:45 +0400 Subject: [PATCH 724/863] test(builtins): tune time-sync units --- .../if-run/builtins/time-sync.test.ts | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index f3b268034..41e47548b 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -66,7 +66,10 @@ describe('builtins/time-sync:', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); }); @@ -483,7 +486,12 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); @@ -598,8 +606,18 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({'time-reserved': 'avg'}); - storeAggregationMetrics({'resources-total': 'sum'}); + storeAggregationMetrics({ + 'time-reserved': { + time: 'avg', + component: 'avg', + }, + }); + storeAggregationMetrics({ + 'resources-total': { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); @@ -647,8 +665,18 @@ describe('builtins/time-sync:', () => { 'time-reserved': 'time-allocated', }; - storeAggregationMetrics({'time-allocated': 'avg'}); - storeAggregationMetrics({'resources-total': 'sum'}); + storeAggregationMetrics({ + 'time-allocated': { + time: 'avg', + component: 'avg', + }, + }); + storeAggregationMetrics({ + 'resources-total': { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, mapping); @@ -722,7 +750,12 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({'resources-total': 'none'}); + storeAggregationMetrics({ + 'resources-total': { + time: 'none', + component: 'none', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); From bfb7b29f8ae7fbdd64c68c83702b579c02ae1692 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 10:18:50 +0400 Subject: [PATCH 725/863] feat(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca145548d..9f54932dc 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.20", + "@grnsft/if-core": "^0.0.22", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.20.tgz", - "integrity": "sha512-D5P97E0O9qIw9Ok0qCcy3zmNl8j1sr/vwfPsueFzkbmF6ZnLDBL1vapn8MzSRFsp3lJoH/mStDZ3uf3+S1L17g==", + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.22.tgz", + "integrity": "sha512-uzgYrQNh/aecouRdM5xcdCMC8Wu7xAWrGqJWqABopi/2CGs0xbvrQU0bqtGkSs1otAMnv5t7ynr6mpUyBxdQrw==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 802c9f138..eed57c1a2 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.20", + "@grnsft/if-core": "^0.0.22", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 922cbc496fab50d41a1152085b5efe83365f4fda Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 16:26:31 +0400 Subject: [PATCH 726/863] fix(builtins): fix output param of sci embodied --- src/if-run/builtins/sci-embodied/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 657f68e86..835284ea8 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -90,7 +90,10 @@ export const SciEmbodied = ( 'embodied-carbon': { description: 'embodied carbon for a resource, scaled by usage', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, }; From b800ad9acff29c3e2a3781d3fe8c5e5569523225 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 11 Sep 2024 18:57:40 +0400 Subject: [PATCH 727/863] fix(manifests): rename `carbon-embodied` to `embodied-carbon` --- manifests/examples/pipelines/nesting.yml | 4 +- .../pipeline-with-aggregate.yaml | 56 ++++----- .../outputs-if-diff/pipeline-with-mocks.yaml | 58 +++++----- .../examples/pipelines/pipeline-teads-sci.yml | 4 +- .../pipelines/pipeline-with-aggregate.yml | 4 +- .../pipelines/pipeline-with-mocks.yml | 4 +- manifests/examples/pipelines/sci.yml | 4 +- .../outputs/builtins/coefficient/success.yaml | 43 +++---- manifests/outputs/pipelines/nesting.yaml | 108 +++++++++--------- .../outputs/pipelines/pipeline-teads-sci.yaml | 10 +- manifests/outputs/pipelines/sci.yaml | 12 +- 11 files changed, 154 insertions(+), 153 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index 631f4db90..de1c5e70f 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -136,7 +136,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: inputs: @@ -144,7 +144,7 @@ initialize: description: Operational carbon footprint unit: gCO2eq aggregation-method: sum - carbon-embodied: + embodied-carbon: description: Embodied carbon footprint unit: gCO2eq aggregation-method: sum diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml index b9771834f..7512e15fb 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -156,7 +156,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: inputs: @@ -164,7 +164,7 @@ initialize: description: Operational carbon footprint unit: gCO2eq aggregation-method: sum - carbon-embodied: + embodied-carbon: description: Embodied carbon footprint unit: gCO2eq aggregation-method: sum @@ -319,7 +319,7 @@ tree: cpu-energy-raw: 0.0000563888888888889 vcpu-ratio: 8 cpu-energy-kwh: 0.000007048611111111113 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.0056388888888888895 carbon: 0.005649016996448503 sci: 0.000403501214032036 @@ -342,7 +342,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0005589976298113692 @@ -365,7 +365,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0006170797001436077 @@ -388,7 +388,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 @@ -411,7 +411,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 @@ -434,7 +434,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 @@ -457,7 +457,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 @@ -480,7 +480,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0010402200659563674 @@ -503,7 +503,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0010402200659563674 @@ -526,7 +526,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -549,7 +549,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -572,7 +572,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -595,7 +595,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -671,7 +671,7 @@ tree: cpu-energy-raw: 0.00007191666666666668 vcpu-ratio: 8 cpu-energy-kwh: 0.000008989583333333334 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007191666666666666 carbon: 0.007201794774226282 sci: 0.00003273543079193765 @@ -694,7 +694,7 @@ tree: cpu-energy-raw: 0.00008565277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000010706597222222223 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.008565277777777778 carbon: 0.008575405885337391 sci: 0.00009235052491901808 @@ -717,7 +717,7 @@ tree: cpu-energy-raw: 0.00008505555555555556 vcpu-ratio: 8 cpu-energy-kwh: 0.000010631944444444445 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.008505555555555556 carbon: 0.00851568366311517 sci: 0.0001439849894729618 @@ -740,7 +740,7 @@ tree: cpu-energy-raw: 0.00007878472222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 @@ -763,7 +763,7 @@ tree: cpu-energy-raw: 0.00007878472222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 @@ -786,7 +786,7 @@ tree: cpu-energy-raw: 0.00007878472222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 @@ -809,7 +809,7 @@ tree: cpu-energy-raw: 0.00007878472222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 @@ -832,7 +832,7 @@ tree: cpu-energy-raw: 0.00007878472222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.000009848090277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.007878472222222222 carbon: 0.007888600329781836 sci: 0.0002629533443260612 @@ -855,7 +855,7 @@ tree: cpu-energy-raw: 0.00004727083333333333 vcpu-ratio: 8 cpu-energy-kwh: 0.000005908854166666666 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.004727083333333333 carbon: 0.0047331601978691015 sci: 0.00026295334432606117 @@ -878,7 +878,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -901,7 +901,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -924,7 +924,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -947,7 +947,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index 6b4f1c51d..6c820ea44 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -209,7 +209,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: inputs: @@ -217,7 +217,7 @@ initialize: unit: gCO2eq description: Operational carbon footprint aggregation-method: sum - carbon-embodied: + embodied-carbon: unit: gCO2eq description: Embodied carbon footprint aggregation-method: sum @@ -379,7 +379,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -402,7 +402,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -425,7 +425,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -448,7 +448,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -471,7 +471,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -494,7 +494,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -517,7 +517,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -540,7 +540,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -563,7 +563,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -586,7 +586,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -609,7 +609,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -632,7 +632,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: "*" carbon: "*" sci: "*" @@ -655,7 +655,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: 0.0000020256215119228817 + embodied-carbon: 0.0000020256215119228817 carbon-operational: "*" carbon: "*" sci: "*" @@ -733,7 +733,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -756,7 +756,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -779,7 +779,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -802,7 +802,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -825,7 +825,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -848,7 +848,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -871,7 +871,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -894,7 +894,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -917,7 +917,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -940,7 +940,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -963,7 +963,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -986,7 +986,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -1009,7 +1009,7 @@ tree: cpu-energy-raw: "*" vcpu-ratio: 8 cpu-energy-kwh: "*" - carbon-embodied: "*" + embodied-carbon: "*" carbon-operational: "*" carbon: "*" sci: "*" @@ -1056,4 +1056,4 @@ tree: timestamp: "2023-12-12T00:01:00.000Z" duration: 1 aggregated: - carbon: "*" + carbon: "*" \ No newline at end of file diff --git a/manifests/examples/pipelines/pipeline-teads-sci.yml b/manifests/examples/pipelines/pipeline-teads-sci.yml index 28243d38f..2a20ce1b7 100644 --- a/manifests/examples/pipelines/pipeline-teads-sci.yml +++ b/manifests/examples/pipelines/pipeline-teads-sci.yml @@ -65,7 +65,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon "time-sync": method: TimeSync @@ -123,4 +123,4 @@ tree: cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 - network/energy: 0.000001 + network/energy: 0.000001 \ No newline at end of file diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index 7cf805d92..1f436d0fa 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -142,7 +142,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: outputs: @@ -259,4 +259,4 @@ tree: cpu/utilization: 33 cloud/instance-type: A1 cloud/region: uk-west - requests: 180 + requests: 180 \ No newline at end of file diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 3e3ce92d8..804e3cdfe 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -196,7 +196,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: inputs: @@ -204,7 +204,7 @@ initialize: description: Operational carbon footprint unit: gCO2eq aggregation-method: sum - carbon-embodied: + embodied-carbon: description: Embodied carbon footprint unit: gCO2eq aggregation-method: sum diff --git a/manifests/examples/pipelines/sci.yml b/manifests/examples/pipelines/sci.yml index 37a338286..4fca75ca7 100644 --- a/manifests/examples/pipelines/sci.yml +++ b/manifests/examples/pipelines/sci.yml @@ -68,7 +68,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon "sci": path: "builtin" @@ -126,4 +126,4 @@ tree: cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 - network/energy: 0.000001 + network/energy: 0.000001 \ No newline at end of file diff --git a/manifests/outputs/builtins/coefficient/success.yaml b/manifests/outputs/builtins/coefficient/success.yaml index 4ea679a9a..d34222918 100644 --- a/manifests/outputs/builtins/coefficient/success.yaml +++ b/manifests/outputs/builtins/coefficient/success.yaml @@ -12,27 +12,27 @@ initialize: output-parameter: carbon-product execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/coefficient/success.yml -o - manifests/outputs/plugins/coefficient/success + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/coefficient/success.yml -o + manifests/outputs/builtins/coefficient/success.yaml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T05:37:08.297Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-11T11:37:21.738Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -52,13 +52,14 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: child: pipeline: - - coefficient + compute: + - coefficient inputs: - timestamp: 2023-08-06T00:00 duration: 3600 @@ -67,4 +68,4 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 carbon: 30 - carbon-product: 90 + carbon-product: 90 \ No newline at end of file diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index f32120275..3a390abac 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -150,7 +150,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon parameter-metadata: inputs: @@ -158,7 +158,7 @@ initialize: description: Operational carbon footprint unit: gCO2eq aggregation-method: sum - carbon-embodied: + embodied-carbon: description: Embodied carbon footprint unit: gCO2eq aggregation-method: sum @@ -319,7 +319,7 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00006983123919278518 @@ -343,7 +343,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0001028924208718729 @@ -367,7 +367,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0001544881286073813 @@ -391,7 +391,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 @@ -415,7 +415,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 @@ -439,7 +439,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 @@ -463,7 +463,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 @@ -487,7 +487,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0005673927632489277 @@ -511,7 +511,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0005673927632489276 @@ -535,7 +535,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -559,7 +559,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -583,7 +583,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -607,7 +607,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -685,7 +685,7 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.0000834568468401579 @@ -709,7 +709,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.00015224732194049487 @@ -733,7 +733,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.000363108733129716 @@ -757,7 +757,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 @@ -781,7 +781,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 @@ -805,7 +805,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 @@ -829,7 +829,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 @@ -853,7 +853,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0014184819081223194 @@ -877,7 +877,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0014184819081223194 @@ -901,7 +901,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -925,7 +925,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -949,7 +949,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -973,7 +973,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1053,7 +1053,7 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00006709275922444067 @@ -1077,7 +1077,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.0000911261343001502 @@ -1101,7 +1101,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.00014075142645028166 @@ -1125,7 +1125,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1149,7 +1149,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1173,7 +1173,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1197,7 +1197,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1221,7 +1221,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1245,7 +1245,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0007801650494672755 @@ -1269,7 +1269,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1293,7 +1293,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1317,7 +1317,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1341,7 +1341,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1419,7 +1419,7 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.006833333333333334 carbon: 0.0068434614408929475 sci: 0.00007603846045436609 @@ -1443,7 +1443,7 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005340277777777777 carbon: 0.005350405885337391 sci: 0.00012081561676568304 @@ -1467,7 +1467,7 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.005190972222222222 carbon: 0.0052011003297818366 sci: 0.0001832602465191587 @@ -1491,7 +1491,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1515,7 +1515,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1539,7 +1539,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1563,7 +1563,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1587,7 +1587,7 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - carbon-embodied: 0.000010128107559614409 + embodied-carbon: 0.000010128107559614409 carbon-operational: 0.005190972222222222 carbon: 0.005201100329781837 sci: 0.0007801650494672756 @@ -1611,7 +1611,7 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - carbon-embodied: 0.000006076864535768645 + embodied-carbon: 0.000006076864535768645 carbon-operational: 0.0031145833333333334 carbon: 0.003120660197869102 sci: 0.0007801650494672755 @@ -1635,7 +1635,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1659,7 +1659,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1683,7 +1683,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 @@ -1707,7 +1707,7 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 - carbon-embodied: 0 + embodied-carbon: 0 carbon-operational: 0 carbon: 0 sci: 0 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index abefd4adf..c014d9f6d 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -81,7 +81,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon execution: command: >- @@ -197,7 +197,7 @@ tree: cpu-energy-raw: 0.000020833333333333333 vcpu-ratio: 8 cpu-energy-kwh: 0.0000026041666666666666 - carbon-embodied: 0.0000020256215119228817 + embodied-carbon: 0.0000020256215119228817 carbon-operational: 0.0020833333333333333 carbon: 0.002085358954845256 sci: 0.002085358954845256 @@ -221,7 +221,7 @@ tree: cpu-energy-raw: 0.000059375 vcpu-ratio: 8 cpu-energy-kwh: 0.000007421875 - carbon-embodied: 0.000010128107559614407 + embodied-carbon: 0.000010128107559614407 carbon-operational: 0.0059375 carbon: 0.005947628107559615 sci: 0.005947628107559615 @@ -245,7 +245,7 @@ tree: cpu-energy-raw: 0.00007267361111111111 vcpu-ratio: 8 cpu-energy-kwh: 0.000009084201388888889 - carbon-embodied: 0.00001417935058346017 + embodied-carbon: 0.00001417935058346017 carbon-operational: 0.007267361111111111 carbon: 0.007281540461694571 sci: 0.007281540461694571 @@ -269,7 +269,7 @@ tree: cpu-energy-raw: 0.00031145833333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.00003893229166666667 - carbon-embodied: 0.00006076864535768645 + embodied-carbon: 0.00006076864535768645 carbon-operational: 0.031145833333333334 carbon: 0.03120660197869102 sci: 0.03120660197869102 diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml index 99eed0ff6..322a413b8 100644 --- a/manifests/outputs/pipelines/sci.yaml +++ b/manifests/outputs/pipelines/sci.yaml @@ -84,7 +84,7 @@ initialize: config: input-parameters: - carbon-operational - - carbon-embodied + - embodied-carbon output-parameter: carbon sci: path: builtin @@ -210,7 +210,7 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000005208333333333333 energy: 0.000006208333333333333 - carbon-embodied: 0.000004051243023845763 + embodied-carbon: 0.000004051243023845763 carbon-operational: 0.004966666666666666 carbon: 0.004970717909690512 sci: 0.004970717909690512 @@ -237,7 +237,7 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00001484375 energy: 0.00001584375 - carbon-embodied: 0.000020256215119228814 + embodied-carbon: 0.000020256215119228814 carbon-operational: 0.012674999999999999 carbon: 0.012695256215119228 sci: 0.012695256215119228 @@ -264,7 +264,7 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000018168402777777778 energy: 0.000019168402777777778 - carbon-embodied: 0.00002835870116692034 + embodied-carbon: 0.00002835870116692034 carbon-operational: 0.015334722222222222 carbon: 0.015363080923389142 sci: 0.015363080923389142 @@ -291,7 +291,7 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00007786458333333334 energy: 0.00007886458333333333 - carbon-embodied: 0.0001215372907153729 + embodied-carbon: 0.0001215372907153729 carbon-operational: 0.06309166666666667 carbon: 0.06321320395738204 - sci: 0.06321320395738204 + sci: 0.06321320395738204 \ No newline at end of file From 5d5311c849d0cb99934153e8f318f17967112df4 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 11 Sep 2024 18:58:26 +0400 Subject: [PATCH 728/863] fix(manifests): fix sci-embodied success manifest --- manifests/examples/builtins/sci-embodied/success.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/manifests/examples/builtins/sci-embodied/success.yml b/manifests/examples/builtins/sci-embodied/success.yml index c37677931..cff80fe05 100644 --- a/manifests/examples/builtins/sci-embodied/success.yml +++ b/manifests/examples/builtins/sci-embodied/success.yml @@ -12,7 +12,7 @@ initialize: query: instance-class: cloud/instance-type output: ["cpu-cores-utilized", "vcpus-allocated"] - "sci-embodied-new": # a model that calculates m from te, tir, el, rr and rtor + "sci-embodied": # a model that calculates m from te, tir, el, rr and rtor method: SciEmbodied path: "builtin" tree: @@ -31,3 +31,6 @@ tree: inputs: - timestamp: 2023-07-06T00:00 duration: 3600 + cloud/vendor: intel + cloud/instance-type: Standard_A1_v2 + cpu/utilization: 10 From fb1c73b9846edb8348d0fa9b52b9b330ca653f3b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 11 Sep 2024 18:59:23 +0400 Subject: [PATCH 729/863] fix(mocks): rename `carbon-embodied` to `embodied-carbon` --- src/__mocks__/builtins/export-yaml.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/__mocks__/builtins/export-yaml.ts b/src/__mocks__/builtins/export-yaml.ts index 5ebf9cb1b..5d23a8705 100644 --- a/src/__mocks__/builtins/export-yaml.ts +++ b/src/__mocks__/builtins/export-yaml.ts @@ -43,8 +43,8 @@ export const tree = { 'resources-reserved': 1, 'resources-total': 8, 'cpu/energy': 0.000008888888888888888, - "carbon-plus-energy'": 10.000008888888889, - 'carbon-embodied': 0.0000020256215119228817, + 'carbon-plus-energy': 10.000008888888889, + 'embodied-carbon': 0.0000020256215119228817, 'carbon-operational': 4000, carbon: 4000.0000020256216, sci: 240000.0001215373, @@ -92,7 +92,7 @@ export const tree = { 'resources-total': 8, 'cpu/energy': 0.00001650338753387534, "carbon-plus-energy'": 10.000016503387533, - 'carbon-embodied': 0.0000020256215119228817, + 'embodied-carbon': 0.0000020256215119228817, 'carbon-operational': 4000, carbon: 4000.0000020256216, sci: 240000.0001215373, From ed44b194fa4406664bff3d60518a5d877307a21f Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 11 Sep 2024 19:00:02 +0400 Subject: [PATCH 730/863] docs(builtins): rename `carbon-embodied` to `embodied-carbon` --- src/if-run/builtins/sci-embodied/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/README.md b/src/if-run/builtins/sci-embodied/README.md index a40072278..80baeab06 100644 --- a/src/if-run/builtins/sci-embodied/README.md +++ b/src/if-run/builtins/sci-embodied/README.md @@ -22,7 +22,7 @@ The `parameter-metadata` section contains information about the `description`, ` - `unit`: The unit of measurement for the parameter. - `aggregation-method`: The method used to aggregate this parameter (`sum`, `avg`, or `none`). -- `outputs`: Describes the `carbon-embodied` parameter, which includes: +- `outputs`: Describes the `embodied-carbon` parameter, which includes: - `description`: A brief description of the parameter. - `unit`: The unit of measurement for the parameter. - `aggregation-method`: The method used to aggregate this parameter (`sum`, `avg`, or `none`). @@ -70,7 +70,7 @@ Note that if you do not provide any inputs at all, we fall back to defaults that ### Outputs -- `carbon-embodied`: The total embodied emissions for the component, measured in gCO2e, per timestep. +- `embodied-carbon`: The total embodied emissions for the component, measured in gCO2e, per timestep. ## Calculation @@ -123,7 +123,7 @@ tree: child: pipeline: compute: - - sci-embodied + - sci-embodied inputs: - timestamp: 2024-08-19T00:00 duration: 3600 From d0d982b416b9211c01564c60d3a9f36fc959d4ae Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:08:33 +0400 Subject: [PATCH 731/863] fix(manifests): fix `aggregation-method` of manifests --- manifests/examples/pipelines/nesting.yml | 84 +- .../pipeline-with-aggregate.yaml | 88 +- .../outputs-if-diff/pipeline-with-mocks.yaml | 120 ++- .../pipelines/pipeline-with-aggregate.yml | 60 +- .../pipelines/pipeline-with-mocks.yml | 112 ++- .../features/aggregate-horizontal.yaml | 4 +- .../outputs/features/aggregate-vertical.yaml | 4 +- manifests/outputs/features/aggregate.yaml | 4 +- manifests/outputs/pipelines/nesting.yaml | 864 ++++++++---------- 9 files changed, 759 insertions(+), 581 deletions(-) diff --git a/manifests/examples/pipelines/nesting.yml b/manifests/examples/pipelines/nesting.yml index de1c5e70f..f62105c87 100644 --- a/manifests/examples/pipelines/nesting.yml +++ b/manifests/examples/pipelines/nesting.yml @@ -24,12 +24,16 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: sum outputs: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg "cpu-factor-to-wattage": method: Multiply path: builtin @@ -41,16 +45,22 @@ initialize: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: unit: kWh description: thermal design power for a processor - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: unit: kWh description: the energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum "wattage-times-duration": method: Multiply path: builtin @@ -69,12 +79,16 @@ initialize: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum "calculate-vcpu-ratio": method: Divide path: "builtin" @@ -87,7 +101,9 @@ initialize: vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: copy + component: copy "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -109,16 +125,22 @@ initialize: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: unit: gCO2eq/kWh description: Carbon intensity for the grid - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci: path: "builtin" method: Sci @@ -129,7 +151,9 @@ initialize: requests: unit: none description: expressed the final SCI value - aggregation-method: sum + aggregation-method: + time: sum + component: sum "sum-carbon": path: "builtin" method: Sum @@ -143,16 +167,22 @@ initialize: carbon-operational: description: Operational carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum embodied-carbon: description: Embodied carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: carbon: description: Total carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum time-sync: method: TimeSync path: "builtin" @@ -166,27 +196,39 @@ initialize: timestamp: unit: RFC3339 description: refers to the time of occurrence of the input - aggregation-method: none + aggregation-method: + time: none + component: none duration: unit: seconds description: refers to the duration of the input - aggregation-method: sum + aggregation-method: + time: sum + component: sum cloud/instance-type: unit: none description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none + aggregation-method: + time: copy + component: copy cloud/region: unit: none description: region cloud instance - aggregation-method: none + aggregation-method: + time: copy + component: copy time-reserved: unit: seconds description: time reserved for a component - aggregation-method: avg + aggregation-method: + time: avg + component: avg network/energy: description: "Energy consumed by the Network of the component" unit: "kWh" - aggregation-method: "sum" + aggregation-method: + time: sum + component: sum tree: children: child-0: diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml index 7512e15fb..6a96cbfc8 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -29,12 +29,16 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -48,16 +52,22 @@ initialize: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: unit: kWh description: thermal design power for a processor - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: unit: kWh description: the energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-times-duration: path: builtin method: Multiply @@ -78,12 +88,16 @@ initialize: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -96,16 +110,22 @@ initialize: vcpus-total: unit: count description: total number of vcpus available on a particular resource - aggregation-method: none + aggregation-method: + time: none + component: none vcpus-allocated: unit: count description: number of vcpus allocated to particular resource - aggregation-method: none + aggregation-method: + time: none + component: none outputs: vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: none + component: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -129,16 +149,22 @@ initialize: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: unit: gCO2eq/kWh description: Carbon intensity for the grid - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci: path: builtin method: Sci @@ -149,7 +175,9 @@ initialize: requests: unit: none description: expressed the final SCI value - aggregation-method: sum + aggregation-method: + time: sum + component: sum sum-carbon: path: builtin method: Sum @@ -163,16 +191,22 @@ initialize: carbon-operational: description: Operational carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum embodied-carbon: description: Embodied carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: carbon: description: Total carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum time-sync: path: builtin method: TimeSync @@ -186,23 +220,33 @@ initialize: timestamp: unit: RFC3339 description: refers to the time of occurrence of the input - aggregation-method: none + aggregation-method: + time: none + component: none duration: unit: seconds description: refers to the duration of the input - aggregation-method: sum + aggregation-method: + time: sum + component: sum cloud/instance-type: unit: none description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none + aggregation-method: + time: none + component: none cloud/region: unit: none description: region cloud instance - aggregation-method: none + aggregation-method: + time: none + component: none time-reserved: unit: seconds description: time reserved for a component - aggregation-method: avg + aggregation-method: + time: avg + component: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml index 6c820ea44..3a744410c 100644 --- a/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ b/manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -28,19 +28,27 @@ initialize: timestamp: unit: RFC3339 description: refers to the time of occurrence of the input - aggregation-method: none + aggregation-method: + time: none + component: none duration: unit: seconds description: refers to the duration of the input - aggregation-method: sum + aggregation-method: + time: sum + component: sum cloud/instance-type: unit: none description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none + aggregation-method: + time: none + component: none cloud/region: unit: none description: region cloud instance - aggregation-method: none + aggregation-method: + time: none + component: none interpolate: path: builtin method: Interpolation @@ -63,12 +71,16 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -82,16 +94,22 @@ initialize: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: unit: kWh description: thermal design power for a processor - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: unit: kWh description: the energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-times-duration: path: builtin method: Multiply @@ -105,16 +123,22 @@ initialize: cpu-wattage: unit: kWh description: Energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum duration: unit: seconds description: Duration of the observation - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-to-energy-kwh: path: builtin method: Divide @@ -127,12 +151,16 @@ initialize: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -145,16 +173,22 @@ initialize: vcpus-total: unit: count description: total number of vcpus available on a particular resource - aggregation-method: none + aggregation-method: + time: none + component: none vcpus-allocated: unit: count description: number of vcpus allocated to particular resource - aggregation-method: none + aggregation-method: + time: none + component: none outputs: vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: none + component: none correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -167,16 +201,22 @@ initialize: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: none + component: none outputs: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci-embodied: path: builtin method: SciEmbodied @@ -193,16 +233,22 @@ initialize: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: unit: gCO2eq/kWh description: Carbon intensity for the grid - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum sum-carbon: path: builtin method: Sum @@ -216,16 +262,22 @@ initialize: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum embodied-carbon: unit: gCO2eq description: Embodied carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: carbon: unit: gCO2eq description: Total carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci: path: builtin method: Sci @@ -236,12 +288,16 @@ initialize: requests: unit: none description: expressed the final SCI value - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: sci: unit: none description: Scientific Carbon Intensity - aggregation-method: none + aggregation-method: + time: none + component: none time-sync: path: builtin method: TimeSync @@ -255,12 +311,16 @@ initialize: time-reserved: unit: seconds description: time reserved for a component - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: synced-time: unit: none description: Synced time - aggregation-method: none + aggregation-method: + time: none + component: none execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/examples/pipelines/pipeline-with-aggregate.yml b/manifests/examples/pipelines/pipeline-with-aggregate.yml index 1f436d0fa..c95047f49 100644 --- a/manifests/examples/pipelines/pipeline-with-aggregate.yml +++ b/manifests/examples/pipelines/pipeline-with-aggregate.yml @@ -21,12 +21,16 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg "cpu-factor-to-wattage": method: Multiply path: builtin @@ -38,16 +42,22 @@ initialize: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: unit: kWh description: thermal design power for a processor - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: unit: kWh description: the energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum "wattage-times-duration": method: Multiply path: builtin @@ -66,12 +76,16 @@ initialize: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum "calculate-vcpu-ratio": method: Divide path: "builtin" @@ -84,16 +98,22 @@ initialize: vcpus-total: unit: count description: total number of vcpus available on a particular resource - aggregation-method: none + aggregation-method: + time: copy + component: copy vcpus-allocated: unit: count description: number of vcpus allocated to particular resource - aggregation-method: none + aggregation-method: + time: copy + component: copy outputs: vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: copy + component: copy "correct-cpu-energy-for-vcpu-ratio": method: Divide path: "builtin" @@ -115,16 +135,22 @@ initialize: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: unit: gCO2eq/kWh description: Carbon intensity for the grid - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum "sci": path: "builtin" method: Sci @@ -135,7 +161,9 @@ initialize: requests: unit: none description: expressed the final SCI value - aggregation-method: sum + aggregation-method: + time: sum + component: sum "sum-carbon": path: "builtin" method: Sum @@ -149,7 +177,9 @@ initialize: carbon: unit: gCO2eq description: product of carbon - aggregation-method: sum + aggregation-method: + time: sum + component: sum "time-sync": method: TimeSync path: "builtin" diff --git a/manifests/examples/pipelines/pipeline-with-mocks.yml b/manifests/examples/pipelines/pipeline-with-mocks.yml index 804e3cdfe..0358525c2 100644 --- a/manifests/examples/pipelines/pipeline-with-mocks.yml +++ b/manifests/examples/pipelines/pipeline-with-mocks.yml @@ -29,19 +29,27 @@ initialize: timestamp: description: refers to the time of occurrence of the input unit: RFC3339 - aggregation-method: none + aggregation-method: + time: none + component: none duration: description: refers to the duration of the input unit: seconds - aggregation-method: sum + aggregation-method: + time: sum + component: sum cloud/instance-type: description: type of Cloud Instance name used in the cloud provider APIs unit: none - aggregation-method: none + aggregation-method: + time: none + component: none cloud/region: description: region cloud instance unit: none - aggregation-method: none + aggregation-method: + time: none + component: none interpolate: method: Interpolation path: "builtin" @@ -56,12 +64,16 @@ initialize: cpu/utilization: description: refers to CPU utilization. unit: percentage - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-factor: description: result of interpolate unit: kWh - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu-factor-to-wattage: method: Multiply path: builtin @@ -73,16 +85,22 @@ initialize: cpu-factor: description: result of interpolate unit: kWh - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: description: thermal design power for a processor unit: kWh - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: description: the energy used by the CPU unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-times-duration: method: Multiply path: builtin @@ -94,16 +112,22 @@ initialize: cpu-wattage: description: Energy used by the CPU unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum duration: description: Duration of the observation unit: seconds - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-wattage-times-duration: description: CPU wattage multiplied by duration unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-to-energy-kwh: method: Divide path: "builtin" @@ -116,12 +140,16 @@ initialize: cpu-wattage-times-duration: description: CPU wattage multiplied by duration unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: description: Raw energy used by CPU in kWh unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum calculate-vcpu-ratio: method: Divide path: "builtin" @@ -134,16 +162,22 @@ initialize: vcpus-total: description: total number of vcpus available on a particular resource unit: count - aggregation-method: none + aggregation-method: + time: none + component: none vcpus-allocated: description: number of vcpus allocated to particular resource unit: count - aggregation-method: none + aggregation-method: + time: none + component: none outputs: vcpu-ratio: description: Ratio of vCPUs unit: none - aggregation-method: none + aggregation-method: + time: none + component: none correct-cpu-energy-for-vcpu-ratio: method: Divide path: "builtin" @@ -156,16 +190,22 @@ initialize: cpu-energy-raw: description: Raw energy used by CPU in kWh unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum vcpu-ratio: description: Ratio of vCPUs unit: none - aggregation-method: none + aggregation-method: + time: none + component: none outputs: cpu-energy-kwh: description: Corrected CPU energy in kWh unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci-embodied: path: "builtin" method: SciEmbodied @@ -180,16 +220,22 @@ initialize: cpu-energy-kwh: description: Corrected CPU energy in kWh unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: description: Carbon intensity for the grid unit: gCO2eq/kWh - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: description: Operational carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum sum-carbon: path: "builtin" method: Sum @@ -203,16 +249,22 @@ initialize: carbon-operational: description: Operational carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum embodied-carbon: description: Embodied carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: carbon: description: Total carbon footprint unit: gCO2eq - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci: path: "builtin" method: Sci @@ -223,12 +275,16 @@ initialize: requests: description: expressed the final SCI value unit: none - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: sci: description: Scientific Carbon Intensity unit: none - aggregation-method: none + aggregation-method: + time: none + component: none time-sync: method: TimeSync path: "builtin" diff --git a/manifests/outputs/features/aggregate-horizontal.yaml b/manifests/outputs/features/aggregate-horizontal.yaml index 888ae1441..f08a645e3 100644 --- a/manifests/outputs/features/aggregate-horizontal.yaml +++ b/manifests/outputs/features/aggregate-horizontal.yaml @@ -22,7 +22,9 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/features/aggregate-vertical.yaml b/manifests/outputs/features/aggregate-vertical.yaml index 3ba96d0b1..e559d715a 100644 --- a/manifests/outputs/features/aggregate-vertical.yaml +++ b/manifests/outputs/features/aggregate-vertical.yaml @@ -22,7 +22,9 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/features/aggregate.yaml b/manifests/outputs/features/aggregate.yaml index 96c72adf2..d00adde49 100644 --- a/manifests/outputs/features/aggregate.yaml +++ b/manifests/outputs/features/aggregate.yaml @@ -22,7 +22,9 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: avg execution: command: >- /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 3a390abac..0a834b082 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -20,7 +20,7 @@ initialize: - 10 - 50 - 100 - "y": + 'y': - 0.12 - 0.32 - 0.75 @@ -32,12 +32,16 @@ initialize: cpu/utilization: unit: percentage description: refers to CPU utilization. - aggregation-method: avg + aggregation-method: + time: avg + component: sum outputs: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu-factor-to-wattage: path: builtin method: Multiply @@ -51,16 +55,22 @@ initialize: cpu-factor: unit: kWh description: result of interpolate - aggregation-method: avg + aggregation-method: + time: avg + component: avg cpu/thermal-design-power: unit: kWh description: thermal design power for a processor - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: cpu-wattage: unit: kWh description: the energy used by the CPU - aggregation-method: sum + aggregation-method: + time: sum + component: sum wattage-times-duration: path: builtin method: Multiply @@ -81,12 +91,16 @@ initialize: cpu-wattage-times-duration: unit: kWh description: CPU wattage multiplied by duration - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: cpu-energy-raw: unit: kWh description: Raw energy used by CPU in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum calculate-vcpu-ratio: path: builtin method: Divide @@ -99,7 +113,9 @@ initialize: vcpu-ratio: unit: none description: Ratio of vCPUs - aggregation-method: none + aggregation-method: + time: copy + component: copy correct-cpu-energy-for-vcpu-ratio: path: builtin method: Divide @@ -123,16 +139,22 @@ initialize: cpu-energy-kwh: unit: kWh description: Corrected CPU energy in kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum grid/carbon-intensity: unit: gCO2eq/kWh description: Carbon intensity for the grid - aggregation-method: avg + aggregation-method: + time: avg + component: avg outputs: carbon-operational: unit: gCO2eq description: Operational carbon footprint - aggregation-method: sum + aggregation-method: + time: sum + component: sum sci: path: builtin method: Sci @@ -143,7 +165,9 @@ initialize: requests: unit: none description: expressed the final SCI value - aggregation-method: sum + aggregation-method: + time: sum + component: sum sum-carbon: path: builtin method: Sum @@ -155,24 +179,30 @@ initialize: parameter-metadata: inputs: carbon-operational: - description: Operational carbon footprint unit: gCO2eq - aggregation-method: sum + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum embodied-carbon: - description: Embodied carbon footprint unit: gCO2eq - aggregation-method: sum + description: Embodied carbon footprint + aggregation-method: + time: sum + component: sum outputs: carbon: - description: Total carbon footprint unit: gCO2eq - aggregation-method: sum + description: Total carbon footprint + aggregation-method: + time: sum + component: sum time-sync: path: builtin method: TimeSync config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true parameter-metadata: @@ -180,50 +210,62 @@ initialize: timestamp: unit: RFC3339 description: refers to the time of occurrence of the input - aggregation-method: none + aggregation-method: + time: none + component: none duration: unit: seconds description: refers to the duration of the input - aggregation-method: sum + aggregation-method: + time: sum + component: sum cloud/instance-type: unit: none description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: none + aggregation-method: + time: copy + component: copy cloud/region: unit: none description: region cloud instance - aggregation-method: none + aggregation-method: + time: copy + component: copy time-reserved: unit: seconds description: time reserved for a component - aggregation-method: avg + aggregation-method: + time: avg + component: avg network/energy: unit: kWh description: Energy consumed by the Network of the component - aggregation-method: sum + aggregation-method: + time: sum + component: sum execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m manifests/examples/pipelines/nesting.yml -o - manifests/outputs/pipelines/nesting-1.yaml + manifests/outputs/pipelines/nesting.yaml environment: - if-version: 0.5.0 + if-version: 0.6.0 os: macOS - os-version: "14.5" - node-version: 18.14.2 - date-time: 2024-07-31T13:17:29.944Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T11:46:37.516Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.16" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -270,28 +312,28 @@ tree: - time-sync - sci inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 60 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 70 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -299,7 +341,7 @@ tree: network/energy: 0.000001 requests: 55 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -308,9 +350,9 @@ tree: requests: 98 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 170294400 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.4065 @@ -319,11 +361,11 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 - carbon: 0.0068434614408929475 - sci: 0.00006983123919278518 - - timestamp: "2023-12-12T00:00:05.000Z" + carbon: 0.04647057331303907 + sci: 0.0004741895236024395 + - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -332,9 +374,9 @@ tree: requests: 52 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.30975 @@ -343,11 +385,11 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.0001028924208718729 - - timestamp: "2023-12-12T00:00:10.000Z" + carbon: 0.044977517757483515 + sci: 0.0008649522645669907 + - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -356,9 +398,9 @@ tree: requests: 33.666666666666664 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -367,11 +409,11 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.0001544881286073813 - - timestamp: "2023-12-12T00:00:15.000Z" + carbon: 0.04482821220192795 + sci: 0.0013315310555028106 + - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -380,9 +422,9 @@ tree: requests: 9.166666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -391,11 +433,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0005673927632489277 - - timestamp: "2023-12-12T00:00:20.000Z" + carbon: 0.04482821220192795 + sci: 0.004890350422028504 + - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -404,9 +446,9 @@ tree: requests: 9.166666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -415,11 +457,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0005673927632489277 - - timestamp: "2023-12-12T00:00:25.000Z" + carbon: 0.04482821220192795 + sci: 0.004890350422028504 + - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -428,9 +470,9 @@ tree: requests: 9.166666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -439,11 +481,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0005673927632489277 - - timestamp: "2023-12-12T00:00:30.000Z" + carbon: 0.04482821220192795 + sci: 0.004890350422028504 + - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -452,9 +494,9 @@ tree: requests: 9.166666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -463,11 +505,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0005673927632489277 - - timestamp: "2023-12-12T00:00:35.000Z" + carbon: 0.04482821220192795 + sci: 0.004890350422028504 + - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -476,9 +518,9 @@ tree: requests: 9.166666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -487,11 +529,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0005673927632489277 - - timestamp: "2023-12-12T00:00:40.000Z" + carbon: 0.04482821220192795 + sci: 0.004890350422028504 + - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -500,9 +542,9 @@ tree: requests: 5.5 cpu/thermal-design-power: 60 grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 + device/emissions-embodied: 1533.12 time-reserved: 2160.2 - device/expected-lifespan: 9460800 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.22425 @@ -511,11 +553,11 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.000006076864535768645 + embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0005673927632489276 - - timestamp: "2023-12-12T00:00:45.000Z" + carbon: 0.02689692732115677 + sci: 0.004890350422028503 + - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -524,9 +566,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -539,7 +581,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:50.000Z" + - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -548,9 +590,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -563,7 +605,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:55.000Z" + - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -572,33 +614,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - network/energy: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -612,7 +630,7 @@ tree: carbon: 0 sci: 0 aggregated: - carbon: 0.04652112950279046 + carbon: 0.3873142916032471 child-1: defaults: cpu/thermal-design-power: 100 @@ -636,28 +654,28 @@ tree: - time-sync - sci inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 10 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 90 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 30 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -665,7 +683,7 @@ tree: network/energy: 0.000001 requests: 22 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -674,9 +692,9 @@ tree: requests: 82 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 170294400 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.4065 @@ -685,11 +703,11 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 - carbon: 0.0068434614408929475 - sci: 0.0000834568468401579 - - timestamp: "2023-12-12T00:00:05.000Z" + carbon: 0.04647057331303907 + sci: 0.0005667143086955984 + - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -698,9 +716,9 @@ tree: requests: 35.14285714285714 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.30975 @@ -709,11 +727,11 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.00015224732194049487 - - timestamp: "2023-12-12T00:00:10.000Z" + carbon: 0.044977517757483515 + sci: 0.0012798480662698562 + - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -722,9 +740,9 @@ tree: requests: 14.323809523809523 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -733,11 +751,11 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.000363108733129716 - - timestamp: "2023-12-12T00:00:15.000Z" + carbon: 0.04482821220192795 + sci: 0.0031296291763314066 + - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -746,9 +764,9 @@ tree: requests: 3.6666666666666665 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -757,11 +775,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:20.000Z" + carbon: 0.04482821220192795 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -770,9 +788,9 @@ tree: requests: 3.6666666666666665 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -781,11 +799,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:25.000Z" + carbon: 0.04482821220192795 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -794,9 +812,9 @@ tree: requests: 3.6666666666666665 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -805,11 +823,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:30.000Z" + carbon: 0.04482821220192795 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -818,9 +836,9 @@ tree: requests: 3.6666666666666665 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -829,11 +847,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:35.000Z" + carbon: 0.04482821220192795 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -842,9 +860,9 @@ tree: requests: 3.6666666666666665 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -853,11 +871,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:40.000Z" + carbon: 0.04482821220192795 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -866,9 +884,9 @@ tree: requests: 2.1999999999999997 cpu/thermal-design-power: 60 grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 + device/emissions-embodied: 1533.12 time-reserved: 2160.2 - device/expected-lifespan: 9460800 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.22425 @@ -877,11 +895,11 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.000006076864535768645 + embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0014184819081223194 - - timestamp: "2023-12-12T00:00:45.000Z" + carbon: 0.02689692732115677 + sci: 0.01222587605507126 + - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -890,9 +908,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -905,7 +923,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:50.000Z" + - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -914,9 +932,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -929,7 +947,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:55.000Z" + - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -938,33 +956,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - network/energy: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -978,7 +972,7 @@ tree: carbon: 0 sci: 0 aggregated: - carbon: 0.04652112950279046 + carbon: 0.3873142916032471 child-2: children: child-2-0: @@ -1004,28 +998,28 @@ tree: - time-sync - sci inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 65 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 80 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -1033,7 +1027,7 @@ tree: network/energy: 0.000001 requests: 40 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -1042,9 +1036,9 @@ tree: requests: 102 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 170294400 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.4065 @@ -1053,11 +1047,11 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 - carbon: 0.0068434614408929475 - sci: 0.00006709275922444067 - - timestamp: "2023-12-12T00:00:05.000Z" + carbon: 0.04647057331303907 + sci: 0.00045559385601018696 + - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -1066,9 +1060,9 @@ tree: requests: 58.71428571428572 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.30975 @@ -1077,11 +1071,11 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.0000911261343001502 - - timestamp: "2023-12-12T00:00:10.000Z" + carbon: 0.044977517757483515 + sci: 0.0007660404484242933 + - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -1090,9 +1084,9 @@ tree: requests: 36.952380952380956 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1101,11 +1095,11 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.00014075142645028166 - - timestamp: "2023-12-12T00:00:15.000Z" + carbon: 0.04482821220192795 + sci: 0.0012131346085573285 + - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1114,9 +1108,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1125,11 +1119,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:20.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1138,9 +1132,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1149,11 +1143,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:25.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1162,9 +1156,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1173,11 +1167,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:30.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1186,9 +1180,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1197,11 +1191,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:35.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1210,9 +1204,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1221,11 +1215,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:40.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1234,9 +1228,9 @@ tree: requests: 4 cpu/thermal-design-power: 60 grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 + device/emissions-embodied: 1533.12 time-reserved: 2160.2 - device/expected-lifespan: 9460800 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.22425 @@ -1245,11 +1239,11 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.000006076864535768645 + embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0007801650494672755 - - timestamp: "2023-12-12T00:00:45.000Z" + carbon: 0.02689692732115677 + sci: 0.006724231830289192 + - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1258,9 +1252,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1273,7 +1267,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:50.000Z" + - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1282,9 +1276,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1297,7 +1291,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:55.000Z" + - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1306,33 +1300,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - network/energy: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1346,7 +1316,7 @@ tree: carbon: 0 sci: 0 aggregated: - carbon: 0.04652112950279046 + carbon: 0.3873142916032471 child-2-1: defaults: cpu/thermal-design-power: 100 @@ -1370,28 +1340,28 @@ tree: - time-sync - sci inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 requests: 50 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 50 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 requests: 60 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -1399,7 +1369,7 @@ tree: network/energy: 0.000001 requests: 40 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 5 @@ -1408,9 +1378,9 @@ tree: requests: 90 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 2759.6159999999995 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 170294400 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.4065 @@ -1419,11 +1389,11 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 - carbon: 0.0068434614408929475 - sci: 0.00007603846045436609 - - timestamp: "2023-12-12T00:00:05.000Z" + carbon: 0.04647057331303907 + sci: 0.0005163397034782119 + - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 cpu/utilization: 13 cloud/instance-type: A1 @@ -1432,9 +1402,9 @@ tree: requests: 44.28571428571428 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 1182.6925714285712 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 72983314.28571428 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.30975 @@ -1443,11 +1413,11 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 - carbon: 0.005350405885337391 - sci: 0.00012081561676568304 - - timestamp: "2023-12-12T00:00:10.000Z" + carbon: 0.044977517757483515 + sci: 0.00101562136871737 + - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 cpu/utilization: 12 cloud/instance-type: A1 @@ -1456,9 +1426,9 @@ tree: requests: 28.38095238095238 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 759.2594285714285 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 46853485.71428572 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1467,11 +1437,11 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 - carbon: 0.0052011003297818366 - sci: 0.0001832602465191587 - - timestamp: "2023-12-12T00:00:15.000Z" + carbon: 0.04482821220192795 + sci: 0.0015795175440276629 + - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1480,9 +1450,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1491,11 +1461,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:20.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1504,9 +1474,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1515,11 +1485,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:25.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1528,9 +1498,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1539,11 +1509,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:30.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1552,9 +1522,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1563,11 +1533,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:35.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1576,9 +1546,9 @@ tree: requests: 6.666666666666666 cpu/thermal-design-power: 80 grid/carbon-intensity: 640 - device/emissions-embodied: 255.51999999999998 + device/emissions-embodied: 1533.12 time-reserved: 2880 - device/expected-lifespan: 15768000 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.29900000000000004 @@ -1587,11 +1557,11 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.000010128107559614409 + embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 - carbon: 0.005201100329781837 - sci: 0.0007801650494672756 - - timestamp: "2023-12-12T00:00:40.000Z" + carbon: 0.04482821220192795 + sci: 0.006724231830289193 + - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1600,9 +1570,9 @@ tree: requests: 4 cpu/thermal-design-power: 60 grid/carbon-intensity: 480 - device/emissions-embodied: 153.312 + device/emissions-embodied: 1533.12 time-reserved: 2160.2 - device/expected-lifespan: 9460800 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0.22425 @@ -1611,11 +1581,11 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.000006076864535768645 + embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 - carbon: 0.003120660197869102 - sci: 0.0007801650494672755 - - timestamp: "2023-12-12T00:00:45.000Z" + carbon: 0.02689692732115677 + sci: 0.006724231830289192 + - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1624,9 +1594,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1639,7 +1609,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:50.000Z" + - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1648,9 +1618,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1663,7 +1633,7 @@ tree: carbon-operational: 0 carbon: 0 sci: 0 - - timestamp: "2023-12-12T00:00:55.000Z" + - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 cloud/instance-type: A1 cloud/region: uk-west @@ -1672,33 +1642,9 @@ tree: requests: 0 cpu/thermal-design-power: 0 grid/carbon-intensity: 0 - device/emissions-embodied: 0 + device/emissions-embodied: 1533.12 time-reserved: 0.8 - device/expected-lifespan: 0 - vcpus-allocated: 1 - vcpus-total: 8 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - network/energy: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 0 - time-reserved: 1 - device/expected-lifespan: 0 + device/expected-lifespan: 94608000 vcpus-allocated: 1 vcpus-total: 8 cpu-factor: 0 @@ -1712,88 +1658,82 @@ tree: carbon: 0 sci: 0 aggregated: - carbon: 0.04652112950279046 + carbon: 0.3873142916032471 outputs: - - carbon: 0.013686922881785895 - timestamp: "2023-12-12T00:00:00.000Z" + - carbon: 0.09294114662607814 + timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - - carbon: 0.010700811770674782 - timestamp: "2023-12-12T00:00:05.000Z" + - carbon: 0.08995503551496703 + timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - - carbon: 0.010402200659563673 - timestamp: "2023-12-12T00:00:10.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - - carbon: 0.010402200659563675 - timestamp: "2023-12-12T00:00:15.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - - carbon: 0.010402200659563675 - timestamp: "2023-12-12T00:00:20.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - - carbon: 0.010402200659563675 - timestamp: "2023-12-12T00:00:25.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - - carbon: 0.010402200659563675 - timestamp: "2023-12-12T00:00:30.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - - carbon: 0.010402200659563675 - timestamp: "2023-12-12T00:00:35.000Z" + - carbon: 0.0896564244038559 + timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - - carbon: 0.006241320395738204 - timestamp: "2023-12-12T00:00:40.000Z" + - carbon: 0.05379385464231354 + timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:45.000Z" + timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:50.000Z" + timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:55.000Z" + timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - - carbon: 0 - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 aggregated: - carbon: 0.09304225900558093 + carbon: 0.7746285832064942 outputs: - - carbon: 0.02737384576357179 - timestamp: "2023-12-12T00:00:00.000Z" + - carbon: 0.18588229325215627 + timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - - carbon: 0.021401623541349564 - timestamp: "2023-12-12T00:00:05.000Z" + - carbon: 0.17991007102993406 + timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - - carbon: 0.020804401319127346 - timestamp: "2023-12-12T00:00:10.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - - carbon: 0.02080440131912735 - timestamp: "2023-12-12T00:00:15.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - - carbon: 0.02080440131912735 - timestamp: "2023-12-12T00:00:20.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - - carbon: 0.02080440131912735 - timestamp: "2023-12-12T00:00:25.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - - carbon: 0.02080440131912735 - timestamp: "2023-12-12T00:00:30.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - - carbon: 0.02080440131912735 - timestamp: "2023-12-12T00:00:35.000Z" + - carbon: 0.1793128488077118 + timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - - carbon: 0.012482640791476408 - timestamp: "2023-12-12T00:00:40.000Z" + - carbon: 0.10758770928462708 + timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:45.000Z" + timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:50.000Z" + timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - carbon: 0 - timestamp: "2023-12-12T00:00:55.000Z" + timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - - carbon: 0 - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 aggregated: - carbon: 0.18608451801116185 + carbon: 1.5492571664129884 From a9b60a8c32cad10352542929e7d41ab06b335365 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:11:46 +0400 Subject: [PATCH 732/863] fix(manifests): fix failure manifests --- .../csv-lookup/cloud-metadata/failure-invalid-vendor.yaml | 4 ++-- .../cloud-metadata/failure-missing-cloud-vendor.yml | 2 +- .../csv-lookup/region-metadata/failure-missing-output.yml | 2 +- .../builtins/regex/failure-not-matching-with-regex.yml | 2 +- .../features/regroup/failure-missing-cloud-instance-type.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml index 17deabf22..5d2fa16b2 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -10,8 +10,8 @@ initialize: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: - instance-class: cloud/instance-type - output: ["cpu-cores-utilized", "vcpus-allocated"] + instance-class: cloud/vendor + output: ["cpu-cores-utilized", "cloud/instance-type"] tree: children: child: diff --git a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml index aece37d5f..4d9b4c2df 100644 --- a/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml +++ b/manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml @@ -10,7 +10,7 @@ initialize: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: - instance-class: cloud/instance-type + instance-class: cloud/vendor output: ["cpu-cores-utilized", "vcpus-allocated"] tree: children: diff --git a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml index 501bde3ce..2a3d363b3 100644 --- a/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml +++ b/manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml @@ -11,7 +11,7 @@ initialize: query: cloud-provider: "cloud/provider" cloud-region: "cloud/region" - output: "*" + output: tree: children: child: diff --git a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml index bad022d72..f79303efb 100644 --- a/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml +++ b/manifests/examples/builtins/regex/failure-not-matching-with-regex.yml @@ -8,7 +8,7 @@ initialize: path: "builtin" config: parameter: physical-processor - match: ^ + match: ^$ output: cpu/name tree: children: diff --git a/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml index 8b8b44faf..708250e27 100644 --- a/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml +++ b/manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml @@ -1,7 +1,7 @@ name: regroup description: initialize: - plugins: + plugins: {} tree: children: my-app: From 1f609484796f475f87a3268c622a56f36f4f6a64 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:15:17 +0400 Subject: [PATCH 733/863] fix(manifests): remove unnecessary manifests --- .../divide/failure-denominator-equal-zero.yml | 36 -- .../outputs/pipelines/mock-obs-time-sync.yaml | 449 ------------------ 2 files changed, 485 deletions(-) delete mode 100644 manifests/examples/builtins/divide/failure-denominator-equal-zero.yml delete mode 100644 manifests/outputs/pipelines/mock-obs-time-sync.yaml diff --git a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml b/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml deleted file mode 100644 index 9635af671..000000000 --- a/manifests/examples/builtins/divide/failure-denominator-equal-zero.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: divide -description: denominator is invalid, denominator is -tags: -initialize: - plugins: - cloud-metadata: - path: builtin - method: CSVLookup - config: - filepath: >- - https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv - query: - instance-class: cloud/instance-type - output: ["cpu-cores-utilized", "vcpus-allocated"] - divide: - method: Divide - path: "builtin" - config: - numerator: vcpus-allocated - denominator: 0 - output: cpu/number-cores -tree: - children: - child: - pipeline: - compute: - - cloud-metadata - - divide - defaults: - cloud/vendor: aws - cloud/instance-type: m5n.large - cpu/name: Intel® Core™ i7-1185G7 - inputs: - - timestamp: 2023-08-06T00:00 - duration: 3600 - cpu/utilization: 80 diff --git a/manifests/outputs/pipelines/mock-obs-time-sync.yaml b/manifests/outputs/pipelines/mock-obs-time-sync.yaml deleted file mode 100644 index efe31175e..000000000 --- a/manifests/outputs/pipelines/mock-obs-time-sync.yaml +++ /dev/null @@ -1,449 +0,0 @@ -name: Mock observation and time sync integration -description: Integration of `mock observation` + `time sync` -tags: null -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - config: - timestamp-from: 2023-12-12T00:00 - timestamp-to: 2023-12-12T00:10 - duration: 60 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - randint: - cpu/utilization: - min: 1 - max: 99 - parameter-metadata: - inputs: - timestamp: - description: refers to the time of occurrence of the input - unit: RFC3339 - aggregation-method: none - duration: - description: refers to the duration of the input - unit: seconds - aggregation-method: sum - cloud/instance-type: - description: type of Cloud Instance name used in the cloud provider APIs - unit: none - aggregation-method: none - cloud/region: - description: region cloud instance - unit: none - aggregation-method: none - interpolate: - path: builtin - method: Interpolation - config: - method: linear - x: - - 0 - - 10 - - 50 - - 100 - "y": - - 0.12 - - 0.32 - - 0.75 - - 1.02 - input-parameter: cpu/utilization - output-parameter: cpu-factor - parameter-metadata: - inputs: - cpu/utilization: - description: refers to CPU utilization. - unit: percentage - aggregation-method: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu/thermal-design-power: - description: thermal design power for a processor - unit: kwh - aggregation-method: avg - wattage-times-duration: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - wattage-to-energy-kwh: - path: builtin - method: Divide - config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - calculate-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - description: total number of vcpus available on a particular resource - unit: count - aggregation-method: none - vcpus-allocated: - description: number of vcpus allocated to particular resource - unit: count - aggregation-method: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - time-sync: - path: builtin - method: TimeSync - config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" - interval: 5 - allow-padding: true -execution: - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/pipelines/mock-obs-time-sync.yml -o - manifests/outputs/pipelines/mock-obs-time-sync - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T05:29:47.787Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - status: success -tree: - children: - child-1: - pipeline: - observe: - - mock-observations - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - time-sync - defaults: - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - inputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:01:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:02:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:03:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:04:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:05:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:06:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:07:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:08:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: "2023-12-12T00:09:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: "*" - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: "2023-12-12T00:00:00.000Z" - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: "*" - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:05.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:10.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:15.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:20.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:25.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:30.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:35.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:40.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:45.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:50.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:00:55.000Z" - duration: 5 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 80 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - cpu/utilization: "*" - cloud/instance-type: A1 - cloud/region: uk-west - cpu/thermal-design-power: 100 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: "*" - cpu-wattage: "*" - cpu-wattage-times-duration: "*" - cpu-energy-raw: "*" - vcpu-ratio: "*" - cpu-energy-kwh: "*" From f368a1f574a57fd0ecdaf0bc1135f96668411a64 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:27:47 +0400 Subject: [PATCH 734/863] fix(manifests): update outdated output manifests --- .../failure-config-start-later-end.yml | 2 - .../failure-missing-cloud-vendor.yaml | 41 ++-- .../failure-missing-output.yaml | 39 ++-- .../failure-invalid-config-denominator.yaml | 62 +++-- .../divide/failure-missing-numerator.yaml | 51 +++-- .../builtins/mock-observations/success.yaml | 215 +++--------------- .../builtins/sci-embodied/success.yaml | 59 +++-- .../sci/failure-invalid-config-value.yaml | 40 ++-- .../builtins/time-converter/success.yaml | 16 +- .../outputs/builtins/time-sync/success.yaml | 107 ++++----- .../outputs/pipelines/pipeline-teads-sci.yaml | 86 +++---- manifests/outputs/pipelines/sci.yaml | 78 +++---- 12 files changed, 347 insertions(+), 449 deletions(-) diff --git a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml index c1ab78855..6a268a2d2 100644 --- a/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml +++ b/manifests/examples/builtins/time-sync/failure-config-start-later-end.yml @@ -2,8 +2,6 @@ name: time-sync description: failure with `config.start-time` being later than `config.end-time` tags: initialize: - output: - - yaml plugins: "time-sync": method: TimeSync diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml index 09539ee9a..0cbfb31db 100644 --- a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml @@ -10,35 +10,35 @@ initialize: filepath: >- https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv query: - instance-class: cloud/instance-type + instance-class: cloud/vendor output: - cpu-cores-utilized - vcpus-allocated execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yml -o - manifests/outputs/plugins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor1 + manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-missing-cloud-vendor.yaml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-05T09:07:35.386Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T08:24:01.971Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -58,7 +58,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- QueryDataNotFoundError: One or more of the given query parameters are not found in the target CSV file column headers. @@ -70,5 +70,6 @@ tree: - cloud-metadata inputs: - timestamp: 2023-07-06T00:00 + cloud/instance-type: m5n.large duration: 100 cpu/utilization: 10 diff --git a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml index 341a17aca..92c9b4c79 100644 --- a/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml +++ b/manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml @@ -12,31 +12,32 @@ initialize: query: cloud-provider: cloud/provider cloud-region: cloud/region + output: null execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output.yml + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/csv-lookup/region-metadata/failure-missing-output.yml -o - manifests/outputs/plugins/csv-lookup/region-metadata/failure-missing-output + manifests/outputs/builtins/csv-lookup/region-metadata/failure-missing-output.yaml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T21:26:09.874Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T08:47:18.608Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -56,7 +57,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- InputValidationError: "output" parameter is invalid input. Error code: invalid_union. diff --git a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml index fd0c50cce..3709451e3 100644 --- a/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml +++ b/manifests/outputs/builtins/divide/failure-invalid-config-denominator.yaml @@ -3,37 +3,48 @@ description: failure when `config.denominator` is string tags: null initialize: plugins: + cloud-metadata: + path: builtin + method: CSVLookup + config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated divide: method: Divide path: builtin config: - numerator: cpu/utilization - denominator: test - output: cpu/divided-two + numerator: vcpus-allocated + denominator: vcpus + output: cpu/number-cores execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml -o - manifests/outputs/plugins/divide/failure-invalid-config-denominator.yml + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/divide/failure-invalid-config-denominator.yml -o + manifests/outputs/builtins/divide/failure-invalid-config-denominator.yml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T06:02:25.409Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:15:13.478Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -53,16 +64,21 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- - MissingInputDataError: test is missing from the input array, or has nullish + MissingInputDataError: vcpus is missing from the input array, or has nullish value. tree: children: child: pipeline: compute: + - cloud-metadata - divide + defaults: + cloud/vendor: aws + cloud/instance-type: m5n.large + cpu/name: Intel® Core™ i7-1185G7 inputs: - timestamp: 2023-08-06T00:00 duration: 3600 diff --git a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml index a59e2f962..2a34a9513 100644 --- a/manifests/outputs/builtins/divide/failure-missing-numerator.yaml +++ b/manifests/outputs/builtins/divide/failure-missing-numerator.yaml @@ -3,6 +3,17 @@ description: success path tags: null initialize: plugins: + cloud-metadata: + path: builtin + method: CSVLookup + config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated divide: method: Divide path: builtin @@ -12,27 +23,27 @@ initialize: execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/divide/failure-missing-numerator.yml -o - manifests/outputs/plugins/divide/failure-missing-numerator + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/divide/failure-missing-numerator.yml -o + manifests/outputs/builtins/divide/failure-missing-numerator.yml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T05:49:51.802Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:15:22.702Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -52,7 +63,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- InputValidationError: "numerator" parameter is required. Error code: invalid_type. @@ -61,6 +72,7 @@ tree: child: pipeline: compute: + - cloud-metadata - divide defaults: cloud/vendor: aws @@ -70,4 +82,3 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 cpu/utilization: 80 - vcpus-allocated: 8 diff --git a/manifests/outputs/builtins/mock-observations/success.yaml b/manifests/outputs/builtins/mock-observations/success.yaml index c2ee71085..f099a5cb5 100644 --- a/manifests/outputs/builtins/mock-observations/success.yaml +++ b/manifests/outputs/builtins/mock-observations/success.yaml @@ -26,27 +26,27 @@ initialize: max: 99 execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m manifests/examples/builtins/mock-observations/success.yml -o - manifests/outputs/builtins/mock-observations/success + manifests/outputs/builtins/mock-observations/success.yaml environment: - if-version: 0.5.0 + if-version: 0.6.0 os: macOS - os-version: "14.5" - node-version: 18.14.2 - date-time: 2024-08-02T15:04:18.262Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T10:54:25.979Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.16" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -75,281 +75,140 @@ tree: observe: - mock-observations inputs: - - timestamp: "2023-07-06T00:00:00.000Z" + - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" + - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" + - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" + - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" + - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" + - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" + - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" + - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" + - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" + - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: A1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:00:00.000Z" + - timestamp: '2023-07-06T00:00:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" + - timestamp: '2023-07-06T00:01:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" + - timestamp: '2023-07-06T00:02:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" + - timestamp: '2023-07-06T00:03:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" + - timestamp: '2023-07-06T00:04:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" + - timestamp: '2023-07-06T00:05:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" + - timestamp: '2023-07-06T00:06:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" + - timestamp: '2023-07-06T00:07:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" + - timestamp: '2023-07-06T00:08:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west common-key: common-val cpu/utilization: "*" memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - outputs: - - timestamp: "2023-07-06T00:00:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:00:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:01:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:02:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:03:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:04:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:05:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:06:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:07:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:08:00.000Z" - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: "*" - memory/utilization: "*" - - timestamp: "2023-07-06T00:09:00.000Z" + - timestamp: '2023-07-06T00:09:00.000Z' duration: 60 cloud/instance-type: B1 region: uk-west diff --git a/manifests/outputs/builtins/sci-embodied/success.yaml b/manifests/outputs/builtins/sci-embodied/success.yaml index e91ab9212..da0a86549 100644 --- a/manifests/outputs/builtins/sci-embodied/success.yaml +++ b/manifests/outputs/builtins/sci-embodied/success.yaml @@ -3,32 +3,43 @@ description: successful path tags: null initialize: plugins: + csv-lookup: + path: builtin + method: CSVLookup + config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-azure-instances.csv + query: + instance-class: cloud/instance-type + output: + - cpu-cores-utilized + - vcpus-allocated sci-embodied: path: builtin method: SciEmbodied execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/sci-embodied/success.yml -o - manifests/outputs/plugins/sci-embodied/success + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/sci-embodied/success.yml -o + manifests/outputs/builtins/sci-embodied/success.yml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T20:42:03.186Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:14:11.145Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -48,13 +59,14 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: child: pipeline: compute: + - csv-lookup - sci-embodied defaults: device/emissions-embodied: 1533.12 @@ -65,12 +77,19 @@ tree: inputs: - timestamp: 2023-07-06T00:00 duration: 3600 + cloud/vendor: intel + cloud/instance-type: Standard_A1_v2 + cpu/utilization: 10 outputs: - timestamp: 2023-07-06T00:00 duration: 3600 + cloud/vendor: intel + cloud/instance-type: Standard_A1_v2 + cpu/utilization: 10 device/emissions-embodied: 1533.12 time-reserved: 3600 device/expected-lifespan: 94608000 resources-reserved: 1 resources-total: 8 - carbon-embodied: 0.007292237442922374 + vcpus-allocated: 1 + embodied-carbon: 28.538812785388128 diff --git a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml index c8f34a4e4..8d46b1964 100644 --- a/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml +++ b/manifests/outputs/builtins/sci/failure-invalid-config-value.yaml @@ -10,27 +10,27 @@ initialize: execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/sci/failure-invalid-config-value.yml -o - manifests/outputs/plugins/sci/failure-invalid-config-value + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/sci/failure-invalid-config-value.yml -o + manifests/outputs/builtins/sci/failure-invalid-config-value.yml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T20:38:15.858Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:15:31.434Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -50,8 +50,8 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 - error: "InputValidationError: Required" + - zod@3.23.8 + error: 'ConfigError: Config is not provided.' tree: children: child: diff --git a/manifests/outputs/builtins/time-converter/success.yaml b/manifests/outputs/builtins/time-converter/success.yaml index 33ae5d503..012fdbbbb 100644 --- a/manifests/outputs/builtins/time-converter/success.yaml +++ b/manifests/outputs/builtins/time-converter/success.yaml @@ -16,23 +16,19 @@ execution: /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m manifests/examples/builtins/time-converter/success.yaml -o - manifests/outputs/time-converter/success + manifests/outputs/builtins/time-converter/success.yaml environment: if-version: 0.6.0 os: macOS - os-version: 13.6.7 - node-version: 18.20.0 - date-time: 2024-08-28T13:04:25.498Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:14:08.350Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.18' - - '@grnsft/if-plugins@v0.3.2 extraneous -> file:../../../if-models' - - >- - @grnsft/if-unofficial-plugins@v0.3.0 extraneous -> - file:../../../if-unofficial-models + - '@grnsft/if-core@0.0.22' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -46,8 +42,6 @@ execution: - fixpack@4.0.0 - gts@5.2.0 - husky@8.0.3 - - if-eco-ci-plugin@v0.0.1 extraneous -> file:../../if-eco-ci-plugin - - if-github-plugin@v0.0.1 extraneous -> file:../../if-github-plugin - jest@29.7.0 - js-yaml@4.1.0 - lint-staged@15.2.2 diff --git a/manifests/outputs/builtins/time-sync/success.yaml b/manifests/outputs/builtins/time-sync/success.yaml index 36d6c10da..b49acb084 100644 --- a/manifests/outputs/builtins/time-sync/success.yaml +++ b/manifests/outputs/builtins/time-sync/success.yaml @@ -7,39 +7,33 @@ initialize: path: builtin method: TimeSync config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true - parameter-metadata: - outputs: - energy-cpu: - unit: KWH - description: energy - aggregation-method: sum execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/time-sync/success.yml -o - manifests/outputs/plugins/time-sync/success -s + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/time-sync/success.yml -o + manifests/outputs/builtins/time-sync/success.yml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T21:12:32.629Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:16:13.676Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -59,7 +53,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: @@ -68,55 +62,52 @@ tree: compute: - time-sync inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 energy-cpu: 0.001 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' duration: 5 - energy-cpu: 0.0018000000000000004 - - timestamp: "2023-12-12T00:00:05.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:05.000Z' duration: 5 - energy-cpu: 0.0007714285714285716 - - timestamp: "2023-12-12T00:00:10.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:10.000Z' duration: 5 - energy-cpu: 0.0004952380952380952 - - timestamp: "2023-12-12T00:00:15.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:15.000Z' duration: 5 - energy-cpu: 0.0001666666666666667 - - timestamp: "2023-12-12T00:00:20.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:20.000Z' duration: 5 - energy-cpu: 0.0001666666666666667 - - timestamp: "2023-12-12T00:00:25.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:25.000Z' duration: 5 - energy-cpu: 0.0001666666666666667 - - timestamp: "2023-12-12T00:00:30.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:30.000Z' duration: 5 - energy-cpu: 0.0001666666666666667 - - timestamp: "2023-12-12T00:00:35.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:35.000Z' duration: 5 - energy-cpu: 0.0001666666666666667 - - timestamp: "2023-12-12T00:00:40.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:40.000Z' duration: 5 - energy-cpu: 0.0001 - - timestamp: "2023-12-12T00:00:45.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:45.000Z' duration: 5 - energy-cpu: 0 - - timestamp: "2023-12-12T00:00:50.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:50.000Z' duration: 5 - energy-cpu: 0 - - timestamp: "2023-12-12T00:00:55.000Z" + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:55.000Z' duration: 5 - energy-cpu: 0 - - timestamp: "2023-12-12T00:01:00.000Z" - duration: 1 - energy-cpu: 0 + energy-cpu: 0.001 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index c014d9f6d..b9a6377f5 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -15,7 +15,7 @@ initialize: - 10 - 50 - 100 - "y": + 'y': - 0.12 - 0.32 - 0.75 @@ -83,29 +83,37 @@ initialize: - carbon-operational - embodied-carbon output-parameter: carbon + time-sync: + path: builtin + method: TimeSync + config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m manifests/examples/pipelines/pipeline-teads-sci.yml -o - manifests/outputs/pipelines/pipeline-teads-sci + manifests/outputs/pipelines/pipeline-teads-sci.yml environment: - if-version: 0.5.0 + if-version: 0.6.0 os: macOS - os-version: "14.5" - node-version: 18.14.2 - date-time: 2024-07-19T06:32:50.994Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:31.812Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -125,7 +133,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: @@ -152,32 +160,32 @@ tree: vcpus-allocated: 1 component: 1 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 network/energy: 0.000001 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 @@ -197,11 +205,11 @@ tree: cpu-energy-raw: 0.000020833333333333333 vcpu-ratio: 8 cpu-energy-kwh: 0.0000026041666666666666 - embodied-carbon: 0.0000020256215119228817 + embodied-carbon: 0.007927447995941146 carbon-operational: 0.0020833333333333333 - carbon: 0.002085358954845256 - sci: 0.002085358954845256 - - timestamp: "2023-12-12T00:00:01.000Z" + carbon: 0.010010781329274479 + sci: 0.010010781329274479 + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 @@ -221,11 +229,11 @@ tree: cpu-energy-raw: 0.000059375 vcpu-ratio: 8 cpu-energy-kwh: 0.000007421875 - embodied-carbon: 0.000010128107559614407 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.0059375 - carbon: 0.005947628107559615 - sci: 0.005947628107559615 - - timestamp: "2023-12-12T00:00:06.000Z" + carbon: 0.045574739979705736 + sci: 0.045574739979705736 + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 @@ -245,11 +253,11 @@ tree: cpu-energy-raw: 0.00007267361111111111 vcpu-ratio: 8 cpu-energy-kwh: 0.000009084201388888889 - embodied-carbon: 0.00001417935058346017 + embodied-carbon: 0.05549213597158803 carbon-operational: 0.007267361111111111 - carbon: 0.007281540461694571 - sci: 0.007281540461694571 - - timestamp: "2023-12-12T00:00:13.000Z" + carbon: 0.06275949708269914 + sci: 0.06275949708269914 + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -269,7 +277,7 @@ tree: cpu-energy-raw: 0.00031145833333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.00003893229166666667 - embodied-carbon: 0.00006076864535768645 + embodied-carbon: 0.2378234398782344 carbon-operational: 0.031145833333333334 - carbon: 0.03120660197869102 - sci: 0.03120660197869102 + carbon: 0.2689692732115677 + sci: 0.2689692732115677 diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml index 322a413b8..7a967c9ef 100644 --- a/manifests/outputs/pipelines/sci.yaml +++ b/manifests/outputs/pipelines/sci.yaml @@ -15,7 +15,7 @@ initialize: - 10 - 50 - 100 - "y": + 'y': - 0.12 - 0.32 - 0.75 @@ -93,26 +93,26 @@ initialize: functional-unit: component execution: command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/if-run/index.ts -m - manifests/examples/pipelines/sci.yml -o manifests/outputs/pipelines/sci + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/sci.yml -o manifests/outputs/pipelines/sci.yml environment: - if-version: 0.5.0 + if-version: 0.6.0 os: macOS - os-version: "14.5" - node-version: 18.14.2 - date-time: 2024-07-19T06:34:45.027Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:59.916Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -132,7 +132,7 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 status: success tree: children: @@ -162,32 +162,32 @@ tree: resources-total: vcpus-total component: 1 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 50 network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west network/energy: 0.000001 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west cpu/utilization: 15 network/energy: 0.000001 outputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 @@ -210,11 +210,11 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000005208333333333333 energy: 0.000006208333333333333 - embodied-carbon: 0.000004051243023845763 + embodied-carbon: 0.007927447995941146 carbon-operational: 0.004966666666666666 - carbon: 0.004970717909690512 - sci: 0.004970717909690512 - - timestamp: "2023-12-12T00:00:01.000Z" + carbon: 0.012894114662607812 + sci: 0.012894114662607812 + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 @@ -237,11 +237,11 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00001484375 energy: 0.00001584375 - embodied-carbon: 0.000020256215119228814 + embodied-carbon: 0.03963723997970574 carbon-operational: 0.012674999999999999 - carbon: 0.012695256215119228 - sci: 0.012695256215119228 - - timestamp: "2023-12-12T00:00:06.000Z" + carbon: 0.05231223997970574 + sci: 0.05231223997970574 + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 @@ -264,11 +264,11 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000018168402777777778 energy: 0.000019168402777777778 - embodied-carbon: 0.00002835870116692034 + embodied-carbon: 0.05549213597158803 carbon-operational: 0.015334722222222222 - carbon: 0.015363080923389142 - sci: 0.015363080923389142 - - timestamp: "2023-12-12T00:00:13.000Z" + carbon: 0.07082685819381025 + sci: 0.07082685819381025 + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -291,7 +291,7 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00007786458333333334 energy: 0.00007886458333333333 - embodied-carbon: 0.0001215372907153729 + embodied-carbon: 0.2378234398782344 carbon-operational: 0.06309166666666667 - carbon: 0.06321320395738204 - sci: 0.06321320395738204 \ No newline at end of file + carbon: 0.30091510654490106 + sci: 0.30091510654490106 From cec3813efe6c5100b08b8b99a2e6cfd387d438ab Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:45:24 +0400 Subject: [PATCH 735/863] fix(manifests): add missed output manifests --- .../failure-invalid-vendor.yaml | 76 + .../failure-not-matching-with-regex.yaml | 72 + .../builtins/sci-embodied/scenario-1.yaml | 91 + .../builtins/sci-embodied/scenario-2.yaml | 100 ++ .../failure-missing-global-config.yaml | 77 + .../regroup/failure-invalid-regroup.yaml | 87 + .../failure-missing-cloud-instance-type.yaml | 87 + .../outputs/features/regroup/success.yaml | 92 + .../pipeline-with-aggregate.yaml | 1212 +++++++++++++ .../outputs-if-diff/pipeline-with-mocks.yaml | 1507 +++++++++++++++++ .../pipelines/pipeline-with-aggregate.yaml | 1167 +++++++++++++ .../pipelines/pipeline-with-mocks.yaml | 1187 +++++++++++++ manifests/outputs/pipelines/scenario-3.yaml | 146 ++ manifests/outputs/pipelines/scenario-4.yaml | 105 ++ manifests/outputs/pipelines/scenario-5.yaml | 125 ++ 15 files changed, 6131 insertions(+) create mode 100644 manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml create mode 100644 manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml create mode 100644 manifests/outputs/builtins/sci-embodied/scenario-1.yaml create mode 100644 manifests/outputs/builtins/sci-embodied/scenario-2.yaml create mode 100644 manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml create mode 100644 manifests/outputs/features/regroup/failure-invalid-regroup.yaml create mode 100644 manifests/outputs/features/regroup/failure-missing-cloud-instance-type.yaml create mode 100644 manifests/outputs/features/regroup/success.yaml create mode 100644 manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml create mode 100644 manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml create mode 100644 manifests/outputs/pipelines/pipeline-with-aggregate.yaml create mode 100644 manifests/outputs/pipelines/pipeline-with-mocks.yaml create mode 100644 manifests/outputs/pipelines/scenario-3.yaml create mode 100644 manifests/outputs/pipelines/scenario-4.yaml create mode 100644 manifests/outputs/pipelines/scenario-5.yaml diff --git a/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml new file mode 100644 index 000000000..aa83f102b --- /dev/null +++ b/manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml @@ -0,0 +1,76 @@ +name: cloud-metadata +description: failure with invalid `inputs.cloud/vendor` +tags: null +initialize: + plugins: + cloud-metadata: + path: builtin + method: CSVLookup + config: + filepath: >- + https://raw.githubusercontent.com/Green-Software-Foundation/if-data/main/cloud-metdata-aws-instances.csv + query: + instance-class: cloud/vendor + output: + - cpu-cores-utilized + - cloud/instance-type +execution: + status: fail + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml + -o + manifests/outputs/builtins/csv-lookup/cloud-metadata/failure-invalid-vendor.yaml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T07:42:52.156Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + error: >- + QueryDataNotFoundError: One or more of the given query parameters are not + found in the target CSV file column headers. +tree: + children: + child: + pipeline: + compute: + - cloud-metadata + inputs: + - timestamp: 2023-07-06T00:00 + cloud/vendor: gcp + cloud/instance-type: m5n.large + duration: 100 + cpu/utilization: 10 diff --git a/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml b/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml new file mode 100644 index 000000000..e18b408b1 --- /dev/null +++ b/manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml @@ -0,0 +1,72 @@ +name: regex +description: physical processor doesn't match the regex expression +tags: null +initialize: + plugins: + regex: + method: Regex + path: builtin + config: + parameter: physical-processor + match: ^$ + output: cpu/name +execution: + status: fail + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/regex/failure-not-matching-with-regex.yml -o + manifests/outputs/builtins/regex/failure-not-matching-with-regex.yaml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T11:17:40.549Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + error: >- + RegexMismatchError: `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` does + not match the /^$/ regex expression +tree: + children: + child: + pipeline: + compute: + - regex + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + physical-processor: >- + 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 diff --git a/manifests/outputs/builtins/sci-embodied/scenario-1.yaml b/manifests/outputs/builtins/sci-embodied/scenario-1.yaml new file mode 100644 index 000000000..ec07d4df1 --- /dev/null +++ b/manifests/outputs/builtins/sci-embodied/scenario-1.yaml @@ -0,0 +1,91 @@ +name: embodied-carbon demo +description: null +tags: null +aggregation: + metrics: + - embodied-carbon + type: both +initialize: + plugins: + embodied-carbon: + path: builtin + method: SciEmbodied + config: + output-parameter: embodied-carbon +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/sci-embodied/scenario-1.yml -o + manifests/outputs/builtins/sci-embodied/scenario-1.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:14:16.990Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child: + pipeline: + compute: + - embodied-carbon + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + hdd: 2 + - timestamp: 2023-08-06T10:00 + duration: 3600 + hdd: 2 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + hdd: 2 + embodied-carbon: 34.24657534246575 + - timestamp: 2023-08-06T10:00 + duration: 3600 + hdd: 2 + embodied-carbon: 34.24657534246575 + aggregated: + embodied-carbon: 68.4931506849315 + outputs: + - embodied-carbon: 34.24657534246575 + timestamp: 2023-08-06T00:00 + duration: 3600 + - embodied-carbon: 34.24657534246575 + timestamp: 2023-08-06T10:00 + duration: 3600 + aggregated: + embodied-carbon: 68.4931506849315 diff --git a/manifests/outputs/builtins/sci-embodied/scenario-2.yaml b/manifests/outputs/builtins/sci-embodied/scenario-2.yaml new file mode 100644 index 000000000..2ecf249cf --- /dev/null +++ b/manifests/outputs/builtins/sci-embodied/scenario-2.yaml @@ -0,0 +1,100 @@ +name: embodied-carbon demo +description: null +tags: null +initialize: + plugins: + embodied-carbon: + path: builtin + method: SciEmbodied + config: + baseline-vcpus: 1 + baseline-memory: 16 + lifespan: 157680000 + baseline-emissions: 2000000 + vcpu-emissions-constant: 100000 + memory-emissions-constant: 1172 + ssd-emissions-constant: 50000 + hdd-emissions-constant: 100000 + gpu-emissions-constant: 150000 + output-parameter: embodied-carbon +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/sci-embodied/scenario-2.yml -o + manifests/outputs/builtins/sci-embodied/scenario-2.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:14:14.168Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child: + pipeline: + compute: + - embodied-carbon + defaults: + vCPUs: 4 + memory: 32 + ssd: 1 + hdd: 1 + gpu: 1 + total-vcpus: 16 + inputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + - timestamp: 2023-08-06T10:00 + duration: 3600 + outputs: + - timestamp: 2023-08-06T00:00 + duration: 3600 + vCPUs: 4 + memory: 32 + ssd: 1 + hdd: 1 + gpu: 1 + total-vcpus: 16 + embodied-carbon: 487.48858447488584 + - timestamp: 2023-08-06T10:00 + duration: 3600 + vCPUs: 4 + memory: 32 + ssd: 1 + hdd: 1 + gpu: 1 + total-vcpus: 16 + embodied-carbon: 487.48858447488584 diff --git a/manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml new file mode 100644 index 000000000..664da36d1 --- /dev/null +++ b/manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml @@ -0,0 +1,77 @@ +name: time-sync +description: missing config +tags: null +initialize: + output: + - yaml + plugins: + time-sync: + method: TimeSync + path: builtin + config: null +execution: + status: fail + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/builtins/time-sync/failure-missing-global-config.yml -o + manifests/outputs/builtins/time-sync/failure-missing-global-config.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:16:16.464Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + error: >- + ManifestValidationError: "initialize.plugins.time-sync.config" parameter is + expected object, received null. Error code: invalid_type. +tree: + children: + child: + pipeline: + compute: + - time-sync + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 3 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + energy-cpu: 0.001 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + energy-cpu: 0.001 diff --git a/manifests/outputs/features/regroup/failure-invalid-regroup.yaml b/manifests/outputs/features/regroup/failure-invalid-regroup.yaml new file mode 100644 index 000000000..2a40fe2fb --- /dev/null +++ b/manifests/outputs/features/regroup/failure-invalid-regroup.yaml @@ -0,0 +1,87 @@ +name: regroup +description: failure when `regroup` is not an array +initialize: + plugins: {} +execution: + status: fail + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/features/regroup/failure-invalid-regroup.yml -o + manifests/outputs/features/regroup/failure-invalid-regroup.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:09.837Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + error: >- + InputValidationError: "regroup" parameter is not an array or should contain + at least one key. Error code: invalid_type. +tree: + children: + my-app: + pipeline: + regroup: cloud/region + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/features/regroup/failure-missing-cloud-instance-type.yaml b/manifests/outputs/features/regroup/failure-missing-cloud-instance-type.yaml new file mode 100644 index 000000000..65fa5a113 --- /dev/null +++ b/manifests/outputs/features/regroup/failure-missing-cloud-instance-type.yaml @@ -0,0 +1,87 @@ +name: regroup +description: null +initialize: + plugins: {} +execution: + status: fail + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/features/regroup/failure-missing-cloud-instance-type.yml + -o + manifests/outputs/features/regroup/failure-missing-cloud-instance-type.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:14.590Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + error: 'InvalidGroupingError: Invalid group cloud/instance-type.' +tree: + children: + my-app: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/features/regroup/success.yaml b/manifests/outputs/features/regroup/success.yaml new file mode 100644 index 000000000..efc6d847f --- /dev/null +++ b/manifests/outputs/features/regroup/success.yaml @@ -0,0 +1,92 @@ +name: regroup +description: successful path +initialize: + plugins: {} +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/features/regroup/success.yml -o + manifests/outputs/features/regroup/success.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:12.222Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + my-app: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + children: + uk-west: + children: + A1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + B1: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 diff --git a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml new file mode 100644 index 000000000..906968735 --- /dev/null +++ b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml @@ -0,0 +1,1212 @@ +name: pipeline-with-aggregate +description: a full pipeline with the aggregate feature enabled +tags: null +aggregation: + metrics: + - carbon + type: both +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + config: + method: linear + x: + - 0 + - 10 + - 50 + - 100 + 'y': + - 0.12 + - 0.32 + - 0.75 + - 1.02 + input-parameter: cpu/utilization + output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: + time: avg + component: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: + time: avg + component: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: + time: sum + component: sum + wattage-times-duration: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: + time: none + component: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: + time: none + component: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: none + component: none + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: + time: avg + component: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + sci: + path: builtin + method: Sci + config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: + time: sum + component: sum + sum-carbon: + path: builtin + method: Sum + config: + input-parameters: + - carbon-operational + - embodied-carbon + output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + embodied-carbon: + unit: gCO2eq + description: Embodied carbon footprint + aggregation-method: + time: sum + component: sum + outputs: + carbon: + unit: gCO2eq + description: Total carbon footprint + aggregation-method: + time: sum + component: sum + time-sync: + path: builtin + method: TimeSync + config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: + time: none + component: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: + time: sum + component: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: + time: none + component: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: + time: none + component: none + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: + time: avg + component: avg +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml -o + manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:45.889Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + aggregated: + carbon: 0.38611984715880265 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 10 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 15 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 14 + requests: 14 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3205 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: null + cpu-energy-kwh: 0.000007048611111111113 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.0056388888888888895 + carbon: 0.045276128868594626 + sci: 0.0032340092048996163 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 13 + cloud/instance-type: null + cloud/region: null + requests: 9.571428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.30975 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: null + cpu-energy-kwh: 0.000006675347222222222 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.005340277777777777 + carbon: 0.044977517757483515 + sci: 0.004699143646304248 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 12 + cloud/instance-type: null + cloud/region: null + requests: 8.428571428571429 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.0000064887152777777775 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005318601447686367 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 9 + requests: 3 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 1533.12 + time-reserved: 2160.2 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.22425 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: null + cpu-energy-kwh: 0.000003893229166666667 + embodied-carbon: 0.02378234398782344 + carbon-operational: 0.0031145833333333334 + carbon: 0.02689692732115677 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.38611984715880265 + outputs: + - carbon: 0.045276128868594626 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.044977517757483515 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02689692732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.38611984715880265 + outputs: + - carbon: 0.045276128868594626 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.044977517757483515 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02689692732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + child-2: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + aggregated: + carbon: 0.4092622082699138 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 150 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 110 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 180 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 22.8 + cloud/instance-type: null + cloud/region: null + requests: 220 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.41509999999999997 + cpu-wattage: 94.57999999999998 + cpu-wattage-times-duration: 258.9 + cpu-energy-raw: 0.00007191666666666668 + vcpu-ratio: null + cpu-energy-kwh: 0.000008989583333333334 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007191666666666666 + carbon: 0.046828906646372404 + sci: 0.00021285866657442002 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 29.6 + cloud/instance-type: null + cloud/region: null + requests: 92.85714285714285 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.48819999999999997 + cpu-wattage: 46.98428571428572 + cpu-wattage-times-duration: 308.35 + cpu-energy-raw: 0.00008565277777777778 + vcpu-ratio: null + cpu-energy-kwh: 0.000010706597222222223 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.008565277777777778 + carbon: 0.04820251775748351 + sci: 0.0005191040373882839 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 30.6 + cloud/instance-type: null + cloud/region: null + requests: 59.14285714285714 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.49894999999999995 + cpu-wattage: 31.31738095238095 + cpu-wattage-times-duration: 306.2 + cpu-energy-raw: 0.00008505555555555556 + vcpu-ratio: null + cpu-energy-kwh: 0.000010631944444444445 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.008505555555555556 + carbon: 0.04814279553526128 + sci: 0.0008140086201614227 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: null + cloud/region: null + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: null + cloud/region: null + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: null + cloud/region: null + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: null + cloud/region: null + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: null + cloud/region: null + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: null + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 19.8 + cloud/instance-type: null + cloud/region: null + requests: 18 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 1533.12 + time-reserved: 2160.2 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.34035000000000004 + cpu-wattage: 5.6725 + cpu-wattage-times-duration: 170.175 + cpu-energy-raw: 0.00004727083333333333 + vcpu-ratio: null + cpu-energy-kwh: 0.000005908854166666666 + embodied-carbon: 0.02378234398782344 + carbon-operational: 0.004727083333333333 + carbon: 0.02850942732115677 + sci: 0.0015838570733975985 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: null + cloud/region: null + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: null + cloud/region: null + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: null + cloud/region: null + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 0.8 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.4092622082699138 + outputs: + - carbon: 0.046828906646372404 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04820251775748351 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04814279553526128 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02850942732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.4092622082699138 + outputs: + - carbon: 0.046828906646372404 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04820251775748351 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04814279553526128 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02850942732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + outputs: + - carbon: 0.09210503551496703 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.09318003551496702 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.09297100773718923 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.05540635464231354 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.7953820554287163 diff --git a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml new file mode 100644 index 000000000..3afc34f3e --- /dev/null +++ b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml @@ -0,0 +1,1507 @@ +name: pipeline-with-mocks +description: a full pipeline seeded with data from mock-observations feature +tags: null +aggregation: + metrics: + - carbon + type: both +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + config: + timestamp-from: 2023-12-12T00:00 + timestamp-to: 2023-12-12T00:10 + duration: 60 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + randint: + cpu/utilization: + min: 1 + max: 99 + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: + time: none + component: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: + time: sum + component: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: + time: none + component: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: + time: none + component: none + interpolate: + path: builtin + method: Interpolation + config: + method: linear + x: + - 0 + - 10 + - 50 + - 100 + 'y': + - 0.12 + - 0.32 + - 0.75 + - 1.02 + input-parameter: cpu/utilization + output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: + time: avg + component: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: + time: avg + component: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: + time: sum + component: sum + wattage-times-duration: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + parameter-metadata: + inputs: + cpu-wattage: + unit: kWh + description: Energy used by the CPU + aggregation-method: + time: sum + component: sum + duration: + unit: seconds + description: Duration of the observation + aggregation-method: + time: sum + component: sum + outputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + wattage-to-energy-kwh: + path: builtin + method: Divide + config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: + time: none + component: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: + time: none + component: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: none + component: none + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + parameter-metadata: + inputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: none + component: none + outputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: + time: avg + component: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + sum-carbon: + path: builtin + method: Sum + config: + input-parameters: + - carbon-operational + - embodied-carbon + output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + embodied-carbon: + unit: gCO2eq + description: Embodied carbon footprint + aggregation-method: + time: sum + component: sum + outputs: + carbon: + unit: gCO2eq + description: Total carbon footprint + aggregation-method: + time: sum + component: sum + sci: + path: builtin + method: Sci + config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: + time: sum + component: sum + outputs: + sci: + unit: none + description: Scientific Carbon Intensity + aggregation-method: + time: none + component: none + time-sync: + path: builtin + method: TimeSync + config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true + parameter-metadata: + inputs: + time-reserved: + unit: seconds + description: time reserved for a component + aggregation-method: + time: avg + component: avg + outputs: + synced-time: + unit: none + description: Synced time + aggregation-method: + time: none + component: none +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml -o + manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:48.694Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + aggregated: + carbon: 0.5505472444190767 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 17 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:01:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 17 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:02:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 90 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:03:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 10 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:04:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 59 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:05:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 64 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:06:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 46 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:07:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 28 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:08:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 40 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:09:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 60 + cpu/utilization: 37 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:05.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:10.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:15.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:20.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:25.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:30.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:35.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:40.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:45.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:50.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:00:55.000Z' + cloud/instance-type: null + cloud/region: null + duration: 5 + cpu/utilization: 13.6 + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.3162 + cpu-wattage: 3.2937499999999997 + cpu-wattage-times-duration: 197.625 + cpu-energy-raw: 0.00005489583333333334 + vcpu-ratio: null + cpu-energy-kwh: 0.000006861979166666667 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005489583333333334 + carbon: 0.04512682331303906 + sci: 0.018050729325215627 + - timestamp: '2023-12-12T00:01:00.000Z' + cloud/instance-type: null + cloud/region: null + duration: 1 + cpu/utilization: 17 + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.39525 + cpu-wattage: 0.65875 + cpu-wattage-times-duration: 39.525 + cpu-energy-raw: 0.000010979166666666668 + vcpu-ratio: null + cpu-energy-kwh: 0.0000013723958333333335 + embodied-carbon: 0.007927447995941146 + carbon-operational: 0.0010979166666666667 + carbon: 0.009025364662607813 + sci: 0.018050729325215627 + aggregated: + carbon: 0.5505472444190767 + outputs: + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0.009025364662607813 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.5505472444190767 + outputs: + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0.04512682331303906 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0.009025364662607813 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + child-2: + pipeline: + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + aggregated: + carbon: 0.6495376610857433 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 60 + cpu/utilization: 93 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 60 + cpu/utilization: 62 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:02:00.000Z' + duration: 60 + cpu/utilization: 66 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:03:00.000Z' + duration: 60 + cpu/utilization: 46 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:04:00.000Z' + duration: 60 + cpu/utilization: 60 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:05:00.000Z' + duration: 60 + cpu/utilization: 10 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:06:00.000Z' + duration: 60 + cpu/utilization: 62 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:07:00.000Z' + duration: 60 + cpu/utilization: 71 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:08:00.000Z' + duration: 60 + cpu/utilization: 21 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:09:00.000Z' + duration: 60 + cpu/utilization: 53 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 74.4 + cloud/instance-type: null + cloud/region: null + requests: 2.5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 2880 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.78576 + cpu-wattage: 8.185 + cpu-wattage-times-duration: 491.1 + cpu-energy-raw: 0.00013641666666666666 + vcpu-ratio: null + cpu-energy-kwh: 0.000017052083333333332 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013641666666666667 + carbon: 0.053278906646372394 + sci: 0.021311562658548958 + - timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + cpu/utilization: 62 + cloud/instance-type: null + cloud/region: null + requests: 0.5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + cpu-factor: 0.8148 + cpu-wattage: 1.3579999999999999 + cpu-wattage-times-duration: 81.47999999999999 + cpu-energy-raw: 0.00002263333333333333 + vcpu-ratio: null + cpu-energy-kwh: 0.000002829166666666666 + embodied-carbon: 0.007927447995941146 + carbon-operational: 0.002263333333333333 + carbon: 0.010190781329274479 + sci: 0.020381562658548957 + aggregated: + carbon: 0.6495376610857433 + outputs: + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0.010190781329274479 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 0.6495376610857433 + outputs: + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0.053278906646372394 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0.010190781329274479 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + outputs: + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0.09840572995941146 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + - carbon: 0.019216145991882292 + timestamp: '2023-12-12T00:01:00.000Z' + duration: 1 + aggregated: + carbon: 1.2000849055048197 diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml new file mode 100644 index 000000000..582e8351d --- /dev/null +++ b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml @@ -0,0 +1,1167 @@ +name: pipeline-with-aggregate +description: a full pipeline with the aggregate feature enabled +tags: null +aggregation: + metrics: + - carbon + type: both +initialize: + plugins: + interpolate: + path: builtin + method: Interpolation + config: + method: linear + x: + - 0 + - 10 + - 50 + - 100 + 'y': + - 0.12 + - 0.32 + - 0.75 + - 1.02 + input-parameter: cpu/utilization + output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: + time: avg + component: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: + time: avg + component: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: + time: sum + component: sum + wattage-times-duration: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + wattage-to-energy-kwh: + path: builtin + method: Divide + config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: + time: copy + component: copy + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: + time: copy + component: copy + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: copy + component: copy + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: + time: avg + component: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + sci: + path: builtin + method: Sci + config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: + time: sum + component: sum + sum-carbon: + path: builtin + method: Sum + config: + input-parameters: + - carbon-operational + - embodied-carbon + output-parameter: carbon + parameter-metadata: + outputs: + carbon: + unit: gCO2eq + description: product of carbon + aggregation-method: + time: sum + component: sum + time-sync: + path: builtin + method: TimeSync + config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-aggregate.yml -o + manifests/outputs/pipelines/pipeline-with-aggregate.yaml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T11:54:19.467Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 10 + requests: 10 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 20 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 5 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 15 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 15 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + requests: 30 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 5 + cpu/utilization: 14 + requests: 14 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.3205 + cpu-wattage: 66.19999999999999 + cpu-wattage-times-duration: 203 + cpu-energy-raw: 0.0000563888888888889 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000007048611111111113 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.0056388888888888895 + carbon: 0.045276128868594626 + sci: 0.0032340092048996163 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 13 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 9.571428571428571 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.30975 + cpu-wattage: 29.907142857142862 + cpu-wattage-times-duration: 192.25 + cpu-energy-raw: 0.00005340277777777778 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006675347222222222 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.005340277777777777 + carbon: 0.044977517757483515 + sci: 0.004699143646304248 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 12 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 8.428571428571429 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 18.50952380952381 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.0000064887152777777775 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005318601447686367 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + requests: 5 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 9 + requests: 3 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.22425 + cpu-wattage: 3.7375 + cpu-wattage-times-duration: 112.125 + cpu-energy-raw: 0.000031145833333333336 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000003893229166666667 + embodied-carbon: 0.02378234398782344 + carbon-operational: 0.0031145833333333334 + carbon: 0.02689692732115677 + sci: 0.00896564244038559 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 0 + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.38611984715880265 + outputs: + - carbon: 0.045276128868594626 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.044977517757483515 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02689692732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.38611984715880265 + outputs: + - carbon: 0.045276128868594626 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.044977517757483515 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02689692732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.38611984715880265 + child-2: + pipeline: + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + children: + uk-west: + children: + A1: + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 1 + cpu/utilization: 30 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 100 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:01.000Z' + duration: 5 + cpu/utilization: 28 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 150 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:06.000Z' + duration: 7 + cpu/utilization: 40 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 110 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + - timestamp: '2023-12-12T00:00:13.000Z' + duration: 30 + cpu/utilization: 33 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 180 + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cpu/utilization: 22.8 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 220 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.41509999999999997 + cpu-wattage: 94.57999999999998 + cpu-wattage-times-duration: 258.9 + cpu-energy-raw: 0.00007191666666666668 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000008989583333333334 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007191666666666666 + carbon: 0.046828906646372404 + sci: 0.00021285866657442002 + - timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cpu/utilization: 29.6 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 92.85714285714285 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.48819999999999997 + cpu-wattage: 46.98428571428572 + cpu-wattage-times-duration: 308.35 + cpu-energy-raw: 0.00008565277777777778 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000010706597222222223 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.008565277777777778 + carbon: 0.04820251775748351 + sci: 0.0005191040373882839 + - timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cpu/utilization: 30.6 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 59.14285714285714 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.49894999999999995 + cpu-wattage: 31.31738095238095 + cpu-wattage-times-duration: 306.2 + cpu-energy-raw: 0.00008505555555555556 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000010631944444444445 + embodied-carbon: 0.03963723997970574 + carbon-operational: 0.008505555555555556 + carbon: 0.04814279553526128 + sci: 0.0008140086201614227 + - timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cpu/utilization: 26.4 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 30 + cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.45380000000000004 + cpu-wattage: 9.454166666666667 + cpu-wattage-times-duration: 283.625 + cpu-energy-raw: 0.00007878472222222222 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000009848090277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.007878472222222222 + carbon: 0.04751571220192795 + sci: 0.0015838570733975983 + - timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cpu/utilization: 19.8 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 18 + cpu/thermal-design-power: 60 + grid/carbon-intensity: 480 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0.34035000000000004 + cpu-wattage: 5.6725 + cpu-wattage-times-duration: 170.175 + cpu-energy-raw: 0.00004727083333333333 + vcpu-ratio: 8 + cpu-energy-kwh: 0.000005908854166666666 + embodied-carbon: 0.02378234398782344 + carbon-operational: 0.004727083333333333 + carbon: 0.02850942732115677 + sci: 0.0015838570733975985 + - timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cpu/utilization: 0 + cloud/instance-type: A1 + cloud/region: uk-west + requests: 0 + cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + time-reserved: 1 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: 8 + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.4092622082699138 + outputs: + - carbon: 0.046828906646372404 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04820251775748351 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04814279553526128 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02850942732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.4092622082699138 + outputs: + - carbon: 0.046828906646372404 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04820251775748351 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04814279553526128 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.04751571220192795 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.02850942732115677 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.4092622082699138 + outputs: + - carbon: 0.09210503551496703 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.09318003551496702 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.09297100773718923 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0.0923439244038559 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0.05540635464231354 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.7953820554287163 diff --git a/manifests/outputs/pipelines/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/pipeline-with-mocks.yaml new file mode 100644 index 000000000..bd27a179a --- /dev/null +++ b/manifests/outputs/pipelines/pipeline-with-mocks.yaml @@ -0,0 +1,1187 @@ +name: pipeline-with-mocks +description: a full pipeline seeded with data from mock-observations feature +tags: null +aggregation: + metrics: + - carbon + type: both +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + config: + timestamp-from: '2023-12-12T00:00:00.000Z' + timestamp-to: '2023-12-12T00:00:13.000Z' + duration: 30 + components: + - cloud/instance-type: A1 + generators: + common: + cloud/region: uk-west + randint: + cpu/utilization: + min: 1 + max: 99 + parameter-metadata: + inputs: + timestamp: + unit: RFC3339 + description: refers to the time of occurrence of the input + aggregation-method: + time: none + component: none + duration: + unit: seconds + description: refers to the duration of the input + aggregation-method: + time: sum + component: sum + cloud/instance-type: + unit: none + description: type of Cloud Instance name used in the cloud provider APIs + aggregation-method: + time: none + component: none + cloud/region: + unit: none + description: region cloud instance + aggregation-method: + time: none + component: none + interpolate: + path: builtin + method: Interpolation + config: + method: linear + x: + - 0 + - 10 + - 50 + - 100 + 'y': + - 0.12 + - 0.32 + - 0.75 + - 1.02 + input-parameter: cpu/utilization + output-parameter: cpu-factor + parameter-metadata: + inputs: + cpu/utilization: + unit: percentage + description: refers to CPU utilization. + aggregation-method: + time: avg + component: avg + outputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu-factor-to-wattage: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-factor + - cpu/thermal-design-power + output-parameter: cpu-wattage + parameter-metadata: + inputs: + cpu-factor: + unit: kWh + description: result of interpolate + aggregation-method: + time: avg + component: avg + cpu/thermal-design-power: + unit: kWh + description: thermal design power for a processor + aggregation-method: + time: avg + component: avg + outputs: + cpu-wattage: + unit: kWh + description: the energy used by the CPU + aggregation-method: + time: sum + component: sum + wattage-times-duration: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-wattage + - duration + output-parameter: cpu-wattage-times-duration + parameter-metadata: + inputs: + cpu-wattage: + unit: kWh + description: Energy used by the CPU + aggregation-method: + time: sum + component: sum + duration: + unit: seconds + description: Duration of the observation + aggregation-method: + time: sum + component: sum + outputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + wattage-to-energy-kwh: + path: builtin + method: Divide + config: + numerator: cpu-wattage-times-duration + denominator: 3600000 + output: cpu-energy-raw + parameter-metadata: + inputs: + cpu-wattage-times-duration: + unit: kWh + description: CPU wattage multiplied by duration + aggregation-method: + time: sum + component: sum + outputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + calculate-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: vcpus-total + denominator: vcpus-allocated + output: vcpu-ratio + parameter-metadata: + inputs: + vcpus-total: + unit: count + description: total number of vcpus available on a particular resource + aggregation-method: + time: none + component: none + vcpus-allocated: + unit: count + description: number of vcpus allocated to particular resource + aggregation-method: + time: none + component: none + outputs: + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: none + component: none + correct-cpu-energy-for-vcpu-ratio: + path: builtin + method: Divide + config: + numerator: cpu-energy-raw + denominator: vcpu-ratio + output: cpu-energy-kwh + parameter-metadata: + inputs: + cpu-energy-raw: + unit: kWh + description: Raw energy used by CPU in kWh + aggregation-method: + time: sum + component: sum + vcpu-ratio: + unit: none + description: Ratio of vCPUs + aggregation-method: + time: none + component: none + outputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + sci-embodied: + path: builtin + method: SciEmbodied + operational-carbon: + path: builtin + method: Multiply + config: + input-parameters: + - cpu-energy-kwh + - grid/carbon-intensity + output-parameter: carbon-operational + parameter-metadata: + inputs: + cpu-energy-kwh: + unit: kWh + description: Corrected CPU energy in kWh + aggregation-method: + time: sum + component: sum + grid/carbon-intensity: + unit: gCO2eq/kWh + description: Carbon intensity for the grid + aggregation-method: + time: avg + component: avg + outputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + sum-carbon: + path: builtin + method: Sum + config: + input-parameters: + - carbon-operational + - embodied-carbon + output-parameter: carbon + parameter-metadata: + inputs: + carbon-operational: + unit: gCO2eq + description: Operational carbon footprint + aggregation-method: + time: sum + component: sum + embodied-carbon: + unit: gCO2eq + description: Embodied carbon footprint + aggregation-method: + time: sum + component: sum + outputs: + carbon: + unit: gCO2eq + description: Total carbon footprint + aggregation-method: + time: sum + component: sum + sci: + path: builtin + method: Sci + config: + functional-unit: requests + parameter-metadata: + inputs: + requests: + unit: none + description: expressed the final SCI value + aggregation-method: + time: sum + component: sum + outputs: + sci: + unit: none + description: Scientific Carbon Intensity + aggregation-method: + time: none + component: none + time-sync: + path: builtin + method: TimeSync + config: + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' + interval: 5 + allow-padding: true +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/pipeline-with-mocks.yml -o + manifests/outputs/pipelines/pipeline-with-mocks.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:14:02.702Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + requests: 50 + children: + uk-west: + children: + A1: + inputs: + - cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + requests: 50 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 89 + outputs: + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 71.2 + cpu-factor: 0.76848 + cpu-wattage: 16.009999999999998 + cpu-wattage-times-duration: 480.3 + cpu-energy-raw: 0.00013341666666666667 + vcpu-ratio: null + cpu-energy-kwh: 0.000016677083333333333 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.013341666666666668 + carbon: 0.0529789066463724 + sci: 0.006357468797564688 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.3178734398782344 + outputs: + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.3178734398782344 + outputs: + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.0529789066463724 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.3178734398782344 + child-2: + pipeline: + observe: + - mock-observations + regroup: + - cloud/region + - cloud/instance-type + compute: + - interpolate + - cpu-factor-to-wattage + - wattage-times-duration + - wattage-to-energy-kwh + - calculate-vcpu-ratio + - correct-cpu-energy-for-vcpu-ratio + - sci-embodied + - operational-carbon + - sum-carbon + - time-sync + - sci + defaults: + cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + requests: 50 + children: + uk-west: + children: + A1: + inputs: + - cpu/thermal-design-power: 100 + grid/carbon-intensity: 800 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: 8 + vcpus-allocated: 1 + requests: 50 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 30 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 15 + outputs: + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 80 + grid/carbon-intensity: 640 + device/emissions-embodied: 1533.12 + time-reserved: 3600 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 8.333333333333334 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 12 + cpu-factor: 0.29900000000000004 + cpu-wattage: 6.229166666666667 + cpu-wattage-times-duration: 186.875 + cpu-energy-raw: 0.00005190972222222223 + vcpu-ratio: null + cpu-energy-kwh: 0.000006488715277777778 + embodied-carbon: 0.03963723997970573 + carbon-operational: 0.005190972222222222 + carbon: 0.04482821220192795 + sci: 0.005379385464231354 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + - cpu/thermal-design-power: 0 + grid/carbon-intensity: 0 + device/emissions-embodied: 1533.12 + device/expected-lifespan: 94608000 + vcpus-total: null + vcpus-allocated: null + requests: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + cloud/instance-type: null + cloud/region: null + cpu/utilization: 0 + cpu-factor: 0 + cpu-wattage: 0 + cpu-wattage-times-duration: 0 + cpu-energy-raw: 0 + vcpu-ratio: null + cpu-energy-kwh: 0 + embodied-carbon: 0 + carbon-operational: 0 + carbon: 0 + sci: 0 + aggregated: + carbon: 0.2689692732115677 + outputs: + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.2689692732115677 + outputs: + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.04482821220192795 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.2689692732115677 + outputs: + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:00.000Z' + duration: 5 + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:05.000Z' + duration: 5 + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:10.000Z' + duration: 5 + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:15.000Z' + duration: 5 + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:20.000Z' + duration: 5 + - carbon: 0.09780711884830035 + timestamp: '2023-12-12T00:00:25.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:30.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:35.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:40.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:45.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:50.000Z' + duration: 5 + - carbon: 0 + timestamp: '2023-12-12T00:00:55.000Z' + duration: 5 + aggregated: + carbon: 0.5868427130898021 diff --git a/manifests/outputs/pipelines/scenario-3.yaml b/manifests/outputs/pipelines/scenario-3.yaml new file mode 100644 index 000000000..1f315baa4 --- /dev/null +++ b/manifests/outputs/pipelines/scenario-3.yaml @@ -0,0 +1,146 @@ +name: groupby +description: successful path +initialize: + plugins: + sum: + path: builtin + method: Sum + config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/scenario-3.yml -o + manifests/outputs/pipelines/scenario-3.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:43.098Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + my-app: + pipeline: + observe: null + regroup: + - cloud/instance-type + - cloud/region + compute: null + children: + uk-west: + children: + A1: + children: + uk-west: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 99 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-west + cpu/utilization: 12 + B1: + children: + uk-west: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-west + cpu/utilization: 1 + uk-east: + children: + A1: + children: + uk-east: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 9 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 23 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: A1 + cloud/region: uk-east + cpu/utilization: 12 + B1: + children: + uk-east: + inputs: + - timestamp: 2023-07-06T00:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 11 + - timestamp: 2023-07-06T05:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 67 + - timestamp: 2023-07-06T10:00 + duration: 300 + cloud/instance-type: B1 + cloud/region: uk-east + cpu/utilization: 1 diff --git a/manifests/outputs/pipelines/scenario-4.yaml b/manifests/outputs/pipelines/scenario-4.yaml new file mode 100644 index 000000000..fde5bcbf0 --- /dev/null +++ b/manifests/outputs/pipelines/scenario-4.yaml @@ -0,0 +1,105 @@ +name: demo +description: null +tags: null +initialize: + plugins: + sum: + path: builtin + method: Sum + config: + input-parameters: + - cpu/energy + - network/energy + output-parameter: energy-sum + coefficient: + path: builtin + method: Coefficient + config: + input-parameter: energy + coefficient: 2 + output-parameter: energy-doubled + multiply: + path: builtin + method: Multiply + config: + input-parameters: + - cpu/utilization + - duration + output-parameter: cpu-times-duration +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/scenario-4.yml -o + manifests/outputs/pipelines/scenario-4.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:40.278Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child-1: + pipeline: + observe: null + compute: + - sum + - coefficient + - multiply + defaults: + cpu/thermal-design-power: 100 + inputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + cpu/energy: 20 + network/energy: 10 + energy: 5 + outputs: + - timestamp: '2023-12-12T00:00:00.000Z' + cloud/instance-type: A1 + cloud/region: uk-west + duration: 1 + cpu/utilization: 50 + cpu/energy: 20 + network/energy: 10 + energy: 5 + cpu/thermal-design-power: 100 + energy-sum: 30 + energy-doubled: 10 + cpu-times-duration: 50 diff --git a/manifests/outputs/pipelines/scenario-5.yaml b/manifests/outputs/pipelines/scenario-5.yaml new file mode 100644 index 000000000..4e9e0f011 --- /dev/null +++ b/manifests/outputs/pipelines/scenario-5.yaml @@ -0,0 +1,125 @@ +name: demo +description: null +tags: null +initialize: + plugins: + mock-observations: + path: builtin + method: MockObservations + config: + timestamp-from: 2023-07-06T00:00 + timestamp-to: 2023-07-06T00:01 + duration: 60 + components: + - cloud/instance-type: A1 + - cloud/instance-type: B1 + generators: + common: + region: uk-west + common-key: common-val + randint: + cpu/utilization: + min: 1 + max: 99 + memory/utilization: + min: 1 + max: 99 + sum: + path: builtin + method: Sum + config: + input-parameters: + - cpu/utilization + - memory/utilization + output-parameter: util-sum +execution: + command: >- + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/examples/pipelines/scenario-5.yml -o + manifests/outputs/pipelines/scenario-5.yml + environment: + if-version: 0.6.0 + os: macOS + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-09-12T06:13:37.404Z (UTC) + dependencies: + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.22' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' + - axios-mock-adapter@1.22.0 + - axios@1.7.2 + - cross-env@7.0.3 + - csv-parse@5.5.6 + - csv-stringify@6.4.6 + - fixpack@4.0.0 + - gts@5.2.0 + - husky@8.0.3 + - jest@29.7.0 + - js-yaml@4.1.0 + - lint-staged@15.2.2 + - luxon@3.4.4 + - release-it@16.3.0 + - rimraf@5.0.5 + - ts-command-line-args@2.5.1 + - ts-jest@29.1.1 + - typescript-cubic-spline@1.0.1 + - typescript@5.2.2 + - winston@3.11.0 + - zod@3.23.8 + status: success +tree: + children: + child: + pipeline: + observe: + - mock-observations + regroup: + - cloud/instance-type + compute: + - sum + children: + A1: + inputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 65 + memory/utilization: 84 + outputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: A1 + region: uk-west + common-key: common-val + cpu/utilization: 65 + memory/utilization: 84 + util-sum: 149 + B1: + inputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 70 + memory/utilization: 82 + outputs: + - timestamp: '2023-07-06T00:00:00.000Z' + duration: 60 + cloud/instance-type: B1 + region: uk-west + common-key: common-val + cpu/utilization: 70 + memory/utilization: 82 + util-sum: 152 From 7251ade3056b3eef93c446f4b31d6db2bbcc2043 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:46:18 +0400 Subject: [PATCH 736/863] fix(manifests): remove unnecessary manifests --- manifests/examples/pipelines/scenario-1.yml | 34 -------------- manifests/examples/pipelines/scenario-2.yml | 52 --------------------- 2 files changed, 86 deletions(-) delete mode 100644 manifests/examples/pipelines/scenario-1.yml delete mode 100644 manifests/examples/pipelines/scenario-2.yml diff --git a/manifests/examples/pipelines/scenario-1.yml b/manifests/examples/pipelines/scenario-1.yml deleted file mode 100644 index 0c474fe67..000000000 --- a/manifests/examples/pipelines/scenario-1.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: demo -description: demo for observe feat -tags: -initialize: - plugins: - mock-observations: - kind: plugin - method: MockObservations - path: "builtin" - config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:01 - duration: 60 - components: - - cloud/instance-type: A1 - - cloud/instance-type: B1 - generators: - common: - region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - memory/utilization: - min: 1 - max: 99 -tree: - children: - child: - pipeline: - observe: - - mock-observations - inputs: null diff --git a/manifests/examples/pipelines/scenario-2.yml b/manifests/examples/pipelines/scenario-2.yml deleted file mode 100644 index 6f32afde6..000000000 --- a/manifests/examples/pipelines/scenario-2.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: regroup demo -description: -initialize: - plugins: - interpolate: - method: Interpolation - path: "builtin" - config: - method: linear - x: [0, 10, 50, 100] - y: [0.12, 0.32, 0.75, 1.02] - input-parameter: "cpu/utilization" - output-parameter: "cpu-factor" -tree: - children: - child: - pipeline: - observe: - regroup: - - cloud/region - - cloud/instance-type - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - - timestamp: 2023-07-06T00:00 # note this time restarts at the start timstamp - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 From f967f3bace152b012ef2e32e49fc38ea66b7c02c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:47:38 +0400 Subject: [PATCH 737/863] fix(scripts): fix script to create output manifests --- scripts/impact-test.sh | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/impact-test.sh b/scripts/impact-test.sh index 2cefa3d17..9bdd213c3 100755 --- a/scripts/impact-test.sh +++ b/scripts/impact-test.sh @@ -1,12 +1,23 @@ #!/bin/bash - + echo "Starting impact tests" -prefix="examples/manifests/"; -for file in examples/manifests/*; -do -echo "" -echo executing $file, outfile is ${file#"$prefix"} -echo "" -npx ts-node ./src --manifest $file --output examples/outputs/${file#"$prefix"} +prefix="manifests/examples" + +# Using find to traverse files recursively within the manifests/examples folder +find "$prefix" -type f | while read -r file; do + # Remove the prefix and store the output file path + outfile="${file#$prefix/}" + + echo "" + echo "Executing $file, outfile is $outfile" + echo "" + + # Ensure the output directory exists before running the command + output_dir="manifests/outputs/$(dirname "$outfile")" + mkdir -p "$output_dir" + + # Run the npm command with the correct file and output path + npm run if-run -- -m "$file" -o "$output_dir/$(basename "$outfile")" done + exit 0 From 02447e5a378b27b15891f0fc3e9f1f4878eaa09c Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 16:51:32 +0400 Subject: [PATCH 738/863] fix(doc): fix aggregation-method in readme files of plugins --- src/if-run/builtins/coefficient/README.md | 8 ++++++-- src/if-run/builtins/sum/README.md | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 38209f953..c79bdab7b 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -103,12 +103,16 @@ initialize: carbon: description: 'an amount of carbon emitted into the atmosphere' unit: 'gCO2e' - aggregation-method: sum + aggregation-method: + time: sum + component: sum outputs: carbon-product: description: 'a product of cabon property and the coefficient' unit: 'gCO2e' - aggregation-method: sum + aggregation-method: + time: sum + component: sum tree: children: child: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index c6ba6d0cb..66914b789 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -103,18 +103,28 @@ initialize: cpu/energy: description: energy consumed by the cpu unit: kWh - aggregation-method: sum - aggregation-method: sum + aggregation-method: + time: sum + component: sum + aggregation-method: + time: sum + component: sum network/energy: description: energy consumed by data ingress and egress unit: kWh - aggregation-method: sum - aggregation-method: sum + aggregation-method: + time: sum + component: sum + aggregation-method: + time: sum + component: sum outputs: energy: description: sum of energy components unit: kWh - aggregation-method: sum + aggregation-method: + time: sum + component: sum tree: children: child: From 2cd92a81208a5594e86ef3b526ee8ae605387307 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 12 Sep 2024 18:40:43 +0400 Subject: [PATCH 739/863] docs(builtins): fix `aggregation-method` description in the plugins readme files --- src/if-run/builtins/coefficient/README.md | 9 ++++++--- src/if-run/builtins/copy-param/README.md | 10 ++++++---- src/if-run/builtins/csv-lookup/README.md | 10 ++++++---- src/if-run/builtins/divide/README.md | 10 ++++++---- src/if-run/builtins/exponent/README.md | 10 ++++++---- src/if-run/builtins/interpolation/README.md | 10 ++++++---- src/if-run/builtins/mock-observations/README.md | 10 ++++++---- src/if-run/builtins/multiply/README.md | 10 ++++++---- src/if-run/builtins/regex/README.md | 10 ++++++---- src/if-run/builtins/sci/README.md | 10 ++++++---- src/if-run/builtins/shell/README.md | 10 ++++++---- src/if-run/builtins/subtract/README.md | 10 ++++++---- src/if-run/builtins/sum/README.md | 10 ++++++---- 13 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index c79bdab7b..3d19dc4a1 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -25,12 +25,15 @@ of the parameters of the inputs and outputs - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe parameters of the `output-parameter` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 331c95e95..224c21703 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -47,13 +47,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameters of the `to` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 72ac25bab..0e77ce0ff 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -61,13 +61,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameters in the `output` of the config block. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 7280a94fd..1d57784a1 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -20,13 +20,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `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 - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index 4065e9ae3..d918b4dad 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -24,13 +24,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes:: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index 35ef4df5e..c7b1876f2 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -33,13 +33,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameters of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index b95da0bab..da2444147 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -25,13 +25,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the output parameters. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 36d03e4c5..43d189fad 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -23,13 +23,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 1d2a9ca00..246dad3dd 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -24,13 +24,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameters of the `output` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 10f9e5fea..0ccd5ff94 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -16,14 +16,16 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the `sci` parameter which has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index 2357e46c2..d5e51a18e 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -30,13 +30,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the output parameter. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Inputs The parameters included in the `inputs` field in the `manifest` depend entirely on the plugin itself. A typical plugin might expect the following common data to be provided as `inputs`: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index e19e873ec..11d2573ef 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -23,13 +23,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 66914b789..794b6bac7 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -23,13 +23,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - - `aggregation-method`: aggregation method of the parameter (it can be `sum`, `avg` or `none`) - + - `aggregation-method`: aggregation method object of the parameter + - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: From ca6b5235f75fd88e3305a3d87f6b266d5808f98a Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 6 Sep 2024 18:20:15 +0400 Subject: [PATCH 740/863] feat(builtins): add inline arithmetic logic into plugins Signed-off-by: manushak --- src/if-run/builtins/coefficient/index.ts | 85 ++++++++++++++++----- src/if-run/builtins/copy-param/index.ts | 57 +++++++++----- src/if-run/builtins/divide/index.ts | 75 ++++++++++++------ src/if-run/builtins/exponent/index.ts | 84 +++++++++++++++----- src/if-run/builtins/interpolation/index.ts | 52 ++++++++++--- src/if-run/builtins/multiply/index.ts | 36 ++++++--- src/if-run/builtins/sci-embodied/index.ts | 84 +++++++++++++++----- src/if-run/builtins/sci/index.ts | 65 +++++++++++----- src/if-run/builtins/subtract/index.ts | 44 ++++++++--- src/if-run/builtins/sum/index.ts | 46 ++++++++--- src/if-run/builtins/time-converter/index.ts | 72 +++++++++++++---- src/if-run/builtins/time-sync/index.ts | 27 ++++--- 12 files changed, 540 insertions(+), 187 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 0a002f67a..fc0142f16 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,5 +1,12 @@ -import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import {z, ZodType} from 'zod'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + getParameterFromArithmeticExpression, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -34,17 +41,30 @@ export const Coefficient = ( * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const inputParameter = safeGlobalConfig['input-parameter']; - const outputParameter = safeGlobalConfig['output-parameter']; - const coefficient = safeGlobalConfig['coefficient']; - + const safeConfig = validateConfig(); + const { + 'input-parameter': inputParameter, + 'output-parameter': outputParameter, + } = safeConfig; return inputs.map(input => { - validateSingleInput(input, inputParameter); + const calculatedConfig = evaluateConfig({ + config: safeConfig, + input, + parametersToEvaluate: ['input-parameter', 'coefficient'], + }); + + const safeInput = validateSingleInput(input, inputParameter); + const coefficient = Number(calculatedConfig['coefficient']); + const calculatedResult = calculateProduct( + safeInput, + calculatedConfig['input-parameter'], + coefficient + ); const result = { ...input, - [outputParameter]: calculateProduct(input, inputParameter, coefficient), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); @@ -54,14 +74,21 @@ export const Coefficient = ( /** * Checks for required fields in input. */ - const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const validateSingleInput = ( + input: PluginParams, + configInputParameter: string + ) => { + const inputParameter = + getParameterFromArithmeticExpression(configInputParameter); + const evaluatedInput = evaluateInput(input); + const inputData = { - 'input-parameter': input[inputParameter], + [inputParameter]: evaluatedInput[inputParameter], }; const validationSchema = z.record(z.string(), z.number()); validate(validationSchema, inputData); - return input; + return evaluatedInput; }; /** @@ -69,9 +96,11 @@ export const Coefficient = ( */ const calculateProduct = ( input: PluginParams, - inputParameter: string, + inputParameter: string | number, coefficient: number - ) => input[inputParameter] * coefficient; + ) => + (isNaN(Number(inputParameter)) ? input[inputParameter] : inputParameter) * + coefficient; /** * Checks config value are valid. @@ -83,13 +112,27 @@ export const Coefficient = ( const mappedConfig = mapConfigIfNeeded(config, mapping); - const configSchema = z.object({ - coefficient: z.number(), - 'input-parameter': z.string().min(1), - 'output-parameter': z.string().min(1), - }); - - return validate>(configSchema, mappedConfig); + const configSchema = z + .object({ + coefficient: z.preprocess( + value => validateArithmeticExpression('coefficient', value), + z.number() + ), + 'input-parameter': z.string().min(1), + 'output-parameter': z.string().min(1), + }) + .refine(params => { + Object.entries(params).forEach(([param, value]) => + validateArithmeticExpression(param, value) + ); + + return true; + }); + + return validate>( + configSchema as ZodType, + mappedConfig + ); }; return { diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index fec1fd850..d10fb5546 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,5 +1,11 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -60,43 +66,54 @@ export const Copy = ( */ const validateSingleInput = ( input: PluginParams, - inputParameters: (string | number)[] + configInputParameter: string | number ) => { - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = input[param]; - - return acc; - }, - {} as Record + const inputParameter = getParameterFromArithmeticExpression( + configInputParameter.toString() ); + const evaluatedInput = evaluateInput(input); + const inputData = { + [inputParameter]: evaluatedInput[inputParameter], + }; const validationSchema = z.record(z.string(), z.string().or(z.number())); validate(validationSchema, inputData); - return input; + return evaluatedInput; }; const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const keepExisting = safeGlobalConfig['keep-existing'] === true; - const from = safeGlobalConfig['from']; - const to = safeGlobalConfig['to']; + const safeConfig = validateConfig(); + const keepExisting = safeConfig['keep-existing'] === true; + const from = safeConfig['from']; + const to = safeConfig['to']; return inputs.map(input => { - const safeInput = validateSingleInput(input, [from]); + const evaluatedConfig = evaluateConfig({ + config: safeConfig, + input, + parametersToEvaluate: ['from'], + }); + + const safeInput = validateSingleInput(input, from); + const safeFrom = getParameterFromArithmeticExpression(from.toString()); + + const outputValue = !isNaN(evaluatedConfig?.from) + ? evaluatedConfig.from + : safeInput[safeFrom]; - const outputValue = safeInput[from]; - if (safeInput[from]) { + if (safeInput[safeFrom]) { if (!keepExisting) { - delete safeInput[from]; + delete input[safeFrom]; + delete safeInput[safeFrom]; } } const result = { - ...safeInput, // need to return or what you provide won't be outputted, don't be evil! - [to]: outputValue, + ...input, + ...safeInput, + ...evaluateArithmeticOutput(to, outputValue), }; return mapOutputIfNeeded(result, mapping); diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 767fd1d6d..07ab3ba8a 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -1,5 +1,12 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -34,19 +41,25 @@ export const Divide = ( * Calculate the division of each input parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const {numerator, denominator, output} = safeGlobalConfig; + const safeConfig = validateConfig(); + const {numerator, denominator, output} = safeConfig; return inputs.map((input, index) => { - const safeInput = Object.assign( - {}, + const evaluatedConfig = evaluateConfig({ + config: safeConfig, input, - validateSingleInput(input, {numerator, denominator}) - ); + parametersToEvaluate: ['numerator', 'denominator'], + }); + const safeInput = validateSingleInput(input, safeConfig); + const calculatedResult = calculateDivide(safeInput, index, { + numerator: evaluatedConfig.numerator || numerator, + denominator: evaluatedConfig.denominator || denominator, + }); const result = { ...input, - [output]: calculateDivide(safeInput, index, {numerator, denominator}), + ...safeInput, + ...evaluateArithmeticOutput(output, calculatedResult), }; return mapOutputIfNeeded(result, mapping); @@ -62,11 +75,19 @@ export const Divide = ( } const mappedConfig = mapConfigIfNeeded(config, mapping); - const schema = z.object({ - numerator: z.string().min(1), - denominator: z.string().or(z.number()), - output: z.string(), - }); + const schema = z + .object({ + numerator: z.string().min(1), + denominator: z.string().or(z.number()), + output: z.string(), + }) + .refine(params => { + Object.entries(params).forEach(([param, value]) => + validateArithmeticExpression(param, value) + ); + + return true; + }); return validate>(schema, mappedConfig); }; @@ -76,12 +97,14 @@ export const Divide = ( */ const validateSingleInput = ( input: PluginParams, - params: { - numerator: string; - denominator: number | string; - } + safeConfig: ConfigParams ) => { - const {numerator, denominator} = params; + const numerator = getParameterFromArithmeticExpression( + safeConfig.numerator + ); + const denominator = getParameterFromArithmeticExpression( + safeConfig.denominator + ); const schema = z .object({ @@ -96,7 +119,8 @@ export const Divide = ( return true; }); - return validate>(schema, input); + const evaluatedInput = evaluateInput(input); + return validate>(schema, evaluatedInput); }; /** @@ -106,19 +130,24 @@ export const Divide = ( input: PluginParams, index: number, params: { - numerator: string; + numerator: number | string; denominator: number | string; } ) => { const {denominator, numerator} = params; - const finalDenominator = input[denominator] || denominator; + const finalDenominator = + typeof denominator === 'number' + ? denominator + : input[denominator] || denominator; + const finalNumerator = + typeof numerator === 'number' ? numerator : input[numerator]; if (finalDenominator === 0) { console.warn(ZERO_DIVISION(Divide.name, index)); - return input[numerator]; + return finalNumerator; } - return input[numerator] / finalDenominator; + return finalNumerator / finalDenominator; }; return { diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 199f44b17..500ea96a3 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -1,8 +1,16 @@ -import {z} from 'zod'; +import {z, ZodType} from 'zod'; import { mapConfigIfNeeded, mapOutputIfNeeded, } from '@grnsft/if-core/utils/helpers'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + getParameterFromArithmeticExpression, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { ExecutePlugin, PluginParams, @@ -10,7 +18,6 @@ import { PluginParametersMetadata, MappingParams, } from '@grnsft/if-core/types'; -import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; @@ -39,44 +46,82 @@ export const Exponent = ( } const mappedConfig = mapConfigIfNeeded(config, mapping); - const configSchema = z.object({ - 'input-parameter': z.string().min(1), - exponent: z.number(), - 'output-parameter': z.string().min(1), - }); - - return validate>(configSchema, mappedConfig); + const configSchema = z + .object({ + 'input-parameter': z.string().min(1), + exponent: z.preprocess( + value => validateArithmeticExpression('exponent', value), + z.number() + ), + 'output-parameter': z.string().min(1), + }) + .refine(params => { + Object.entries(params).forEach(([param, value]) => + validateArithmeticExpression(param, value) + ); + + return true; + }); + + return validate>( + configSchema as ZodType, + mappedConfig + ); }; /** * Checks for required fields in input. */ - const validateSingleInput = (input: PluginParams, inputParameter: string) => { + const validateSingleInput = ( + input: PluginParams, + configInputParameter: string | number + ) => { + const inputParameter = + typeof configInputParameter === 'number' + ? configInputParameter + : getParameterFromArithmeticExpression(configInputParameter); + const evaluatedInput = evaluateInput(input); + const inputData = { - 'input-parameter': input[inputParameter], + [inputParameter]: + typeof inputParameter === 'number' + ? inputParameter + : evaluatedInput[inputParameter], }; const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - return input; + return validate(validationSchema, inputData); }; /** * Calculate the input param raised by to the power of the given exponent. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + const safeConfig = validateConfig(); const { 'input-parameter': inputParameter, exponent, 'output-parameter': outputParameter, - } = validateConfig(); + } = safeConfig; return inputs.map(input => { - validateSingleInput(input, inputParameter); + const safeInput = validateSingleInput(input, inputParameter); + const evaluatedConfig = evaluateConfig({ + config: safeConfig, + input, + parametersToEvaluate: ['input-parameter', 'exponent'], + }); + + const calculatedResult = calculateExponent( + safeInput, + evaluatedConfig['input-parameter'] || inputParameter, + evaluatedConfig.exponent || exponent + ); const result = { ...input, - [outputParameter]: calculateExponent(input, inputParameter, exponent), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); @@ -88,10 +133,13 @@ export const Exponent = ( */ const calculateExponent = ( input: PluginParams, - inputParameter: string, + inputParameter: string | number, exponent: number ) => { - const base = input[inputParameter]; + const base = + typeof inputParameter === 'number' + ? inputParameter + : input[inputParameter]; return Math.pow(base, exponent); }; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index c7c9887f7..468c9d980 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -1,6 +1,13 @@ import Spline from 'typescript-cubic-spline'; import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -38,16 +45,22 @@ export const Interpolation = ( */ const execute = (inputs: PluginParams[]) => { const validatedConfig = validateConfig(); + const {'output-parameter': outputParameter} = validatedConfig; return inputs.map((input, index) => { + const calculatedConfig = evaluateConfig({ + config: validatedConfig, + input, + parametersToEvaluate: ['input-parameter'], + }); const safeInput = validateInput(input, index); + const calculatedResult = calculateResult(calculatedConfig, safeInput); + const result = { ...input, - [validatedConfig['output-parameter']]: calculateResult( - validatedConfig, - safeInput - ), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); @@ -74,7 +87,10 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[config['input-parameter']]; + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; @@ -104,7 +120,10 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[config['input-parameter']]; + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; const spline: any = new Spline(xPoints, yPoints); @@ -119,7 +138,10 @@ export const Interpolation = ( config: ConfigParams, input: PluginParams ) => { - const parameter = input[config['input-parameter']]; + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; const xPoints: number[] = config.x; const yPoints: number[] = config.y; @@ -154,7 +176,11 @@ export const Interpolation = ( method: z.nativeEnum(Method), x: z.array(z.number()), y: z.array(z.number()), - 'input-parameter': z.string(), + 'input-parameter': z + .string() + .refine(param => + validateArithmeticExpression('input-parameter', param) + ), 'output-parameter': z.string(), }) .refine(data => data.x && data.y && data.x.length === data.y.length, { @@ -182,7 +208,10 @@ export const Interpolation = ( * Validates inputes parameters. */ const validateInput = (input: PluginParams, index: number) => { - const inputParameter = config['input-parameter']; + const inputParameter = getParameterFromArithmeticExpression( + config['input-parameter'] + ); + const schema = z .object({ timestamp: z.string().or(z.date()), @@ -198,7 +227,8 @@ export const Interpolation = ( } ); - return validate>(schema, input, index); + const evaluatedInput = evaluateInput(input); + return validate>(schema, evaluatedInput, index); }; return { diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 530cb77a1..a701f9b4e 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -1,5 +1,10 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateArithmeticOutput, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -42,7 +47,12 @@ export const Multiply = ( const configSchema = z.object({ 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), + 'output-parameter': z + .string() + .min(1) + .refine(param => + validateArithmeticExpression('output-parameter', param) + ), }); return validate>(configSchema, mappedConfig); @@ -55,9 +65,11 @@ export const Multiply = ( input: PluginParams, inputParameters: string[] ) => { + const evaluatedInput = evaluateInput(input); + const inputData = inputParameters.reduce( (acc, param) => { - acc[param] = input[param]; + acc[param] = evaluatedInput[param]; return acc; }, @@ -66,25 +78,27 @@ export const Multiply = ( const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; + return validate(validationSchema, inputData); }; /** * Calculate the product of each input parameter. */ const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeGlobalConfig = validateConfig(); - const inputParameters = safeGlobalConfig['input-parameters']; - const outputParameter = safeGlobalConfig['output-parameter']; + const safeConfig = validateConfig(); + const { + 'input-parameters': inputParameters, + 'output-parameter': outputParameter, + } = safeConfig; return inputs.map(input => { - validateSingleInput(input, inputParameters); + const safeInput = validateSingleInput(input, inputParameters); + const calculatedResult = calculateProduct(safeInput, inputParameters); const result = { ...input, - [outputParameter]: calculateProduct(input, inputParameters), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 2b3c4ccfa..c86dbd718 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,5 +1,11 @@ import {z, ZodType} from 'zod'; +import { + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapInputIfNeeded, @@ -77,28 +83,63 @@ export const SciEmbodied = ( /** * Checks for required fields in input. */ - const validateConfig = () => { + const validateConfig = (input: PluginParams) => { const schema = z.object({ - 'baseline-vcpus': z.number().gte(0).default(1), - 'baseline-memory': z.number().gte(0).default(16), - 'baseline-emissions': z.number().gte(0).default(1000000), - lifespan: z.number().gt(0).default(126144000), - 'vcpu-emissions-constant': z.number().gte(0).default(100000), - 'memory-emissions-constant': z - .number() - .gte(0) - .default(533 / 384), - 'ssd-emissions-constant': z.number().gte(0).default(50000), - 'hdd-emissions-constant': z.number().gte(0).default(100000), - 'gpu-emissions-constant': z.number().gte(0).default(150000), + 'baseline-vcpus': z.preprocess( + value => validateArithmeticExpression('baseline-vcpus', value), + z.number().gte(0).default(1) + ), + 'baseline-memory': z.preprocess( + value => validateArithmeticExpression('baseline-memory', value), + z.number().gte(0).default(16) + ), + 'baseline-emissions': z.preprocess( + value => validateArithmeticExpression('baseline-emissions', value), + z.number().gte(0).default(1000000) + ), + lifespan: z.preprocess( + value => validateArithmeticExpression('lifespan', value), + z.number().gt(0).default(126144000) + ), + 'vcpu-emissions-constant': z.preprocess( + value => validateArithmeticExpression('vcpu-emissions-constant', value), + z.number().gte(0).default(100000) + ), + 'memory-emissions-constant': z.preprocess( + value => + validateArithmeticExpression('memory-emissions-constant', value), + z + .number() + .gte(0) + .default(533 / 384) + ), + 'ssd-emissions-constant': z.preprocess( + value => validateArithmeticExpression('ssd-emissions-constant', value), + z.number().gte(0).default(50000) + ), + 'hdd-emissions-constant': z.preprocess( + value => validateArithmeticExpression('hdd-emissions-constant', value), + z.number().gte(0).default(100000) + ), + 'gpu-emissions-constant': z.preprocess( + value => validateArithmeticExpression('gpu-emissions-constant', value), + z.number().gte(0).default(150000) + ), 'output-parameter': z.string().optional(), }); const mappedConfig = mapConfigIfNeeded(config, mapping); + const evaluatedConfig = evaluateConfig({ + config: mappedConfig, + input, + parametersToEvaluate: Object.keys(config).filter( + key => key !== 'output-parameter' + ), + }); return validate>( schema as ZodType, - mappedConfig + evaluatedConfig ); }; @@ -117,7 +158,11 @@ export const SciEmbodied = ( time: z.number().gt(0).optional(), }); - return validate>(schema as ZodType, input); + const evaluatedInput = evaluateInput(input); + return validate>( + schema as ZodType, + evaluatedInput + ); }; /** @@ -126,9 +171,8 @@ export const SciEmbodied = ( * 3. Calculates total embodied carbon by substracting and the difference between baseline server and given one. */ const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - return inputs.map(input => { + const safeConfig = validateConfig(input); const mappedInput = mapInputIfNeeded(input, mapping); const safeInput = validateInput(mappedInput); @@ -157,9 +201,13 @@ export const SciEmbodied = ( const embodiedCarbonKey = safeConfig['output-parameter'] || 'embodied-carbon'; + const result = { ...input, - [embodiedCarbonKey]: totalEmbodiedScaledByUsageAndTime, + ...evaluateArithmeticOutput( + embodiedCarbonKey, + totalEmbodiedScaledByUsageAndTime + ), }; return mapOutputIfNeeded(result, mapping); diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 407621b86..7c1c7d08e 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -1,7 +1,15 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapInputIfNeeded, + mapConfigIfNeeded, mapOutputIfNeeded, } from '@grnsft/if-core/utils/helpers'; import { @@ -68,55 +76,76 @@ export const Sci = ( throw new ConfigError(MISSING_CONFIG); } + const mappedConfig = mapConfigIfNeeded(config, mapping); const schema = z .object({ - 'functional-unit': z.string(), + 'functional-unit': z + .string() + .refine(param => + validateArithmeticExpression('functional-unit', param) + ), }) .refine(data => data['functional-unit'], { message: MISSING_FUNCTIONAL_UNIT_CONFIG, }); - return validate>(schema, config); + return validate>(schema, mappedConfig); }; /** * Calculate the total emissions for a list of inputs. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + const safeConfig = validateConfig(); + return inputs.map((input, index) => { - const mappedInput = mapInputIfNeeded(input, mapping); - const safeInput = validateInput(mappedInput); - const functionalUnit = input[config['functional-unit']]; + const safeInput = Object.assign( + {}, + input, + validateInput(input, safeConfig) + ); + + const evaluatedConfig = evaluateConfig({ + config: safeConfig, + input: safeInput, + parametersToEvaluate: ['functional-unit'], + }); + const functionalUnit = isNaN(evaluatedConfig['functional-unit']) + ? safeInput[evaluatedConfig['functional-unit']] + : evaluatedConfig['functional-unit']; if (functionalUnit === 0) { console.warn(ZERO_DIVISION(Sci.name, index)); return { ...input, + ...safeInput, sci: safeInput['carbon'], }; } + const calculatedResult = safeInput['carbon'] / functionalUnit; const result = { ...input, - sci: safeInput['carbon'] / functionalUnit, + ...safeInput, + ...evaluateArithmeticOutput('sci', calculatedResult), }; return mapOutputIfNeeded(result, mapping); }); }; + /** * Checks for fields in input. */ - const validateInput = (input: PluginParams) => { - const validatedConfig = validateConfig(); - - if ( - !( - validatedConfig['functional-unit'] in input && - input[validatedConfig['functional-unit']] >= 0 - ) - ) { + const validateInput = (input: PluginParams, safeConfig: ConfigParams) => { + const mappedInput = mapInputIfNeeded(input, mapping); + + const functionalUnit = getParameterFromArithmeticExpression( + safeConfig['functional-unit'] + ); + + if (!(functionalUnit in mappedInput && mappedInput[functionalUnit] >= 0)) { throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); } @@ -129,7 +158,9 @@ export const Sci = ( message: SCI_MISSING_FN_UNIT(config['functional-unit']), }); - return validate>(schema, input); + const evaluatedInput = evaluateInput(mappedInput); + + return validate>(schema, evaluatedInput); }; return { diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 5051017c5..8d4524641 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -1,5 +1,11 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -42,7 +48,12 @@ export const Subtract = ( const configSchema = z.object({ 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), + 'output-parameter': z + .string() + .min(1) + .refine(value => + validateArithmeticExpression('output-parameter', value) + ), }); return validate>(configSchema, mappedConfig); @@ -55,9 +66,11 @@ export const Subtract = ( input: PluginParams, inputParameters: string[] ) => { + const evaluatedInput = evaluateInput(input); + const inputData = inputParameters.reduce( (acc, param) => { - acc[param] = input[param]; + acc[param] = evaluatedInput[param]; return acc; }, @@ -66,26 +79,39 @@ export const Subtract = ( const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; + return validate(validationSchema, inputData); }; /** * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam. */ const execute = (inputs: PluginParams[]): PluginParams[] => { + const safeConfig = validateConfig(); const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, - } = validateConfig(); + } = safeConfig; return inputs.map(input => { - validateSingleInput(input, inputParameters); + const calculatedConfig = evaluateConfig({ + config: safeConfig, + input, + parametersToEvaluate: safeConfig['input-parameters'], + }); + const safeInput = Object.assign( + {}, + input, + validateSingleInput(input, inputParameters) + ); + const calculatedResult = calculateDiff( + safeInput, + calculatedConfig['input-parameters'] || inputParameters + ); const result = { ...input, - [outputParameter]: calculateDiff(input, inputParameters), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 580821ddb..e111bce41 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -1,5 +1,11 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -34,16 +40,30 @@ export const Sum = ( * Calculate the sum of each input-paramters. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const inputParameters = safeGlobalConfig['input-parameters']; - const outputParameter = safeGlobalConfig['output-parameter']; + const safeConfig = validateConfig(); + const { + 'input-parameters': inputParameters, + 'output-parameter': outputParameter, + } = safeConfig; return inputs.map(input => { - validateSingleInput(input, inputParameters); + const safeInput = validateSingleInput(input, inputParameters); + + const calculatedConfig = evaluateConfig({ + config: safeConfig, + input, + parametersToEvaluate: config['input-parameters'], + }); + + const calculatedResult = calculateSum( + safeInput, + calculatedConfig['input-parameters'] || inputParameters + ); const result = { ...input, - [outputParameter]: calculateSum(input, inputParameters), + ...safeInput, + ...evaluateArithmeticOutput(outputParameter, calculatedResult), }; return mapOutputIfNeeded(result, mapping); @@ -62,7 +82,12 @@ export const Sum = ( const configSchema = z.object({ 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), + 'output-parameter': z + .string() + .min(1) + .refine(value => + validateArithmeticExpression('output-parameter', value) + ), }); return validate>(configSchema, mappedConfig); @@ -75,18 +100,17 @@ export const Sum = ( input: PluginParams, inputParameters: string[] ) => { + const evaluatedInput = evaluateInput(input); const inputData = inputParameters.reduce( (acc, param) => { - acc[param] = input[param]; + acc[param] = evaluatedInput[param]; return acc; }, {} as Record ); const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return input; + return validate(validationSchema, inputData); }; /** diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index c4b9ef577..8e82458ca 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -1,5 +1,12 @@ import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import { + ERRORS, + evaluateInput, + evaluateConfig, + evaluateArithmeticOutput, + validateArithmeticExpression, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import { mapConfigIfNeeded, mapOutputIfNeeded, @@ -33,16 +40,31 @@ export const TimeConverter = ( }; const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const inputParameter = safeGlobalConfig['input-parameter']; - const outputParameter = safeGlobalConfig['output-parameter']; + const safeConfig = validateConfig(); + const { + 'input-parameter': inputParameter, + 'output-parameter': outputParameter, + } = safeConfig; return inputs.map(input => { - validateInput(input, inputParameter); + const safeInput = Object.assign( + {}, + input, + validateInput(input, inputParameter) + ); + const calculatedConfig = evaluateConfig({ + config: safeConfig, + input: safeInput, + parametersToEvaluate: ['input-parameter'], + }); const result = { ...input, - [outputParameter]: calculateEnergy(input), + ...safeInput, + ...evaluateArithmeticOutput( + outputParameter, + calculateEnergy(safeInput, calculatedConfig['input-parameter']) + ), }; return mapOutputIfNeeded(result, mapping); @@ -52,14 +74,20 @@ export const TimeConverter = ( /** * Calculates the energy for given period. */ - const calculateEnergy = (input: PluginParams) => { + const calculateEnergy = ( + input: PluginParams, + inputParameter: string | number + ) => { const originalTimeUnit = config['original-time-unit']; const originalTimeUnitInSeoncds = TIME_UNITS_IN_SECONDS[originalTimeUnit]; - const energyPerPeriod = input[config['input-parameter']]; + const energyPerPeriod = isNaN(Number(inputParameter)) + ? input[inputParameter] + : inputParameter; const newTimeUnit = config['new-time-unit'] === 'duration' ? input.duration : TIME_UNITS_IN_SECONDS[config['new-time-unit']]; + const result = (energyPerPeriod / originalTimeUnitInSeoncds) * newTimeUnit; return Number(result.toFixed(6)); @@ -68,13 +96,17 @@ export const TimeConverter = ( /** * Checks for required fields in input. */ - const validateInput = (input: PluginParams, inputParameter: string) => { + const validateInput = (input: PluginParams, configInputParameter: string) => { + const inputParameter = + getParameterFromArithmeticExpression(configInputParameter); + const schema = z.object({ duration: z.number().gte(1), [inputParameter]: z.number(), }); - return validate>(schema, input); + const evaluatedInput = evaluateInput(input); + return validate>(schema, evaluatedInput); }; /** @@ -93,12 +125,20 @@ export const TimeConverter = ( ] as const; const originalTimeUnitValues = timeUnitsValues as [string, ...string[]]; - const configSchema = z.object({ - 'input-parameter': z.string(), - 'original-time-unit': z.enum(originalTimeUnitValues), - 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), - 'output-parameter': z.string().min(1), - }); + const configSchema = z + .object({ + 'input-parameter': z.string(), + 'original-time-unit': z.enum(originalTimeUnitValues), + 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), + 'output-parameter': z.string().min(1), + }) + .refine(params => { + Object.entries(params).forEach(([param, value]) => + validateArithmeticExpression(param, value) + ); + + return true; + }); return validate>(configSchema, config); }; diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index d85f08c32..1fecfebd8 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -2,7 +2,7 @@ import {isDate} from 'node:util/types'; import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; +import {ERRORS, evaluateInput} from '@grnsft/if-core/utils'; import { mapInputIfNeeded, mapOutputIfNeeded, @@ -117,14 +117,14 @@ export const TimeSync = ( /** Checks for timestamps overlap. */ if ( parseDate(previousInput.timestamp).plus({ - seconds: previousInput.duration, + seconds: eval(previousInput.duration), }) > currentMoment ) { throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); } const compareableTime = previousInputTimestamp.plus({ - seconds: previousInput.duration, + seconds: eval(previousInput.duration), }); const timelineGapSize = currentMoment @@ -137,14 +137,14 @@ export const TimeSync = ( ...getZeroishInputPerSecondBetweenRange( compareableTime, currentMoment, - input + safeInput ) ); } } /** Break down current observation. */ - for (let i = 0; i < input.duration; i++) { - const normalizedInput = breakDownInput(input, i); + for (let i = 0; i < safeInput.duration; i++) { + const normalizedInput = breakDownInput(safeInput, i); acc.push(normalizedInput); } @@ -199,7 +199,9 @@ export const TimeSync = ( duration: z.number(), }); - return validate>(schema, input); + const evaluatedInput = evaluateInput(input); + + return validate>(schema, evaluatedInput); }; /** @@ -246,7 +248,8 @@ export const TimeSync = ( * Breaks down input per minimal time unit. */ const breakDownInput = (input: PluginParams, i: number) => { - const inputKeys = Object.keys(input); + const evaluatedInput = evaluateInput(input); + const inputKeys = Object.keys(evaluatedInput); return inputKeys.reduce((acc, key) => { const method = getAggregationMethod(key); @@ -273,8 +276,8 @@ export const TimeSync = ( acc[key] = method === 'sum' - ? convertPerInterval(input[key], input['duration']) - : input[key]; + ? convertPerInterval(evaluatedInput[key], evaluatedInput['duration']) + : evaluatedInput[key]; return acc; }, {} as PluginParams); @@ -363,7 +366,7 @@ export const TimeSync = ( const lastInput = inputs[inputs.length - 1]; const endDiffInSeconds = parseDate(lastInput.timestamp) - .plus({second: lastInput.duration}) + .plus({second: eval(lastInput.duration)}) .diff(params.endTime) .as('seconds'); @@ -477,7 +480,7 @@ export const TimeSync = ( if (end) { const lastInput = inputs[inputs.length - 1]; const lastInputEnd = parseDate(lastInput.timestamp).plus({ - seconds: lastInput.duration, + seconds: eval(lastInput.duration), }); paddedArray.push( ...getZeroishInputPerSecondBetweenRange( From 796cf7eaa244234352ae6367fec3a9165adfbea6 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 6 Sep 2024 18:27:33 +0400 Subject: [PATCH 741/863] test(builtins): add tests related to inline arithmetic feature Signed-off-by: manushak --- .../if-run/builtins/coefficient.test.ts | 74 ++++++++++++- .../if-run/builtins/copy-param.test.ts | 30 ++++++ src/__tests__/if-run/builtins/divide.test.ts | 61 ++++++++++- .../if-run/builtins/exponent.test.ts | 100 +++++++++++++++++- .../if-run/builtins/interpolation.test.ts | 61 +++++++++++ .../if-run/builtins/multiply.test.ts | 85 ++++++++++++++- src/__tests__/if-run/builtins/regex.test.ts | 2 +- .../if-run/builtins/sci-embodied.test.ts | 88 +++++++++++++++ src/__tests__/if-run/builtins/sci.test.ts | 86 ++++++++++++++- .../if-run/builtins/subtract.test.ts | 88 ++++++++++++++- src/__tests__/if-run/builtins/sum.test.ts | 63 +++++++++++ .../if-run/builtins/time-converter.test.ts | 60 +++++++++++ .../if-run/builtins/time-sync.test.ts | 45 ++++++++ 13 files changed, 834 insertions(+), 9 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 0aa638d50..1d6152b55 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -3,6 +3,7 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Coefficient} from '../../../if-run/builtins/coefficient'; import {STRINGS} from '../../../if-run/config'; +import {CoefficientConfig} from '@grnsft/if-core/types'; const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; @@ -113,7 +114,78 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when global config is not provided.', () => { + it('successfully executes when a parameter has an arithmetic expression.', () => { + expect.assertions(1); + const config = { + 'input-parameter': '=3*carbon', + coefficient: 3, + 'output-parameter': 'carbon-product', + }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const coefficient = Coefficient(config, parametersMetadata, {}); + + const expectedResult = [ + { + duration: 3600, + carbon: 3, + 'carbon-product': 27, + 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 the `coefficient` has wrong arithmetic expression.', () => { + const config = { + 'input-parameter': 'carbon', + coefficient: 'mock-param', + 'output-parameter': 'carbon-product', + }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + const coefficient = Coefficient( + config as any as CoefficientConfig, + parametersMetadata, + {} + ); + + expect.assertions(2); + + try { + coefficient.execute([ + { + duration: 3600, + carbon: 'some-param', + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + '"coefficient" parameter is expected number, received string. Error code: invalid_type.' + ) + ); + } + }); + + it('throws an error when config is not provided.', () => { const config = undefined; const coefficient = Coefficient(config!, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index fcbd3155c..f7d0dea8e 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -177,6 +177,36 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); + + it('successfully executes when the `from` contains arithmetic expression', () => { + const config = { + 'keep-existing': false, + from: '=3*size', + to: 'if-size', + }; + const copy = Copy(config, parametersMetadata, {}); + + const inputs = [ + { + timestamp: '2024-07-05T13:45:48.398Z', + duration: 3600, + size: 0.05, + }, + ]; + + const expectedResult = [ + { + timestamp: '2024-07-05T13:45:48.398Z', + duration: 3600, + 'if-size': 0.15000000000000002, + }, + ]; + + expect.assertions(1); + const result = copy.execute(inputs); + + expect(result).toEqual(expectedResult); + }); }); }); }); diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index 10236e5c7..f81561f9f 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -107,7 +107,7 @@ describe('builtins/divide: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('returns a result when `denominator` is provded in input.', async () => { + it('returns a result when `denominator` is provided in input.', async () => { expect.assertions(1); const config = { numerator: 'vcpus-allocated', @@ -137,6 +137,65 @@ describe('builtins/divide: ', () => { expect(response).toEqual(expectedResult); }); + it('successfully executes when a parameter contains arithmetic expression.', () => { + expect.assertions(1); + + const config = { + numerator: '=3*"vcpus-allocated"', + denominator: 'duration', + output: 'vcpus-allocated-per-second', + }; + + const divide = Divide(config, parametersMetadata, {}); + const input = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]; + const response = divide.execute(input); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + 'vcpus-allocated-per-second': 72 / 3600, + }, + ]; + + expect(response).toEqual(expectedResult); + }); + + it('throws an error the `numerator` parameter has wrong arithmetic expression.', () => { + const config = { + numerator: '3*"vcpus-allocated"', + denominator: 'duration', + output: 'vcpus-allocated-per-second', + }; + + const divide = Divide(config, parametersMetadata, {}); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'vcpus-allocated': 24, + }, + ]; + expect.assertions(2); + try { + divide.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `numerator` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); + it('throws an error on missing params in input.', async () => { const expectedMessage = '"vcpus-allocated" parameter is required. Error code: invalid_type.'; diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index 89df469e0..d90a388c5 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -1,8 +1,12 @@ +import {ExponentConfig} from '@grnsft/if-core/types'; import {ERRORS} from '@grnsft/if-core/utils'; +import {STRINGS} from '../../../if-run/config'; import {Exponent} from '../../../if-run/builtins/exponent'; -const {InputValidationError} = ERRORS; +const {InputValidationError, ConfigError} = ERRORS; + +const {MISSING_CONFIG} = STRINGS; describe('builtins/exponent: ', () => { describe('Exponent: ', () => { @@ -124,7 +128,7 @@ describe('builtins/exponent: ', () => { } catch (error) { expect(error).toStrictEqual( new InputValidationError( - '"input-parameter" parameter is required. Error code: invalid_type.' + '"energy/base" parameter is required. Error code: invalid_type.' ) ); } @@ -145,7 +149,7 @@ describe('builtins/exponent: ', () => { } catch (error) { expect(error).toStrictEqual( new InputValidationError( - '"input-parameter" parameter is expected number, received string. Error code: invalid_type.' + '"energy/base" parameter is expected number, received string. Error code: invalid_type.' ) ); } @@ -180,6 +184,96 @@ describe('builtins/exponent: ', () => { expect(response).toEqual(expectedResult); }); + + it('successfully executes when a parameter contains arithmetic expression.', () => { + const config = { + 'input-parameter': "=2*'energy/base'", + exponent: 3, + 'output-parameter': 'energy', + }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + + const exponent = Exponent(config, parametersMetadata, {}); + + expect.assertions(1); + + const expectedResult = [ + { + duration: 3600, + 'energy/base': 4, + energy: 512, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = exponent.execute([ + { + duration: 3600, + 'energy/base': 4, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('throws an error when the `exponent` has wrong arithmetic expression.', () => { + const config = { + 'input-parameter': "=2*'energy/base'", + exponent: "3*'mock-param'", + 'output-parameter': 'energy', + }; + const parametersMetadata = { + inputs: {}, + outputs: {}, + }; + + const exponent = Exponent( + config as any as ExponentConfig, + parametersMetadata, + {} + ); + + expect.assertions(2); + + try { + exponent.execute([ + { + duration: 3600, + 'energy/base': 4, + timestamp: '2021-01-01T00:00:00Z', + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `exponent` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); + }); + + it('throws an error on missing config.', async () => { + const config = undefined; + const divide = Exponent(config!, parametersMetadata, {}); + + expect.assertions(1); + + try { + await divide.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); + } }); }); }); diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index f2fb7a44f..b3952903e 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -207,6 +207,67 @@ describe('builtins/interpolation: ', () => { expect(plugin.execute(inputs)).toEqual(outputs); }); + it('successfully executes when the config parameter contains an arithmetic expression.', () => { + const config = { + method: Method.LINEAR, + x: [0, 10, 50, 100], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': "=2*'cpu/utilization'", + 'output-parameter': 'interpolation-result', + }; + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 90, + }, + ]; + + const plugin = Interpolation(config, parametersMetadata, {}); + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 90, + 'interpolation-result': 0, + }, + ]; + + expect.assertions(1); + expect(plugin.execute(inputs)).toEqual(outputs); + }); + + it('throws an error the config parameter contains wrong arithmetic expression.', () => { + const config = { + method: Method.LINEAR, + x: [0, 10, 50, 100], + y: [0.12, 0.32, 0.75, 1.02], + 'input-parameter': "2*'cpu/utilization'", + 'output-parameter': 'interpolation-result', + }; + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 90, + }, + ]; + + const plugin = Interpolation(config, parametersMetadata, {}); + + expect.assertions(2); + try { + plugin.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `input-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); + it('throws an when the config is not provided.', () => { const config = undefined; const plugin = Interpolation(config!, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index 00979ea37..3d92b1d8d 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -1,8 +1,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Multiply} from '../../../if-run/builtins/multiply'; +import {STRINGS} from '../../../if-run/config'; -const {InputValidationError} = ERRORS; +const {InputValidationError, ConfigError} = ERRORS; + +const {MISSING_CONFIG} = STRINGS; describe('builtins/multiply: ', () => { describe('Multiply: ', () => { @@ -173,6 +176,86 @@ describe('builtins/multiply: ', () => { expect(response).toEqual(expectedResult); }); + + it('successfully executes when the config output parameter contains arithmetic expression.', () => { + expect.assertions(1); + + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': '=2*energy', + }; + const multiply = Multiply(config, parametersMetadata, {}); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + }, + ]; + const response = multiply.execute(inputs); + + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + energy: 16, + }, + ]; + + expect(response).toEqual(expectedResult); + }); + + it('throws an error the config output parameter has wrong arithmetic expression.', () => { + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': '2*energy', + }; + + const multiply = Multiply(config, parametersMetadata, {}); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 2, + 'network/energy': 2, + 'memory/energy': 2, + }, + ]; + expect.assertions(2); + try { + multiply.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); + + it('throws an error on missing config.', async () => { + const config = undefined; + const multiply = Multiply(config!, parametersMetadata, {}); + + expect.assertions(1); + + try { + await multiply.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); + } + }); }); }); }); diff --git a/src/__tests__/if-run/builtins/regex.test.ts b/src/__tests__/if-run/builtins/regex.test.ts index 49974d169..d509c8918 100644 --- a/src/__tests__/if-run/builtins/regex.test.ts +++ b/src/__tests__/if-run/builtins/regex.test.ts @@ -53,7 +53,7 @@ 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 config = { parameter: 'cloud/instance-type', match: '/(?<=_)[^_]+?(?=_|$)/g', diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 9014a0982..e79f55dc2 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -152,6 +152,94 @@ describe('builtins/sci-embodied:', () => { expect(error).toBeInstanceOf(InputValidationError); } }); + + it('successfully executes when a parameter contains arithmetic expression.', () => { + const config = { + 'baseline-vcpus': 1, + 'baseline-memory': 16, + lifespan: 157680000, + 'baseline-emissions': 2000000, + 'vcpu-emissions-constant': 100000, + 'memory-emissions-constant': 1172, + 'ssd-emissions-constant': 50000, + 'hdd-emissions-constant': 1 * 100000, + 'gpu-emissions-constant': '= 2 * "mock-param"', + 'output-parameter': 'embodied-carbon', + }; + const sciEmbodied = SciEmbodied(config, parametersMetadata, {}); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + vCPUs: 2, + 'mock-param': 150000, + }, + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + vCPUs: 4, + 'mock-param': 100000, + }, + ]; + + const result = sciEmbodied.execute(inputs); + + expect.assertions(1); + + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + vCPUs: 2, + 'embodied-carbon': 47.945205479452056, + 'mock-param': 150000, + }, + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + vCPUs: 4, + 'embodied-carbon': 52.51141552511416, + 'mock-param': 100000, + }, + ]); + }); + + it('throws an error the `gpu-emissions-constant` parameter has wrong arithmetic expression.', () => { + const config = { + 'baseline-vcpus': 1, + 'baseline-memory': 16, + lifespan: 157680000, + 'baseline-emissions': 2000000, + 'vcpu-emissions-constant': 100000, + 'memory-emissions-constant': 1172, + 'ssd-emissions-constant': 50000, + 'hdd-emissions-constant': 1 * 100000, + 'gpu-emissions-constant': '2 * "mock-param"', + 'output-parameter': 'embodied-carbon', + }; + const sciEmbodied = SciEmbodied(config, parametersMetadata, {}); + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + vCPUs: 2, + 'mock-param': 150000, + }, + ]; + + expect.assertions(2); + + try { + sciEmbodied.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `gpu-emissions-constant` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); }); }); }); diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index 0576b1e42..bd7378495 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -2,7 +2,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Sci} from '../../../if-run/builtins/sci'; -const {MissingInputDataError} = ERRORS; +import {STRINGS} from '../../../if-run/config'; + +const {MissingInputDataError, ConfigError, InputValidationError} = ERRORS; + +const {MISSING_CONFIG} = STRINGS; describe('builtins/sci:', () => { describe('Sci: ', () => { @@ -220,5 +224,85 @@ describe('builtins/sci:', () => { expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); }); + + it('throws an error on missing config.', () => { + const config = undefined; + const sci = Sci(config!, parametersMetadata, {}); + + expect.assertions(1); + + try { + sci.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); + } + }); + + it('successfully executes when a parameter contains arithmetic expression.', () => { + const config = {'functional-unit': '=10*users'}; + const sci = Sci(config, parametersMetadata, {}); + expect.assertions(1); + + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + duration: 1, + }, + ]; + const result = sci.execute(inputs); + + expect.assertions(1); + expect(result).toStrictEqual([ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + duration: 1, + // eslint-disable-next-line @typescript-eslint/no-loss-of-precision + sci: 0.0050199999999999995, + }, + ]); + }); + + it('throws an error the `functional-unit` parameter has wrong arithmetic expression.', () => { + const config = {'functional-unit': '10*users'}; + const sci = Sci(config, parametersMetadata, {}); + expect.assertions(1); + + const inputs = [ + { + timestamp: '2021-01-01T00:00:00Z', + 'carbon-operational': 0.02, + 'carbon-embodied': 5, + carbon: 5.02, + users: 100, + duration: 1, + }, + ]; + + expect.assertions(2); + + try { + sci.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `functional-unit` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); }); }); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index 3343e2abd..8cdb7b0a1 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -2,7 +2,11 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Subtract} from '../../../if-run/builtins/subtract'; -const {InputValidationError} = ERRORS; +import {STRINGS} from '../../../if-run/config'; + +const {InputValidationError, ConfigError} = ERRORS; + +const {MISSING_CONFIG} = STRINGS; describe('builtins/subtract: ', () => { describe('Subtract: ', () => { @@ -171,5 +175,87 @@ describe('builtins/subtract: ', () => { expect(response).toEqual(expectedResult); }); }); + + it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + expect.assertions(1); + + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': "= 2 * 'energy/diff'", + }; + const subtract = Subtract(config, parametersMetadata, {}); + + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 4, + 'network/energy': 2, + 'memory/energy': 1, + 'energy/diff': 2, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + const result = 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 the config output parameter has wrong arithmetic expression.', () => { + expect.assertions(2); + + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': "=2 & 'energy/diff'", + }; + const subtract = Subtract(config, parametersMetadata, {}); + + const inputs = [ + { + duration: 3600, + 'cpu/energy': 4, + 'network/energy': 2, + 'memory/energy': 1, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + try { + subtract.execute(inputs); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); + + it('throws an error on missing config.', async () => { + const config = undefined; + const subtract = Subtract(config!, parametersMetadata, {}); + + expect.assertions(1); + + try { + await subtract.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + }, + ]); + } catch (error) { + expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); + } + }); }); }); diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 30701c23f..1d0e928f2 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -199,6 +199,69 @@ describe('builtins/sum: ', () => { expect(response).toEqual(expectedResult); }); + + it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + expect.assertions(1); + + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': "=2*'energy'", + }; + + const sum = Sum(config, parametersMetadata, {}); + const expectedResult = [ + { + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + energy: 6, + timestamp: '2021-01-01T00:00:00Z', + }, + ]; + + 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 the config output parameter has wrong arithmetic expression.', () => { + expect.assertions(2); + + const config = { + 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], + 'output-parameter': "2*'energy'", + }; + + const sum = Sum(config, parametersMetadata, {}); + + try { + sum.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'cpu/energy': 1, + 'network/energy': 1, + 'memory/energy': 1, + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); }); }); }); diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index 646beb3b2..90664c64f 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -181,6 +181,66 @@ describe('builtins/time-converter: ', () => { expect(response).toEqual(expectedResult); }); + + it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + expect.assertions(1); + + const config = { + 'input-parameter': '=2 * "energy-per-year"', + 'original-time-unit': 'year', + 'new-time-unit': 'duration', + 'output-parameter': 'energy-per-duration', + }; + + const timeConverter = TimeConverter(config, parametersMetadata, {}); + const expectedResult = [ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + 'energy-per-duration': 2.281589, + }, + ]; + + const result = timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]); + + expect(result).toStrictEqual(expectedResult); + }); + + it('throws an error the config input parameter has wrong arithmetic expression.', () => { + expect.assertions(2); + const config = { + 'input-parameter': '2*"energy-per-year"', + 'original-time-unit': 'year', + 'new-time-unit': 'duration', + 'output-parameter': 'energy-per-duration', + }; + + const timeConverter = TimeConverter(config, parametersMetadata, {}); + + try { + timeConverter.execute([ + { + timestamp: '2021-01-01T00:00:00Z', + duration: 3600, + 'energy-per-year': 10000, + }, + ]); + } catch (error) { + expect(error).toBeInstanceOf(Error); + expect(error).toEqual( + new InputValidationError( + 'The `input-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + ) + ); + } + }); }); }); }); diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 0bfc59b5a..d1aa49076 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -864,6 +864,51 @@ describe('builtins/time-sync:', () => { ); expect(DateTime.fromISO(result[0].timestamp).offset === 0); }); + + it('successfully executes when the `duration` contains an arithmetic expression.', () => { + expect.assertions(1); + + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:10.000Z', + interval: 5, + 'allow-padding': true, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + + const result = timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 3, + 'resources-total': 10, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 3 * 2, + 'resources-total': 10, + }, + ]); + + const expectedResult = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + 'resources-total': null, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + 'resources-total': null, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 1, + 'resources-total': null, + }, + ]; + + expect(result).toStrictEqual(expectedResult); + }); }); }); }); From 27f6e27fe7c2fb2c49e2bb344583a33430bf78d8 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 9 Sep 2024 09:50:40 +0400 Subject: [PATCH 742/863] feat(package): update if-core version Signed-off-by: manushak --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca145548d..8687cc420 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.20", + "@grnsft/if-core": "^0.0.21", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.20.tgz", - "integrity": "sha512-D5P97E0O9qIw9Ok0qCcy3zmNl8j1sr/vwfPsueFzkbmF6ZnLDBL1vapn8MzSRFsp3lJoH/mStDZ3uf3+S1L17g==", + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.21.tgz", + "integrity": "sha512-zk50alrh3I9Sd+MKRcyo2srBmUUYIfU0Bm6dZ6nHaINR5DUACkDmA+z2ByCXQlHZJQM0y3K1FLjdG2Ug0tTd1A==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 802c9f138..698f18cfa 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.20", + "@grnsft/if-core": "^0.0.21", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 3e198bfda8bf6b6661216aa06fcaa9d4d1f1915b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:03:57 +0400 Subject: [PATCH 743/863] feat(config): add strings for explain feature Signed-off-by: manushak --- src/common/config/strings.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/config/strings.ts b/src/common/config/strings.ts index 82592463f..e5884852b 100644 --- a/src/common/config/strings.ts +++ b/src/common/config/strings.ts @@ -10,4 +10,8 @@ Incubation projects are experimental, offer no support guarantee, have minimal g SUCCESS_MESSAGE: 'The environment is successfully setup!', MANIFEST_IS_MISSING: 'Manifest is missing.', DIRECTORY_NOT_FOUND: 'Directory not found.', + AGGREGATION_UNITS_NOT_MATCH: (param: string) => + `Your manifest uses two instances of ${param} with different units. Please check that you are using consistent units for ${param} throughout your manifest.`, + AGGREGATION_METHODS_NOT_MATCH: (param: string) => + `Your manifest uses two instances of ${param} with different 'aggregation-method'. Please check that you are using right 'aggregation-method' for ${param} throughout your manifest.`, }; From ccec98110127bfd05b09152a691a42e90733638d Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:06:52 +0400 Subject: [PATCH 744/863] feat(lib): update explain feature logic Signed-off-by: manushak --- src/if-run/lib/explain.ts | 73 +++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index dce49b75a..eb42cfd49 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -1,26 +1,33 @@ -import {ExplainParams} from '../types/explain'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../common/config'; + +import {ExplainParams, ExplainStorageType} from '../types/explain'; + +const {ManifestValidationError} = ERRORS; +const {AGGREGATION_UNITS_NOT_MATCH, AGGREGATION_METHODS_NOT_MATCH} = STRINGS; /** * Retrieves stored explain data. */ -export const explain = () => storeExplainData.plugins; +export const explain = () => storeExplainData.parameters; /** * Manages the storage of explain data. */ const storeExplainData = (() => { - let plugin = {}; + let parameter: ExplainStorageType = {}; - const pluginManager = { - get plugins() { - return plugin; + const parameterManager = { + get parameters() { + return parameter; }, - set plugins(value: object) { - plugin = value; + set parameters(value: ExplainStorageType) { + parameter = value; }, }; - return pluginManager; + return parameterManager; })(); /** @@ -28,17 +35,45 @@ const storeExplainData = (() => { */ export const addExplainData = (params: ExplainParams) => { const {pluginName, pluginData, metadata} = params; - const plugin = { - [pluginName]: { - method: pluginData!.method, - path: pluginData!.path, - inputs: metadata?.inputs || 'undefined', - outputs: metadata?.outputs || 'undefined', - }, + const parameterMetadata = pluginData?.['parameter-metadata'] || metadata; + const parameters = storeExplainData.parameters; + const allParameters = { + ...parameterMetadata?.inputs, + ...parameterMetadata?.outputs, }; - storeExplainData.plugins = { - ...storeExplainData.plugins, - ...plugin, + Object.entries(allParameters).forEach(([name, meta]) => { + const existingParameter = parameters[name]; + + if (parameters[name]?.plugins?.includes(pluginName)) { + return; + } + + if (existingParameter) { + if (meta.unit !== existingParameter.unit) { + throw new ManifestValidationError(AGGREGATION_UNITS_NOT_MATCH(name)); + } + + if ( + meta['aggregation-method'] !== existingParameter['aggregation-method'] + ) { + throw new ManifestValidationError(AGGREGATION_METHODS_NOT_MATCH(name)); + } + + existingParameter.plugins.push(pluginName); + existingParameter.description = + meta.description || existingParameter.description; + } else { + parameters[name] = { + plugins: [pluginName], + unit: meta.unit, + description: meta.description, + 'aggregation-method': meta['aggregation-method'], + }; + } + }); + + storeExplainData.parameters = { + ...parameters, }; }; From cd877b133356a1e46ed04e2bb3945688b0d037da Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:11:05 +0400 Subject: [PATCH 745/863] feat(types): add `ExplainStorageType` type Signed-off-by: manushak --- src/if-run/types/explain.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index c7f1a6d38..c32f91325 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -7,3 +7,13 @@ export type ExplainParams = { pluginData: PluginOptions; metadata: {inputs?: ParameterMetadata; outputs?: ParameterMetadata}; }; + +export type ExplainStorageType = Record< + string, + { + plugins: string[]; + unit: string; + description: string; + 'aggregation-method': string; + } +>; From c4574a5d114855e4542c08df8618745a64eed624 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 28 Aug 2024 15:13:53 +0400 Subject: [PATCH 746/863] test(lib): update tests and add new ones Signed-off-by: manushak --- src/__tests__/if-run/lib/explain.test.ts | 196 ++++++++++++++++++++--- 1 file changed, 175 insertions(+), 21 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 506c62669..8178bf07d 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -1,8 +1,15 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ +import {ERRORS} from '@grnsft/if-core/utils'; + +import {STRINGS} from '../../../common/config'; + import {explain, addExplainData} from '../../../if-run/lib/explain'; +const {ManifestValidationError} = ERRORS; +const {AGGREGATION_UNITS_NOT_MATCH, AGGREGATION_METHODS_NOT_MATCH} = STRINGS; + describe('lib/explain: ', () => { - it('successfully adds explain data if `inputs` and `outputs` of `metadata` are `undefined`.', () => { + it('missing explain data if `inputs` and `outputs` of `metadata` are `undefined`.', () => { const mockData = { pluginName: 'divide', metadata: {kind: 'execute', inputs: undefined, outputs: undefined}, @@ -11,19 +18,11 @@ describe('lib/explain: ', () => { method: 'Divide', }, }; - const expectedResult = { - divide: { - method: 'Divide', - path: 'builtin', - inputs: 'undefined', - outputs: 'undefined', - }, - }; addExplainData(mockData); const result = explain(); expect.assertions(1); - expect(result).toEqual(expectedResult); + expect(result).toEqual({}); }); it('successfully adds explain data if `inputs` and `outputs` of `metadata` are valid data.', () => { @@ -56,36 +55,99 @@ describe('lib/explain: ', () => { method: 'Sum', }, }; + const expectedResult = { - divide: { - method: 'Divide', - path: 'builtin', - inputs: 'undefined', - outputs: 'undefined', + 'cpu/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', }, - sum: { - method: 'Sum', - path: 'builtin', + 'network/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', + }, + 'energy-sum': { + plugins: ['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); + }); + + it('successfully adds explain data if the parameter is using more than one plugin.', () => { + const mockData = { + pluginName: 'sum-energy', + metadata: { + kind: 'execute', inputs: { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', 'aggregation-method': 'sum', }, - 'network/energy': { + 'memory/energy': { unit: 'kWh', - description: 'energy consumed by data ingress and egress', + description: 'energy consumed by data from memory', 'aggregation-method': 'sum', }, }, outputs: { - 'energy-sum': { + 'total/energy': { unit: 'kWh', description: 'sum of energy components', 'aggregation-method': 'sum', }, }, }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + const expectedResult = { + 'cpu/energy': { + plugins: ['sum', 'sum-energy'], + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', + }, + 'network/energy': { + plugins: ['sum'], + unit: 'kWh', + description: 'energy consumed by data ingress and egress', + 'aggregation-method': 'sum', + }, + 'energy-sum': { + plugins: ['sum'], + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + 'memory/energy': { + plugins: ['sum-energy'], + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + 'total/energy': { + plugins: ['sum-energy'], + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, }; // @ts-ignore @@ -96,4 +158,96 @@ describe('lib/explain: ', () => { expect.assertions(1); expect(result).toEqual(expectedResult); }); + + it('throws an error if `unit` of the parameter is not matched.', () => { + const mockData = { + pluginName: 'sum-of-energy', + metadata: { + kind: 'execute', + inputs: { + 'cpu/energy': { + unit: 'co2q', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', + }, + 'memory/energy': { + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + }, + outputs: { + 'total/energy': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + }, + }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + expect.assertions(2); + try { + // @ts-ignore + addExplainData(mockData); + explain(); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ManifestValidationError); + expect(error.message).toEqual( + AGGREGATION_UNITS_NOT_MATCH('cpu/energy') + ); + } + } + }); + + it('throws an error if `aggregation-method` of the parameter is not matched.', () => { + const mockData = { + pluginName: 'sum-of-energy', + metadata: { + kind: 'execute', + inputs: { + 'cpu/energy': { + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'avg', + }, + 'memory/energy': { + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + }, + outputs: { + 'total/energy': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + }, + }, + pluginData: { + path: 'builtin', + method: 'Sum', + }, + }; + + expect.assertions(2); + try { + // @ts-ignore + addExplainData(mockData); + explain(); + } catch (error) { + if (error instanceof Error) { + expect(error).toBeInstanceOf(ManifestValidationError); + expect(error.message).toEqual( + AGGREGATION_METHODS_NOT_MATCH('cpu/energy') + ); + } + } + }); }); From 7d07ada265cd1d4a2097f2dc97189b4e6fd82797 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:34:31 +0400 Subject: [PATCH 747/863] fix(lib): change default aggregation method Signed-off-by: manushak --- src/if-run/lib/aggregate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index 43b84fcf6..a810ecc47 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -159,5 +159,5 @@ export const getAggregationMethod = (unitName: string) => { memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); - return AGGREGATION_METHODS[2]; + return AGGREGATION_METHODS[AGGREGATION_METHODS.length - 1]; }; From 5a86cf3884886c3350f7a9a2dde2e600cde48b26 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:36:07 +0400 Subject: [PATCH 748/863] fix(builtins): add a bit of doc, remove additional 1 second Signed-off-by: manushak --- src/if-run/builtins/time-sync/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 1fecfebd8..60b88c432 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -485,7 +485,7 @@ export const TimeSync = ( paddedArray.push( ...getZeroishInputPerSecondBetweenRange( lastInputEnd, - params.endTime.plus({seconds: 1}), + params.endTime, lastInput ) ); @@ -494,6 +494,9 @@ export const TimeSync = ( return paddedArray; }; + /** + * Brakes down the given range by 1 second, and generates zeroish values. + */ const getZeroishInputPerSecondBetweenRange = ( startDate: DateTimeMaybeValid, endDate: DateTimeMaybeValid, From 20e56ee6ab6cc17e2df456c69e9efcbe57aab430 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 4 Sep 2024 15:46:48 +0400 Subject: [PATCH 749/863] test(builtins): update time sync Signed-off-by: manushak --- .../if-run/builtins/time-sync.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index d1aa49076..da9d05ed5 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -463,12 +463,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 1, - 'cpu/utilization': null, + 'cpu/utilization': 10, }, { timestamp: '2023-12-12T00:00:01.000Z', duration: 1, - 'cpu/utilization': null, + 'cpu/utilization': 10, }, ]; @@ -578,12 +578,12 @@ describe('builtins/time-sync:', () => { { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, - 'resources-total': null, + 'resources-total': 10, }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, - 'resources-total': null, + duration: 4, + 'resources-total': 10, }, ]; @@ -627,9 +627,9 @@ describe('builtins/time-sync:', () => { }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, + duration: 4, 'resources-total': 10, - 'time-reserved': 3.2, + 'time-reserved': 3.75, }, ]; @@ -676,9 +676,9 @@ describe('builtins/time-sync:', () => { }, { timestamp: '2023-12-12T00:00:05.000Z', - duration: 5, + duration: 4, 'resources-total': 10, - 'time-allocated': 3.2, + 'time-allocated': 3.75, }, ]; From 943921e0138a8ae402c5e38bbaf33792d82a058a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:55:10 +0400 Subject: [PATCH 750/863] feat(util): enable granular aggregation in helper Signed-off-by: manushak --- src/if-run/util/aggregation-helper.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index e573720b1..211364f1a 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -3,13 +3,13 @@ import {PluginParams} from '@grnsft/if-core/types'; import {CONFIG, STRINGS} from '../config'; -import {AggregationMetric, AggregationResult} from '../types/aggregation'; +import {AggregationResult} from '../types/aggregation'; -import {getAggregationMethod} from '../lib/aggregate'; +import {getAggregationInfoFor} from '../lib/aggregate'; const {MissingAggregationParamError} = ERRORS; const {METRIC_MISSING} = STRINGS; -const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; +const {AGGREGATION_TIME_METRICS} = CONFIG; /** * Aggregates child node level metrics. Appends aggregation additional params to metrics. @@ -17,31 +17,32 @@ const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG; */ export const aggregateInputsIntoOne = ( inputs: PluginParams[], - metrics: AggregationMetric[], + metrics: string[], isTemporal?: boolean ) => { - const metricsKeys: string[] = metrics.map(metric => Object.keys(metric)[0]); - const extendedMetrics = [...metricsKeys, ...AGGREGATION_ADDITIONAL_PARAMS]; + const metricsWithTime = metrics.concat(AGGREGATION_TIME_METRICS); return inputs.reduce((acc, input, index) => { - for (const metric of extendedMetrics) { + for (const metric of metricsWithTime) { if (!(metric in input)) { throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); } /** Checks if metric is timestamp or duration, then adds to aggregated value. */ - if (AGGREGATION_ADDITIONAL_PARAMS.includes(metric)) { + if (AGGREGATION_TIME_METRICS.includes(metric)) { if (isTemporal) { acc[metric] = input[metric]; } } else { - const method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); + /** Checks either its a temporal aggregation (vertical), then chooses `component`, otherwise `time`. */ + const aggregationType = isTemporal ? 'component' : 'time'; - if (method === 'none') { + if (aggregationParams[aggregationType] === 'none') { return acc; } - if (method === 'copy') { + if (aggregationParams[aggregationType] === 'copy') { acc[metric] = input[metric]; return acc; } @@ -51,7 +52,7 @@ export const aggregateInputsIntoOne = ( /** Checks for the last iteration. */ if (index === inputs.length - 1) { - if (method === 'avg') { + if (aggregationParams[aggregationType] === 'avg') { acc[metric] /= inputs.length; } } From 4f01a8e8b7a1d39c00a4940bf6912588c0da29aa Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:56:08 +0400 Subject: [PATCH 751/863] feat(types): use aggregation options as method Signed-off-by: manushak --- src/if-run/types/explain.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index c32f91325..caedd3992 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -1,4 +1,4 @@ -import {ParameterMetadata} from '@grnsft/if-core/types'; +import {AggregationOptions, ParameterMetadata} from '@grnsft/if-core/types'; import {PluginOptions} from '../../common/types/manifest'; @@ -14,6 +14,6 @@ export type ExplainStorageType = Record< plugins: string[]; unit: string; description: string; - 'aggregation-method': string; + 'aggregation-method': AggregationOptions; } >; From 35f8142ea62aff13c65071b310228a0e4a49ad12 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:57:00 +0400 Subject: [PATCH 752/863] feat(types): enable time and component aggregations Signed-off-by: manushak --- src/if-run/types/aggregation.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/if-run/types/aggregation.ts b/src/if-run/types/aggregation.ts index 5315b298f..811833c7b 100644 --- a/src/if-run/types/aggregation.ts +++ b/src/if-run/types/aggregation.ts @@ -1,7 +1,9 @@ -import {AggregationMethodTypes} from '@grnsft/if-core/types'; - export type AggregationResult = Record; -export const AGGREGATION_TYPES = ['horizontal', 'vertical', 'both'] as const; - -export type AggregationMetric = Record; +export const AGGREGATION_TYPES = [ + 'horizontal', + 'time', + 'vertical', + 'component', + 'both', +] as const; From b58cbbfb4ba0a1b09c36101a743020e716e33c5c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:57:48 +0400 Subject: [PATCH 753/863] fix(lib): update docs, improve readablity in initialize Signed-off-by: manushak --- src/if-run/lib/initialize.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 6deb73ce2..9239fe3d1 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -103,6 +103,10 @@ const initPlugin = async ( /** * Registers all plugins from `manifest`.`initialize` property. + * 1. Initalizes plugin storage. + * 2. Iterates over plugin names array. + * 3. While iteration, initalizes current plugin, gathers it's parameters (input/output). + * Then stores the aggregation metrics for each parameter to override stub values. */ export const initialize = async ( context: Context @@ -117,9 +121,9 @@ export const initialize = async ( const plugin = await initPlugin(plugins[pluginName]); const parameters = {...plugin.metadata.inputs, ...plugin.metadata.outputs}; - Object.keys(parameters).forEach(key => { + Object.keys(parameters).forEach(current => { storeAggregationMetrics({ - [key]: parameters[key]['aggregation-method'], + [current]: parameters[current]['aggregation-method'], }); }); From 23bc5f9884c1849606b8a26d3605e33c081c0be8 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:58:36 +0400 Subject: [PATCH 754/863] feat(lib): use granular aggregation in explain Signed-off-by: manushak --- src/if-run/lib/explain.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index eb42cfd49..470eed2e7 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -40,7 +40,7 @@ export const addExplainData = (params: ExplainParams) => { const allParameters = { ...parameterMetadata?.inputs, ...parameterMetadata?.outputs, - }; + } as ExplainStorageType; Object.entries(allParameters).forEach(([name, meta]) => { const existingParameter = parameters[name]; @@ -55,7 +55,10 @@ export const addExplainData = (params: ExplainParams) => { } if ( - meta['aggregation-method'] !== existingParameter['aggregation-method'] + meta['aggregation-method'].component !== + existingParameter['aggregation-method'].component || + meta['aggregation-method'].time !== + existingParameter['aggregation-method'].time ) { throw new ManifestValidationError(AGGREGATION_METHODS_NOT_MATCH(name)); } From 5832a241ac5448b755a97987f04c781901189306 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 9 Sep 2024 23:59:30 +0400 Subject: [PATCH 755/863] feat(lib): introduce granular aggregation to aggregate Signed-off-by: manushak --- src/if-run/lib/aggregate.ts | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index a810ecc47..bee7d3031 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -12,8 +12,6 @@ import { import {aggregateInputsIntoOne} from '../util/aggregation-helper'; import {memoizedLog} from '../util/log-memoize'; -import {AggregationMetric} from '../types/aggregation'; - import {STRINGS} from '../config/strings'; const { @@ -40,7 +38,7 @@ const getIthElementsFromChildren = (children: any, i: number) => { * 1. Gets the i'th element from each childrens outputs (treating children as rows and we are after a column of data). * 2. Now we just aggregate over the `ithSliceOfOutputs` the same as we did for the normal outputs. */ -const temporalAggregation = (node: any, metrics: AggregationMetric[]) => { +const temporalAggregation = (node: any, metrics: string[]) => { const outputs: PluginParams[] = []; const values: any = Object.values(node.children); @@ -64,9 +62,7 @@ const temporalAggregation = (node: any, metrics: AggregationMetric[]) => { * 5. Now a grouping node has it's own outputs, it can horizotnally aggregate them. */ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { - const metrics: AggregationMetric[] = aggregationParams!.metrics.map( - metric => ({[metric]: 'none'}) - ); + const metrics = aggregationParams!.metrics; const type = aggregationParams!.type; if (node.children) { @@ -78,11 +74,13 @@ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { } if (!node.children) { - if (type === 'horizontal' || type === 'both') { + /** `time` aggregation is the new name of `horizontal`. */ + if (type === 'horizontal' || type === 'time' || type === 'both') { node.aggregated = aggregateInputsIntoOne(node.outputs, metrics); } } else { - if (type === 'vertical' || type === 'both') { + /** `component` aggregation is the new name of `vertical`. */ + if (type === 'vertical' || type === 'component' || type === 'both') { const outputs = temporalAggregation(node, metrics); node.outputs = outputs; node.aggregated = aggregateInputsIntoOne(outputs, metrics); @@ -127,13 +125,13 @@ export const storeAggregationMetrics = ( * Creates an encapsulated object to retrieve the metrics. */ const metricManager = (() => { - let metric: AggregationMetric; + let metric: AggregationMetricsWithMethod; const manager = { get metrics() { return metric; }, - set metrics(value: AggregationMetric) { + set metrics(value: AggregationMetricsWithMethod) { metric = value; }, }; @@ -142,22 +140,25 @@ const metricManager = (() => { })(); /** - * Returns aggregation method for given `unitName`. If doesn't exist then returns value `sum`. + * Returns aggregation method for given `metric`. */ -export const getAggregationMethod = (unitName: string) => { +export const getAggregationInfoFor = (metric: string) => { debugLogger.setExecutingPluginName(); memoizedLog(console.debug, '\n'); - memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(unitName)); + memoizedLog(console.debug, CHECKING_AGGREGATION_METHOD(metric)); const aggregationMetricsStorage = storeAggregationMetrics(); if ( aggregationMetricsStorage && - Object.keys(aggregationMetricsStorage).includes(unitName) + Object.keys(aggregationMetricsStorage).includes(metric) ) { - return aggregationMetricsStorage[unitName]; + return aggregationMetricsStorage[metric]; } - memoizedLog(logger.warn, UNKNOWN_PARAM(unitName)); + memoizedLog(logger.warn, UNKNOWN_PARAM(metric)); - return AGGREGATION_METHODS[AGGREGATION_METHODS.length - 1]; + return { + time: AGGREGATION_METHODS[3], + component: AGGREGATION_METHODS[3], + }; }; From ee6c2ab6bc29ca8aa8ddc013a8fd9ff36d845528 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:00:06 +0400 Subject: [PATCH 756/863] feat(config): rename additional params to time metrics Signed-off-by: manushak --- src/if-run/config/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index 9bd39d89f..d151a0389 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -71,5 +71,5 @@ export const CONFIG = { } as ParseOptions, GITHUB_PATH: 'https://github.com', NATIVE_PLUGIN: 'if-plugins', - AGGREGATION_ADDITIONAL_PARAMS: ['timestamp', 'duration'], + AGGREGATION_TIME_METRICS: ['timestamp', 'duration'], }; From 3c07a4a4278168331d29cc7650345cac8cb15f4e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:00:55 +0400 Subject: [PATCH 757/863] feat(builtins): use granular aggregation in time sync Signed-off-by: manushak --- src/if-run/builtins/time-sync/index.ts | 59 +++++++++++++++----------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 60b88c432..9c42866f9 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -21,7 +21,7 @@ import { import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -import {getAggregationMethod} from '../../lib/aggregate'; +import {getAggregationInfoFor} from '../../lib/aggregate'; Settings.defaultZone = 'utc'; @@ -69,12 +69,18 @@ export const TimeSync = ( timestamp: { description: 'refers to the time of occurrence of the input', unit: 'RFC3339', - 'aggregation-method': 'none', + 'aggregation-method': { + time: 'none', + component: 'none', + }, }, duration: { description: 'refers to the duration of the input', unit: 'seconds', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'none', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, @@ -249,35 +255,35 @@ export const TimeSync = ( */ const breakDownInput = (input: PluginParams, i: number) => { const evaluatedInput = evaluateInput(input); - const inputKeys = Object.keys(evaluatedInput); + const metrics = Object.keys(evaluatedInput); - return inputKeys.reduce((acc, key) => { - const method = getAggregationMethod(key); + return metrics.reduce((acc, metric) => { + const aggregationParams = getAggregationInfoFor(metric); - if (key === 'timestamp') { + if (metric === 'timestamp') { const perSecond = normalizeTimePerSecond(input.timestamp, i); - acc[key] = perSecond.toUTC().toISO() ?? ''; + acc[metric] = perSecond.toUTC().toISO() ?? ''; return acc; } /** @todo use user defined resolution later */ - if (key === 'duration') { - acc[key] = 1; + if (metric === 'duration') { + acc[metric] = 1; return acc; } - if (method === 'none') { - acc[key] = null; + if (aggregationParams.time === 'none') { + acc[metric] = null; return acc; } - acc[key] = - method === 'sum' - ? convertPerInterval(evaluatedInput[key], evaluatedInput['duration']) - : evaluatedInput[key]; + acc[metric] = + aggregationParams.time === 'sum' + ? convertPerInterval(evaluatedInput[metric], evaluatedInput['duration']) + : evaluatedInput[metric]; return acc; }, {} as PluginParams); @@ -317,21 +323,24 @@ export const TimeSync = ( return acc; } - const method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); - if (method === 'none') { + if (aggregationParams.time === 'none') { acc[metric] = null; return acc; } - if (method === 'avg' || method === 'sum') { + if ( + aggregationParams.time === 'avg' || + aggregationParams.time === 'sum' + ) { acc[metric] = 0; return acc; } - if (method === 'copy') { + if (aggregationParams.time === 'copy') { acc[metric] = input[metric]; return acc; } @@ -385,7 +394,7 @@ export const TimeSync = ( const metrics = Object.keys(input); metrics.forEach(metric => { - let method = getAggregationMethod(metric); + const aggregationParams = getAggregationInfoFor(metric); if (metric === 'timestamp') { acc[metric] = inputs[0][metric]; @@ -394,23 +403,23 @@ export const TimeSync = ( } if (metric === 'duration') { - method = 'sum'; + aggregationParams.time = 'sum'; } - if (method === 'none') { + if (aggregationParams.time === 'none') { acc[metric] = null; return; } acc[metric] = acc[metric] ?? 0; - if (method === 'sum') { + if (aggregationParams.time === 'sum') { acc[metric] += input[metric]; return; } - if (method === 'copy') { + if (aggregationParams.time === 'copy') { acc[metric] = input[metric]; return; From 1f278ec0b2e5d71bbab95818074c043fe340ed40 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:01:26 +0400 Subject: [PATCH 758/863] feat(builtins): use granular aggregation methods in sci embodied Signed-off-by: manushak --- src/if-run/builtins/sci-embodied/index.ts | 35 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index c86dbd718..7de0c2774 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -34,39 +34,60 @@ export const SciEmbodied = ( vCPUs: { description: 'number of CPUs allocated to an application', unit: 'CPUs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, memory: { description: 'RAM available for a resource, in GB', unit: 'GB', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, ssd: { description: 'number of SSDs available for a resource', unit: 'SSDs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, hdd: { description: 'number of HDDs available for a resource', unit: 'HDDs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, gpu: { description: 'number of GPUs available for a resource', unit: 'GPUs', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, 'usage-ratio': { description: 'a scaling factor that can be used to describe the ratio of actual resource usage comapred to real device usage, e.g. 0.25 if you are using 2 out of 8 vCPUs, 0.1 if you are responsible for 1 out of 10 GB of storage, etc', unit: 'dimensionless', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, time: { description: 'a time unit to scale the embodied carbon by, in seconds. If not provided,time defaults to the value of the timestep duration.', unit: 'seconds', - 'aggregation-method': 'copy', + 'aggregation-method': { + time: 'copy', + component: 'copy', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, From f76ab33d4d0d1ac47de24a1df756b253593c1b2f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:04:58 +0400 Subject: [PATCH 759/863] feat(builtins): use granular aggregation methods in sci Signed-off-by: manushak --- src/if-run/builtins/sci/index.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 7c1c7d08e..7e98a8f0e 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -48,13 +48,19 @@ export const Sci = ( carbon: { description: 'an amount of carbon emitted into the atmosphere', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, 'functional-unit': { description: 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', unit: 'none', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, } as ParameterMetadata), ...parametersMetadata?.inputs, @@ -63,7 +69,10 @@ export const Sci = ( sci: { description: 'carbon expressed in terms of the given functional unit', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'avg', + component: 'sum', + }, }, }, }; From ae244122fbc0809a9c6b56b87c8e6142b65c600d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:07:37 +0400 Subject: [PATCH 760/863] feat(src): simplify if-run index Signed-off-by: manushak --- src/if-run/index.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 5607df6b6..6b26b150a 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -1,13 +1,11 @@ #!/usr/bin/env node -import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; - import {STRINGS as COMMON_STRINGS} from '../common/config'; import {validateManifest} from '../common/util/validations'; import {debugLogger} from '../common/util/debug-logger'; import {logger} from '../common/util/logger'; import {load} from '../common/lib/load'; -import {aggregate, storeAggregationMetrics} from './lib/aggregate'; +import {aggregate} from './lib/aggregate'; import {injectEnvironment} from './lib/environment'; import {initialize} from './lib/initialize'; import {compute} from './lib/compute'; @@ -44,16 +42,6 @@ const impactEngine = async () => { try { const {tree, ...context} = validateManifest(envManifest); - if (context.aggregation) { - const convertMetrics = context.aggregation?.metrics.map( - (metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], - }) - ); - - storeAggregationMetrics(...convertMetrics); - } - const pluginStorage = await initialize(context); const computedTree = await compute(tree, { context, @@ -69,6 +57,7 @@ const impactEngine = async () => { await exhaust(aggregatedTree, context, outputOptions); } catch (error) { if (error instanceof Error) { + /** Execution block exists because manifest is already processed. Set's status to `fail`. */ envManifest.execution!.status = 'fail'; envManifest.execution!.error = error.toString(); logger.error(error); From 78de5563fcd9ccc758d43215e891b84add7b7478 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:11:22 +0400 Subject: [PATCH 761/863] feat(util): introduce granular aggregation to validation Signed-off-by: manushak --- src/common/util/validations.ts | 51 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/common/util/validations.ts b/src/common/util/validations.ts index 646aee3fc..5d0ac758b 100644 --- a/src/common/util/validations.ts +++ b/src/common/util/validations.ts @@ -1,4 +1,5 @@ import {ZodIssue, ZodIssueCode, ZodSchema, z} from 'zod'; +import {AGGREGATION_METHODS} from '@grnsft/if-core/consts'; import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../if-run/config'; @@ -22,32 +23,35 @@ export const allDefined = (obj: Record) => Object.values(obj).every(v => v !== undefined); /** - * Schema for parameter metadata. + * Reusabe aggregation method schema for parameter metadata. + */ +const aggregationMethodSchema = z.object({ + time: z.enum(AGGREGATION_METHODS), + component: z.enum(AGGREGATION_METHODS), +}); + +/** + * Reusable metadata schema. + */ +const metadataSchema = z + .record( + z.string(), + z.object({ + unit: z.string(), + description: z.string(), + 'aggregation-method': aggregationMethodSchema, + }) + ) + .optional() + .nullable(); + +/** + * Reusable parameter metadata schema. */ const parameterMetadataSchema = z .object({ - inputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), - outputs: z - .record( - z.string(), - z.object({ - unit: z.string(), - description: z.string(), - 'aggregation-method': z.string(), - }) - ) - .optional() - .nullable(), + inputs: metadataSchema, + outputs: metadataSchema, }) .optional(); @@ -71,6 +75,7 @@ export const manifestSchema = z.object({ .object({ metrics: z.array(z.string()), type: z.enum(AGGREGATION_TYPES), + 'skip-components': z.array(z.string()).optional(), }) .optional() .nullable(), From dc1ccc7334c1caf3c9d94eb860896a9a440521c7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:17:54 +0400 Subject: [PATCH 762/863] feat(types): enable time and component aggregations in manifest Signed-off-by: manushak --- src/common/types/manifest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/types/manifest.ts b/src/common/types/manifest.ts index 488d8eeb5..483af708c 100644 --- a/src/common/types/manifest.ts +++ b/src/common/types/manifest.ts @@ -1,5 +1,5 @@ import {z} from 'zod'; -import {AggregationMethodTypes} from '@grnsft/if-core/types'; +import {AggregationOptions} from '@grnsft/if-core/types'; import {manifestSchema} from '../util/validations'; @@ -11,7 +11,7 @@ export type PluginOptions = GlobalPlugins[string]; export type AggregationParams = Manifest['aggregation']; export type AggregationMetricsWithMethod = { - [key: string]: AggregationMethodTypes; + [key: string]: AggregationOptions; }; export type AggregationParamsSure = Extract; From 39367ac84fb7ef5fbafa1f2b73f8c3ac0dc450c7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:19:06 +0400 Subject: [PATCH 763/863] test(util): tune aggregation helper units Signed-off-by: manushak --- .../if-run/util/aggregation-helper.test.ts | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index d76fcbb94..32a749a47 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -5,7 +5,6 @@ import {PluginParams} from '@grnsft/if-core/types'; import {AggregationParams} from '../../../common/types/manifest'; import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; -import {AggregationMetric} from '../../../if-run/types/aggregation'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -20,16 +19,24 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); }); describe('aggregateInputsIntoOne(): ', () => { it('throws error if aggregation criteria is not found in input.', () => { const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; - const metrics: AggregationMetric[] = [{'cpu/utilization': 'sum'}]; + const metrics: string[] = ['cpu/utilization']; const isTemporal = false; expect.assertions(2); @@ -46,12 +53,17 @@ describe('util/aggregation-helper: ', () => { }); it('passes `timestamp`, `duration` to aggregator if aggregation is temporal.', () => { - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric[] = [{carbon: 'sum'}]; + const metrics: string[] = ['carbon']; const isTemporal = true; const expectedValue = { @@ -68,7 +80,7 @@ describe('util/aggregation-helper: ', () => { {timestamp: '', duration: 10, carbon: 10}, {timestamp: '', duration: 10, carbon: 20}, ]; - const metrics: AggregationMetric[] = [{carbon: 'sum'}]; + const metrics: string[] = ['carbon']; const isTemporal = false; const expectedValue = { @@ -84,16 +96,24 @@ describe('util/aggregation-helper: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); - storeAggregationMetrics({'cpu/utilization': 'avg'}); + storeAggregationMetrics({ + 'cpu/utilization': { + time: 'avg', + component: 'avg', + }, + }); const inputs: PluginParams[] = [ {timestamp: '', duration: 10, 'cpu/utilization': 10}, {timestamp: '', duration: 10, 'cpu/utilization': 90}, ]; - const metrics: AggregationMetric[] = [{'cpu/utilization': 'avg'}]; + const metrics: string[] = ['cpu/utilization']; const isTemporal = false; const expectedValue = { From e9999d711a44c041f43d345e19b8b4d19d87fe75 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:19:43 +0400 Subject: [PATCH 764/863] test(lib): tune explain units Signed-off-by: manushak --- src/__tests__/if-run/lib/explain.test.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index 8178bf07d..df86448ac 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -214,19 +214,28 @@ describe('lib/explain: ', () => { 'cpu/energy': { unit: 'kWh', description: 'energy consumed by the cpu', - 'aggregation-method': 'avg', + 'aggregation-method': { + time: 'avg', + component: 'avg', + }, }, 'memory/energy': { unit: 'kWh', description: 'energy consumed by data from memory', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, outputs: { 'total/energy': { unit: 'kWh', description: 'sum of energy components', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, }, From dd88ca8572f8ea54e848c6d9683142bc8d0dc8a2 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:20:22 +0400 Subject: [PATCH 765/863] test(lib): tune aggregate units Signed-off-by: manushak --- src/__tests__/if-run/lib/aggregate.test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/aggregate.test.ts b/src/__tests__/if-run/lib/aggregate.test.ts index d053fea9f..f39efdfcd 100644 --- a/src/__tests__/if-run/lib/aggregate.test.ts +++ b/src/__tests__/if-run/lib/aggregate.test.ts @@ -15,7 +15,10 @@ describe('lib/aggregate: ', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); @@ -23,7 +26,12 @@ describe('lib/aggregate: ', () => { describe('aggregate(): ', () => { beforeAll(() => { - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); }); it('returns tree if aggregation is missing.', () => { From 91180e076eed0bf1881c42b856bb5ffe4a25b6f3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 00:20:45 +0400 Subject: [PATCH 766/863] test(builtins): tune time-sync units Signed-off-by: manushak --- .../if-run/builtins/time-sync.test.ts | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index da9d05ed5..17b1cf99a 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -66,7 +66,10 @@ describe('builtins/time-sync:', () => { type: 'horizontal', }; const convertedMetrics = metricStorage.metrics.map((metric: string) => ({ - [metric]: AGGREGATION_METHODS[2], + [metric]: { + time: AGGREGATION_METHODS[2], + component: AGGREGATION_METHODS[2], + }, })); storeAggregationMetrics(...convertedMetrics); }); @@ -483,7 +486,12 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({carbon: 'sum'}); + storeAggregationMetrics({ + carbon: { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); @@ -598,8 +606,18 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({'time-reserved': 'avg'}); - storeAggregationMetrics({'resources-total': 'sum'}); + storeAggregationMetrics({ + 'time-reserved': { + time: 'avg', + component: 'avg', + }, + }); + storeAggregationMetrics({ + 'resources-total': { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); @@ -647,8 +665,18 @@ describe('builtins/time-sync:', () => { 'time-reserved': 'time-allocated', }; - storeAggregationMetrics({'time-allocated': 'avg'}); - storeAggregationMetrics({'resources-total': 'sum'}); + storeAggregationMetrics({ + 'time-allocated': { + time: 'avg', + component: 'avg', + }, + }); + storeAggregationMetrics({ + 'resources-total': { + time: 'sum', + component: 'sum', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, mapping); @@ -722,7 +750,12 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, }; - storeAggregationMetrics({'resources-total': 'none'}); + storeAggregationMetrics({ + 'resources-total': { + time: 'none', + component: 'none', + }, + }); const timeModel = TimeSync(basicConfig, parametersMetadata, {}); From 921f4614f0c6bce514d93125702a43333767fb6c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 10:18:50 +0400 Subject: [PATCH 767/863] feat(package): update if-core version Signed-off-by: manushak --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8687cc420..3aa9582e4 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.21", + "@grnsft/if-core": "^0.0.23", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.21", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.21.tgz", - "integrity": "sha512-zk50alrh3I9Sd+MKRcyo2srBmUUYIfU0Bm6dZ6nHaINR5DUACkDmA+z2ByCXQlHZJQM0y3K1FLjdG2Ug0tTd1A==", + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.23.tgz", + "integrity": "sha512-lP+ViXjlhcTSosomLGOAO4PM8Ug5qtb5LEdOouUvg01PoVUJwLLf/MJgYxCegP8maAMCv1n4s1uPx15ffZqMXg==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 698f18cfa..8386c8f10 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.21", + "@grnsft/if-core": "^0.0.23", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 116e48f3dea52f20ac4d80623a93d335fa632886 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 10 Sep 2024 16:26:31 +0400 Subject: [PATCH 768/863] fix(builtins): fix output param of sci embodied Signed-off-by: manushak --- src/if-run/builtins/sci-embodied/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 7de0c2774..a4451cc63 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -96,7 +96,10 @@ export const SciEmbodied = ( 'embodied-carbon': { description: 'embodied carbon for a resource, scaled by usage', unit: 'gCO2e', - 'aggregation-method': 'sum', + 'aggregation-method': { + time: 'sum', + component: 'sum', + }, }, }, }; From cda568131e59edd831d1870684ff2b9a59353ab3 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Sun, 4 Aug 2024 17:59:13 +1000 Subject: [PATCH 769/863] feat(src): add support for appending to existing outputs Signed-off-by: James Crowley Signed-off-by: manushak --- src/__tests__/if-run/lib/compute.test.ts | 34 ++++++++++++++++++++++++ src/if-run/config/config.ts | 6 +++++ src/if-run/index.ts | 2 ++ src/if-run/lib/compute.ts | 4 +++ src/if-run/types/compute.ts | 1 + src/if-run/types/process-args.ts | 2 ++ src/if-run/util/args.ts | 2 ++ 7 files changed, 51 insertions(+) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index 4663d461b..ae062b2bb 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -252,6 +252,40 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); + + it('computes simple tree with append and execute plugin.', async () => { + const tree = { + children: { + mockChild: { + pipeline: ['mock'], + inputs: [ + {timestamp: 'mock-timestamp-1', duration: 10}, + {timestamp: 'mock-timestamp-2', duration: 10}, + ], + outputs: [ + { + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + duration: 10, + }, + { + timestamp: 'mock-timestamp-2', + newField: 'mock-newField', + duration: 10, + }, + ], + }, + }, + }; + const paramsExecuteWithAppend = {...paramsExecute, append: true}; + const response = await compute(tree, paramsExecuteWithAppend); + const expectedResult = [ + ...tree.children.mockChild.outputs, + ...mockExecutePlugin().execute(tree.children.mockChild.inputs), + ]; + expect(response.children.mockChild.outputs).toHaveLength(4); + expect(response.children.mockChild.outputs).toEqual(expectedResult); + }); }); it('computes simple tree with observe plugin.', async () => { diff --git a/src/if-run/config/config.ts b/src/if-run/config/config.ts index d151a0389..4ec43ee29 100644 --- a/src/if-run/config/config.ts +++ b/src/if-run/config/config.ts @@ -38,6 +38,12 @@ export const CONFIG = { alias: 'h', description: '[prints out the above help instruction]', }, + append: { + type: Boolean, + optional: true, + alias: 'a', + description: '[append to outputs, instead of overwriting]', + }, debug: { type: Boolean, optional: true, diff --git a/src/if-run/index.ts b/src/if-run/index.ts index 6b26b150a..0a29409a5 100644 --- a/src/if-run/index.ts +++ b/src/if-run/index.ts @@ -29,6 +29,7 @@ const impactEngine = async () => { observe, regroup, compute: computeFlag, + append, } = options; debugLogger.overrideConsoleMethods(!!debug); @@ -49,6 +50,7 @@ const impactEngine = async () => { observe, regroup, compute: computeFlag, + append, }); const aggregatedTree = aggregate(computedTree, context.aggregation); diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 1e72a2f70..014cde16c 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -100,6 +100,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } + const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -180,6 +181,9 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { } } } + if (params.append) { + node.outputs = originalOutputs.concat(node.outputs || []); + } console.debug('\n'); }; diff --git a/src/if-run/types/compute.ts b/src/if-run/types/compute.ts index 56346d390..22b80b9cc 100644 --- a/src/if-run/types/compute.ts +++ b/src/if-run/types/compute.ts @@ -25,6 +25,7 @@ export type ComputeParams = { observe?: Boolean; regroup?: Boolean; compute?: Boolean; + append?: boolean; }; export type Node = { diff --git a/src/if-run/types/process-args.ts b/src/if-run/types/process-args.ts index 298cadda6..60deb686b 100644 --- a/src/if-run/types/process-args.ts +++ b/src/if-run/types/process-args.ts @@ -6,6 +6,7 @@ export interface IfRunArgs { observe?: boolean; regroup?: boolean; compute?: boolean; + append?: boolean; } export interface ProcessArgsOutputs { @@ -19,6 +20,7 @@ export interface ProcessArgsOutputs { observe?: boolean; regroup?: boolean; compute?: boolean; + append?: boolean; } export interface Options { diff --git a/src/if-run/util/args.ts b/src/if-run/util/args.ts index 538d37a36..b0cf90b8f 100644 --- a/src/if-run/util/args.ts +++ b/src/if-run/util/args.ts @@ -48,6 +48,7 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { observe, regroup, compute, + append, } = validateAndParseProcessArgs(); if (!output && noOutput) { @@ -66,6 +67,7 @@ export const parseIfRunProcessArgs = (): ProcessArgsOutputs => { observe, regroup, compute, + ...(append && {append}), }; } From 4e8c5e1e0c824d4487ee9f69ae1037bf9f50b65e Mon Sep 17 00:00:00 2001 From: James Crowley Date: Fri, 16 Aug 2024 18:41:42 +0100 Subject: [PATCH 770/863] test(lib): make the regroup intended behaviour clearer Signed-off-by: James Crowley Signed-off-by: manushak --- src/__tests__/if-run/lib/compute.test.ts | 65 +++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index ae062b2bb..a4d9f24df 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -117,24 +117,28 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with groupby plugin.', async () => { + it('computes simple tree with regroup.', async () => { const tree = { children: { mockChild: { - pipeline: {regroup: ['duration']}, + pipeline: {regroup: ['region']}, inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, + {timestamp: 'mock-timestamp-1', region: 'uk-west'}, + {timestamp: 'mock-timestamp-2', region: 'uk-east'}, + {timestamp: 'mock-timestamp-3', region: 'uk-east'}, ], }, }, }; const response = await compute(tree, paramsExecute); const expectedResponse = { - '10': { + 'uk-west': { + inputs: [{region: 'uk-west', timestamp: 'mock-timestamp-1'}], + }, + 'uk-east': { inputs: [ - {duration: 10, timestamp: 'mock-timestamp-1'}, - {duration: 10, timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-3'}, ], }, }; @@ -142,6 +146,53 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.children).toEqual(expectedResponse); }); + it('computes tree with regroup and compute.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [ + {timestamp: 'mock-timestamp-1', region: 'uk-west'}, + {timestamp: 'mock-timestamp-2', region: 'uk-east'}, + {timestamp: 'mock-timestamp-3', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResponse = { + 'uk-west': { + inputs: [{region: 'uk-west', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-west', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + 'uk-east': { + inputs: [ + {region: 'uk-east', timestamp: 'mock-timestamp-2'}, + {region: 'uk-east', timestamp: 'mock-timestamp-3'}, + ], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-2', + newField: 'mock-newField', + }, + { + region: 'uk-east', + timestamp: 'mock-timestamp-3', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + it('computes simple tree with defaults and execute plugin.', async () => { const tree = { children: { From a9ab29583e866ae8c219467b4d64665bb69212b1 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Sat, 17 Aug 2024 11:34:15 +0100 Subject: [PATCH 771/863] test(lib): fix typos in test names Signed-off-by: James Crowley Signed-off-by: manushak --- src/__tests__/if-run/lib/compute.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index a4d9f24df..ba631b990 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -269,7 +269,7 @@ describe('lib/compute: ', () => { ); }); - it('computes simple tree with no defaults and no inputs with execue plugin.', async () => { + it('computes simple tree with no defaults and no inputs with execute plugin.', async () => { const tree = { children: { mockChild: { @@ -284,7 +284,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toBeUndefined(); }); - it('computes simple tree with defaults and no inputs with execue plugin.', async () => { + it('computes simple tree with defaults and no inputs with execute plugin.', async () => { const tree = { children: { mockChild: { From 3d51191e5cded01f3608612c7b81fa9a658e2590 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:33:50 +0100 Subject: [PATCH 772/863] refactor(lib): refactor regroup so we can then include outputs Signed-off-by: James Crowley Signed-off-by: manushak --- src/if-run/lib/regroup.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index affd51307..c1a7b554e 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -60,9 +60,12 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { * Interates over inputs, grabs group values for each one. * Based on grouping, initializes the structure. */ - return inputs.reduce((acc, input) => { - const validtedGroups = validateGroups(groups); - const groupsWithData = validtedGroups.map(groupType => { + + const validatedGroups = validateGroups(groups); + + let acc = {} as any; + for (const input of inputs) { + const groupsWithData = validatedGroups.map(groupType => { if (!input[groupType]) { throw new InvalidGroupingError(INVALID_GROUP_KEY(groupType)); } @@ -74,7 +77,7 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { ...acc, ...appendGroup(input, acc, groupsWithData), }; + } - return acc; - }, {} as any).children; + return acc.children; }; From c860286670b7d0eb05e7f976fab82363d9074399 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:38:36 +0100 Subject: [PATCH 773/863] refactor(lib): extract function for looking up group key value Signed-off-by: James Crowley Signed-off-by: manushak --- src/if-run/lib/regroup.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index c1a7b554e..279dc6a4f 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -63,16 +63,19 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const validatedGroups = validateGroups(groups); - let acc = {} as any; - for (const input of inputs) { - const groupsWithData = validatedGroups.map(groupType => { - if (!input[groupType]) { - throw new InvalidGroupingError(INVALID_GROUP_KEY(groupType)); - } + const lookupGroupKey = (input: PluginParams, groupKey: string) => { + if (!input[groupKey]) { + throw new InvalidGroupingError(INVALID_GROUP_KEY(groupKey)); + } - return input[groupType]; - }); + return input[groupKey]; + }; + let acc = {} as any; + for (const input of inputs) { + const groupsWithData = validatedGroups.map(groupKey => + lookupGroupKey(input, groupKey) + ); acc = { ...acc, ...appendGroup(input, acc, groupsWithData), From fa06cfa23ae586c7ac0c5f6cd53e0ca89ca527db Mon Sep 17 00:00:00 2001 From: James Crowley Date: Mon, 19 Aug 2024 09:42:25 +0100 Subject: [PATCH 774/863] refactor(lib): remove unnecessary spread appendGroup already returns acc merged anyway Signed-off-by: James Crowley Signed-off-by: manushak --- src/if-run/lib/regroup.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index 279dc6a4f..f703aed42 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -76,10 +76,7 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const groupsWithData = validatedGroups.map(groupKey => lookupGroupKey(input, groupKey) ); - acc = { - ...acc, - ...appendGroup(input, acc, groupsWithData), - }; + acc = appendGroup(input, acc, groupsWithData); } return acc.children; From 4aa79e1beffd46b64ad57aa00f2696b72d6f4de2 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Tue, 20 Aug 2024 11:23:43 +0100 Subject: [PATCH 775/863] feat(lib): apply regroup to outputs not just inputs only when appending - otherwise outputs are lost if not already grouped. Signed-off-by: James Crowley Signed-off-by: manushak --- src/__tests__/if-run/lib/compute.test.ts | 82 ++++++++++++++++++++---- src/__tests__/if-run/lib/regroup.test.ts | 78 ++++++++++++++++++++-- src/if-run/lib/compute.ts | 18 ++++-- src/if-run/lib/regroup.ts | 32 ++++++--- 4 files changed, 181 insertions(+), 29 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index ba631b990..a7e2b2cd2 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -94,6 +94,7 @@ describe('lib/compute: ', () => { .set('mock-observe-time-sync', mockObservePluginTimeSync()) .set('time-sync', mockTimeSync()), }; + const paramsExecuteWithAppend = {...paramsExecute, append: true}; describe('compute(): ', () => { it('computes simple tree with execute plugin.', async () => { @@ -117,7 +118,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with regroup.', async () => { + it('computes simple tree with regroup on inputs only (no compute).', async () => { const tree = { children: { mockChild: { @@ -146,7 +147,7 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.children).toEqual(expectedResponse); }); - it('computes tree with regroup and compute.', async () => { + it('computes simple tree with regroup, grouping inputs and outputs.', async () => { const tree = { children: { mockChild: { @@ -304,31 +305,30 @@ describe('lib/compute: ', () => { expect(response.children.mockChild.outputs).toEqual(expectedResult); }); - it('computes simple tree with append and execute plugin.', async () => { + it('computes simple tree with append, preserving existing outputs.', async () => { const tree = { children: { mockChild: { - pipeline: ['mock'], + pipeline: {compute: ['mock']}, inputs: [ - {timestamp: 'mock-timestamp-1', duration: 10}, - {timestamp: 'mock-timestamp-2', duration: 10}, + {timestamp: 'mock-timestamp-1', region: 'eu-west'}, + {timestamp: 'mock-timestamp-2', region: 'eu-west'}, ], outputs: [ { - timestamp: 'mock-timestamp-1', + timestamp: 'mock-timestamp-preexisting-1', newField: 'mock-newField', - duration: 10, + region: 'eu-west', }, { - timestamp: 'mock-timestamp-2', + timestamp: 'mock-timestamp-preexisting-2', newField: 'mock-newField', - duration: 10, + region: 'eu-west', }, ], }, }, }; - const paramsExecuteWithAppend = {...paramsExecute, append: true}; const response = await compute(tree, paramsExecuteWithAppend); const expectedResult = [ ...tree.children.mockChild.outputs, @@ -339,6 +339,66 @@ describe('lib/compute: ', () => { }); }); + it('computes simple tree with regroup and append, with existing outputs preserved and regrouped without re-computing.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [{timestamp: 'mock-timestamp-1', region: 'uk-east'}], + outputs: [ + {timestamp: 'mock-timestamp-preexisting-1', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecuteWithAppend); + const expectedResponse = { + 'uk-east': { + inputs: [{region: 'uk-east', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-preexisting-1', + }, + { + region: 'uk-east', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + + it('computes simple tree with regroup and no append, with existing outputs that are removed.', async () => { + const tree = { + children: { + mockChild: { + pipeline: {regroup: ['region'], compute: ['mock']}, + inputs: [{timestamp: 'mock-timestamp-1', region: 'uk-east'}], + outputs: [ + {timestamp: 'mock-timestamp-preexisting-1', region: 'uk-east'}, + ], + }, + }, + }; + const response = await compute(tree, paramsExecute); + const expectedResponse = { + 'uk-east': { + inputs: [{region: 'uk-east', timestamp: 'mock-timestamp-1'}], + outputs: [ + { + region: 'uk-east', + timestamp: 'mock-timestamp-1', + newField: 'mock-newField', + }, + ], + }, + }; + expect(response.children.mockChild.children).toEqual(expectedResponse); + }); + it('computes simple tree with observe plugin.', async () => { const tree = { children: { diff --git a/src/__tests__/if-run/lib/regroup.test.ts b/src/__tests__/if-run/lib/regroup.test.ts index 67ff72e53..b4ba074c6 100644 --- a/src/__tests__/if-run/lib/regroup.test.ts +++ b/src/__tests__/if-run/lib/regroup.test.ts @@ -54,7 +54,75 @@ describe('lib/regroup: ', () => { }, }; - const result = Regroup(inputs, groups); + const result = Regroup(inputs, [], groups); + expect(result).toEqual(expectedOutput); + }); + + it('groups inputs combined with outputs correctly.', () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + region: 'uk-west', + }, + { + timestamp: '2023-07-06T05:00', + region: 'uk-east1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-east1', + }, + ]; + const outputs = [ + { + timestamp: '2022-06-06T00:00', + region: 'uk-west', + }, + { + timestamp: '2022-06-06T05:00', + region: 'uk-east2', + }, + ]; + const groups = ['region']; + + const expectedOutput = { + 'uk-west': { + inputs: [ + { + region: 'uk-west', + timestamp: '2023-07-06T00:00', + }, + ], + outputs: [ + { + timestamp: '2022-06-06T00:00', + region: 'uk-west', + }, + ], + }, + 'uk-east1': { + inputs: [ + { + timestamp: '2023-07-06T05:00', + region: 'uk-east1', + }, + { + timestamp: '2023-07-06T10:00', + region: 'uk-east1', + }, + ], + }, + 'uk-east2': { + outputs: [ + { + timestamp: '2022-06-06T05:00', + region: 'uk-east2', + }, + ], + }, + }; + + const result = Regroup(inputs, outputs, groups); expect(result).toEqual(expectedOutput); }); @@ -81,7 +149,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups!); + Regroup(inputs, [], groups!); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( @@ -113,7 +181,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( @@ -130,7 +198,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( @@ -149,7 +217,7 @@ describe('lib/regroup: ', () => { expect.assertions(2); try { - Regroup(inputs, groups); + Regroup(inputs, [], groups); } catch (error) { expect(error).toBeInstanceOf(InvalidGroupingError); expect(error).toEqual( diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 014cde16c..1e29bdc68 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -100,7 +100,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } - const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -133,7 +132,14 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { * If regroup is requested, execute regroup strategy, delete child's inputs, outputs and empty regroup array. */ if ((noFlags || params.regroup) && pipelineCopy.regroup) { - node.children = Regroup(inputStorage, pipelineCopy.regroup); + const originalOutputs = params.append ? node.outputs || [] : []; + + node.children = Regroup( + inputStorage, + originalOutputs, + pipelineCopy.regroup + ); + delete node.inputs; delete node.outputs; @@ -157,6 +163,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { * If iteration is on compute plugin, then executes compute plugins and sets the outputs value. */ if ((noFlags || params.compute) && pipelineCopy.compute) { + const originalOutputs = params.append ? node.outputs || [] : []; while (pipelineCopy.compute.length !== 0) { const pluginName = pipelineCopy.compute.shift() as string; const plugin = params.pluginStorage.get(pluginName); @@ -180,9 +187,10 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { } } } - } - if (params.append) { - node.outputs = originalOutputs.concat(node.outputs || []); + + if (params.append) { + node.outputs = originalOutputs.concat(node.outputs || []); + } } console.debug('\n'); }; diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index f703aed42..7e39b1c89 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -13,11 +13,20 @@ const {INVALID_GROUP_KEY, REGROUP_ERROR} = STRINGS; /** * Grouping strategy. */ -export const Regroup = (inputs: PluginParams[], groups: string[]) => { +export const Regroup = ( + inputs: PluginParams[], + outputs: PluginParams[], + groups: string[] +) => { /** * Creates structure to insert inputs by groups. */ - const appendGroup = (value: PluginParams, object: any, groups: string[]) => { + const appendGroup = ( + value: PluginParams, + object: any, + target: string, + groups: string[] + ) => { if (groups.length > 0) { const group = groups.shift() as string; @@ -26,16 +35,16 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { if (groups.length === 0) { if ( - object.children[group].inputs && - object.children[group].inputs.length > 0 + object.children[group][target] && + object.children[group][target].length > 0 ) { - object.children[group].inputs.push(value); + object.children[group][target].push(value); } else { - object.children[group].inputs = [value]; + object.children[group][target] = [value]; } } - appendGroup(value, object.children[group], groups); + appendGroup(value, object.children[group], target, groups); } return object; @@ -76,7 +85,14 @@ export const Regroup = (inputs: PluginParams[], groups: string[]) => { const groupsWithData = validatedGroups.map(groupKey => lookupGroupKey(input, groupKey) ); - acc = appendGroup(input, acc, groupsWithData); + acc = appendGroup(input, acc, 'inputs', groupsWithData); + } + + for (const output of outputs) { + const groupsWithData = validatedGroups.map(groupKey => + lookupGroupKey(output, groupKey) + ); + acc = appendGroup(output, acc, 'outputs', groupsWithData); } return acc.children; From 7279f92fa57a41c4d554418a6dfffdde77b351a8 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 17 Sep 2024 10:46:04 +0400 Subject: [PATCH 776/863] fix(builtins): minor fix DCO Remediation Commit Hereby add my Signed-off-by to this commit: dd1cfb0bc72cb96ec58e274f3034cad7098553cb Hereby add my Signed-off-by to this commit: 575ecee7700ba304a815a2ca790c4ccb9fd2fec2 Hereby add my Signed-off-by to this commit: a841b3a4f28db36c7e3cc9d55d1e8b03051c8664 Signed-off-by: manushak --- src/if-run/builtins/csv-lookup/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index f66981b97..63a4a3496 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -203,8 +203,8 @@ export const CSVLookup = ( * 4. Filters requested information from CSV. */ const execute = async (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const {filepath, query, output} = safeGlobalConfig; + const safeConfig = validateConfig(); + const {filepath, query, output} = safeConfig; const file = await retrieveFile(filepath); const parsedCSV = parseCSVFile(file); From af3c60049578bfee2a7c7695cfb73b0ef84bf7fe Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 17 Sep 2024 10:53:53 +0400 Subject: [PATCH 777/863] fix(builtins): minor fix Signed-off-by: manushak --- src/if-run/builtins/regex/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 5e65e677f..171f4a8ad 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -64,8 +64,8 @@ export const Regex = ( * Executes the regex of the given parameter. */ const execute = (inputs: PluginParams[]) => { - const safeGlobalConfig = validateConfig(); - const {parameter: parameter, match, output} = safeGlobalConfig; + const safeConfig = validateConfig(); + const {parameter: parameter, match, output} = safeConfig; return inputs.map(input => { const safeInput = Object.assign( From e3fd10f13e5ab931ad34e15842e03efd7abb1f75 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 17 Sep 2024 11:10:13 +0400 Subject: [PATCH 778/863] fix(builtins): minor fix Signed-off-by: manushak --- src/if-run/builtins/coefficient/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index fc0142f16..12de779d8 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,4 +1,5 @@ import {z, ZodType} from 'zod'; + import { ERRORS, evaluateInput, From 982cfca53f9d883435ee8f9529b186f4523999c1 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Sun, 4 Aug 2024 17:59:13 +1000 Subject: [PATCH 779/863] feat(src): add support for appending to existing outputs Signed-off-by: James Crowley --- src/if-run/lib/compute.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 1e29bdc68..a375a201a 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -100,6 +100,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } + const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -192,6 +193,9 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { node.outputs = originalOutputs.concat(node.outputs || []); } } + if (params.append) { + node.outputs = originalOutputs.concat(node.outputs || []); + } console.debug('\n'); }; From 7618d8b808af5170fc9515c2ccddeece845be731 Mon Sep 17 00:00:00 2001 From: James Crowley Date: Tue, 20 Aug 2024 11:23:43 +0100 Subject: [PATCH 780/863] feat(lib): apply regroup to outputs not just inputs only when appending - otherwise outputs are lost if not already grouped. Signed-off-by: James Crowley --- src/if-run/lib/compute.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index a375a201a..1e29bdc68 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -100,7 +100,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { ) { logger.warn(EMPTY_PIPELINE); } - const originalOutputs = node.outputs || []; /** * If iteration is on observe pipeline, then executes observe plugins and sets the inputs value. @@ -193,9 +192,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { node.outputs = originalOutputs.concat(node.outputs || []); } } - if (params.append) { - node.outputs = originalOutputs.concat(node.outputs || []); - } console.debug('\n'); }; From f381e56407a16e58c220ff38bc869ad7c17839a2 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 17 Sep 2024 11:26:02 +0400 Subject: [PATCH 781/863] fix(builtins): fix linter error Signed-off-by: manushak --- src/if-run/builtins/time-sync/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 9c42866f9..5e3b56e02 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -282,7 +282,10 @@ export const TimeSync = ( acc[metric] = aggregationParams.time === 'sum' - ? convertPerInterval(evaluatedInput[metric], evaluatedInput['duration']) + ? convertPerInterval( + evaluatedInput[metric], + evaluatedInput['duration'] + ) : evaluatedInput[metric]; return acc; From 270b3fa67dfe4c9c30c009f1ba3ac0c218a9d52b Mon Sep 17 00:00:00 2001 From: mouhamadalmounayar Date: Wed, 21 Aug 2024 20:04:16 +0200 Subject: [PATCH 782/863] feat(types): add upsampling-resolution to time-sync related types Signed-off-by: mouhamadalmounayar --- src/if-run/types/time-sync.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/if-run/types/time-sync.ts b/src/if-run/types/time-sync.ts index 505a91f82..c2674b652 100644 --- a/src/if-run/types/time-sync.ts +++ b/src/if-run/types/time-sync.ts @@ -5,6 +5,7 @@ export type TimeNormalizerConfig = { 'end-time': Date | string; interval: number; 'allow-padding': boolean; + 'upsampling-resolution'?: number; }; export type PaddingReceipt = { @@ -17,4 +18,5 @@ export type TimeParams = { endTime: DateTime; interval: number; allowPadding: boolean; + upsamplingResolution: number; }; From e22feb8ffef190708b31b31cad68c86996aeeecc Mon Sep 17 00:00:00 2001 From: mouhamadalmounayar Date: Wed, 21 Aug 2024 20:07:50 +0200 Subject: [PATCH 783/863] feat(builtins): add upsampling-resolution to time-sync Signed-off-by: mouhamadalmounayar --- .../if-run/builtins/time-sync.test.ts | 158 +++++++++++++++++- src/if-run/builtins/time-sync/README.md | 33 +++- src/if-run/builtins/time-sync/index.ts | 118 +++++++++---- src/if-run/config/strings.ts | 2 + 4 files changed, 268 insertions(+), 43 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 17b1cf99a..dceea1728 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -19,6 +19,7 @@ const { } = ERRORS; const { + INVALID_UPSAMPLING_RESOLUTION, INVALID_OBSERVATION_OVERLAP, INVALID_TIME_NORMALIZATION, AVOIDING_PADDING_BY_EDGES, @@ -34,17 +35,17 @@ jest.mock('luxon', () => { fromDateTimes: jest.fn((start, end) => ({ start, end, - splitBy: jest.fn(() => { + splitBy: jest.fn(duration => { const intervals = []; let current = start; while (current < end) { intervals.push({ start: process.env.MOCK_INTERVAL === 'true' ? null : current, - end: current.plus({seconds: 1}), + end: current.plus(duration), }); - current = current.plus({seconds: 1}); + current = current.plus(duration); } return intervals; @@ -942,6 +943,157 @@ describe('builtins/time-sync:', () => { expect(result).toStrictEqual(expectedResult); }); + + it('should throw an error if the upsampling resolution is not compatible with the interval', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:03.000Z', + interval: 3, + 'allow-padding': true, + 'upsampling-resolution': 2, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + expect.assertions(1); + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:02.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + ); + } + }); + + it('should throw an error if the upsampling resolution is not compatible with paddings', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:12.000Z', + interval: 2, + 'allow-padding': true, + 'upsampling-resolution': 2, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + expect.assertions(1); + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 10, + 'cpu/utilization': 10, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + ); + } + }); + + it('should throw an error if the upsampling resolution is not compatible with gaps', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:12.000Z', + interval: 5, + 'allow-padding': true, + 'upsampling-resolution': 5, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + expect.assertions(1); + try { + await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + }, + { + timestamp: '2023-12-12T00:00:07.000Z', + duration: 5, + }, + ]); + } catch (error) { + expect(error).toStrictEqual( + new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + ); + } + }); + + it('should upsample and resample correctly with a custom upsampling resolution given', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:20.000Z', + interval: 5, + 'allow-padding': true, + 'upsampling-resolution': 5, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + }, + ]); + const expected = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 5, + }, + { + timestamp: '2023-12-12T00:00:15.000Z', + duration: 5, + }, + ]; + expect(result).toEqual(expected); + }); + + it('checks that metric carbon with aggregation == sum is properly spread over interpolated time points with custom upsampling resolution given', async () => { + const basicConfig = { + 'start-time': '2023-12-12T00:00:00.000Z', + 'end-time': '2023-12-12T00:00:15.000Z', + interval: 5, + 'allow-padding': true, + 'upsampling-resolution': 5, + }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); + const result = await timeModel.execute([ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 15, + carbon: 3, + }, + ]); + + const expected = [ + { + timestamp: '2023-12-12T00:00:00.000Z', + duration: 5, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:05.000Z', + duration: 5, + carbon: 1, + }, + { + timestamp: '2023-12-12T00:00:10.000Z', + duration: 5, + carbon: 1, + }, + ]; + expect(result).toEqual(expected); + }); }); }); }); diff --git a/src/if-run/builtins/time-sync/README.md b/src/if-run/builtins/time-sync/README.md index 196724657..dd09a89f2 100644 --- a/src/if-run/builtins/time-sync/README.md +++ b/src/if-run/builtins/time-sync/README.md @@ -9,9 +9,10 @@ Time sync standardizes the start time, end time and temporal resolution of all o The following should be defined in the plugin initialization: - `start-time`: global start time as ISO 8061 string -- `stop`: global end time as ISO 8061 string +- `end-time`: global end time as ISO 8061 string - `interval`: temporal resolution in seconds -- `error-on-padding`: avoid zero/'zeroish' padding (if needed) and error out instead. `False` by defult. +- `allow-padding`: avoid zero/'zeroish' padding (if needed) and error out instead. +- `upsampling-resolution`: temporal resolution at which observations will be upsampled, in seconds. Defaults to 1. #### Inputs: @@ -28,7 +29,7 @@ A manifest file for a tree might contain many nodes each representing some diffe We do this by implementing the following logic: - Shift readings to nearest whole seconds -- Upsample the time series to a base resolution (1s) +- Upsample the time series to a base resolution. - Resample to desired resolution by batching 1s entries - Extrapolate or trim to ensure all time series share global start and end dates @@ -39,6 +40,7 @@ The next section explains each stage in more detail. ##### Upsampling rules A set of `inputs` is naturally a time series because all `observations` include a `timestamp` and a `duration`, measured in seconds. + For each `observation` in `inputs` we check whether the duration is greater than 1 second. If `duration` is greater than 1 second, we create N new `observation` objects, where N is equal to `duration`. This means we have an `observation` for every second between the initial timestamp and the end of the observation period. Each new object receives a timestamp incremented by one second. This looks as follows: @@ -54,6 +56,7 @@ This looks as follows: {timestamp: '2023-12-12T00:00:04.000Z', duration: 1} {timestamp: '2023-12-12T00:00:05.000Z', duration: 1} ] + ``` Each `observation` actually includes many key-value pairs. The precise content of the `observation` is not known until runtime because it depends on which plugins have been included in the pipeline. Different values have to be treated differently when we upsample in time. The method we use to upsample depends on the `aggregation-method` defined for each key in `units.yml`. @@ -151,12 +154,31 @@ For example, for `startTime = 2023-12-12T00:00:00.000Z` and `endTime = 2023-12-1 ] ``` -Note that when `error-on-padding` is `true` no padding is performed and the plugin will error out instead. +Note that when `allow-padding` is `true` no padding is performed and the plugin will error out instead. ##### Resampling rules Now we have synchronized, continuous, high resolution time series data, we can resample. To achieve this, we use `interval`, which sets the global temporal resolution for the final, processed time series. `interval` is expressed in units of seconds, which means we can simply batch `observations` together in groups of size `interval`. For each value in each object we either sum, average or copy the values into one single summary object representing each time bucket of size `interval` depending on their `aggregation-method` defined in `aggregation` section in the manifest file. The returned array is the final, synchronized time series at the desired temporal resolution. +#### Setting a custom upsampling resolution + +The model defaults to upsampling observations to a 1-second resolution. However, this can lead to unnecessary effort, as upsampling at a coarser resolution is often sufficient, provided it doesn't interfere with the accuracy of resampling. To optimize performance, we can set the `upsampling-resolution` parameter in the configuration to a more appropriate value. The chosen value should meet the following criteria : + +- It should evenly divide all observation durations within the dataset. +- It must be a divisor of the `interval`. +- It should also divide any gaps between observations, as well as the start and end paddings. + +For example, for `interval = 10` and this time-series + +```ts +[ + {timestamp: '2023-12-12T00:00:00.000Z', duration: 300}, +] +```` +setting the `upsampling-resolution` to `10s` is preferable to the default behavior. +If the default behavior were used, the model would create `300` samples of `1s` each, which would be inefficient. By setting a custom `upsampling-resolution` of `10s`, the model only generates `30` samples, each representing `10s`. + + #### Assumptions and limitations To do time synchronization, we assume: @@ -173,7 +195,8 @@ Then, you can call `execute()`. const config = { 'start-time': '2023-12-12T00:00:00.000Z', 'end-time': '2023-12-12T00:00:30.000Z', - interval: 10 + interval: 10, + 'allow-padding': true, } const timeSync = TimeSync(config); const results = timeSync.execute([ diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 5e3b56e02..329963bba 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -11,13 +11,13 @@ import { ExecutePlugin, PluginParams, PaddingReceipt, - TimeNormalizerConfig, - TimeParams, PluginParametersMetadata, ParameterMetadata, MappingParams, } from '@grnsft/if-core/types'; +import {TimeParams, TimeNormalizerConfig} from '../../types/time-sync'; + import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; @@ -33,6 +33,7 @@ const { } = ERRORS; const { + INVALID_UPSAMPLING_RESOLUTION, INVALID_TIME_NORMALIZATION, INVALID_OBSERVATION_OVERLAP, AVOIDING_PADDING_BY_EDGES, @@ -98,11 +99,16 @@ export const TimeSync = ( endTime: DateTime.fromISO(validatedConfig['end-time']), interval: validatedConfig.interval, allowPadding: validatedConfig['allow-padding'], + upsamplingResolution: validatedConfig['upsampling-resolution'] + ? validatedConfig['upsampling-resolution'] + : 1, }; - + validateIntervalForResample( + timeParams.interval, + timeParams.upsamplingResolution + ); const pad = checkForPadding(inputs, timeParams); validatePadding(pad, timeParams); - const paddedInputs = padInputs(inputs, pad, timeParams); const flattenInputs = paddedInputs.reduce( @@ -137,20 +143,33 @@ export const TimeSync = ( .diff(compareableTime) .as('seconds'); - /** Checks if there is gap in timeline. */ + validateIntervalForResample( + input.duration, + timeParams.upsamplingResolution + ); + if (timelineGapSize > 1) { + /** Checks if there is gap in timeline. */ acc.push( ...getZeroishInputPerSecondBetweenRange( - compareableTime, - currentMoment, + { + startDate: compareableTime, + endDate: currentMoment, + timeStep: timeParams.upsamplingResolution, + }, safeInput ) ); } } + /** Break down current observation. */ - for (let i = 0; i < safeInput.duration; i++) { - const normalizedInput = breakDownInput(safeInput, i); + for ( + let i = 0; + i <= safeInput.duration - timeParams.upsamplingResolution; + i += timeParams.upsamplingResolution + ) { + const normalizedInput = breakDownInput(safeInput, i, timeParams); acc.push(normalizedInput); } @@ -163,11 +182,19 @@ export const TimeSync = ( const sortedInputs = flattenInputs.sort((a, b) => parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') ); - const outputs = resampleInputs(sortedInputs, timeParams) as PluginParams[]; return outputs.map(output => mapOutputIfNeeded(output, mapping)); }; + /** + * Checks if a given duration is compatible with a given timeStep. If not, throws an error + */ + const validateIntervalForResample = (duration: number, timeStep: number) => { + if (duration % timeStep !== 0) { + throw new ConfigError(INVALID_UPSAMPLING_RESOLUTION); + } + }; + /** * Dates are passed to `time-sync` both in ISO 8601 format * and as a Date object (from the deserialization of a YAML file). @@ -224,6 +251,7 @@ export const TimeSync = ( 'end-time': z.string().datetime(), interval: z.number(), 'allow-padding': z.boolean(), + 'upsampling-resolution': z.number().min(1).optional(), }) .refine(data => data['start-time'] < data['end-time'], { message: START_LOWER_END, @@ -235,8 +263,14 @@ export const TimeSync = ( /** * Calculates minimal factor. */ - const convertPerInterval = (value: number, duration: number) => - value / duration; + const convertPerInterval = ( + value: number, + duration: number, + timeStep: number + ) => { + const samplesNumber = duration / timeStep; + return value / samplesNumber; + }; /** * Normalize time per given second. @@ -253,9 +287,14 @@ export const TimeSync = ( /** * Breaks down input per minimal time unit. */ - const breakDownInput = (input: PluginParams, i: number) => { + const breakDownInput = ( + input: PluginParams, + i: number, + params: TimeParams + ) => { const evaluatedInput = evaluateInput(input); const metrics = Object.keys(evaluatedInput); + const timeStep = params.upsamplingResolution; return metrics.reduce((acc, metric) => { const aggregationParams = getAggregationInfoFor(metric); @@ -267,9 +306,8 @@ export const TimeSync = ( return acc; } - /** @todo use user defined resolution later */ if (metric === 'duration') { - acc[metric] = 1; + acc[metric] = timeStep; return acc; } @@ -284,7 +322,8 @@ export const TimeSync = ( aggregationParams.time === 'sum' ? convertPerInterval( evaluatedInput[metric], - evaluatedInput['duration'] + evaluatedInput['duration'], + timeStep ) : evaluatedInput[metric]; @@ -297,10 +336,10 @@ export const TimeSync = ( */ const fillWithZeroishInput = ( input: PluginParams, - missingTimestamp: DateTimeMaybeValid + missingTimestamp: DateTimeMaybeValid, + timeStep: number ) => { const metrics = Object.keys(input); - return metrics.reduce((acc, metric) => { if (metric === 'timestamp') { acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; @@ -308,9 +347,8 @@ export const TimeSync = ( return acc; } - /** @todo later will be changed to user defined interval */ if (metric === 'duration') { - acc[metric] = 1; + acc[metric] = timeStep; return acc; } @@ -381,7 +419,6 @@ export const TimeSync = ( .plus({second: eval(lastInput.duration)}) .diff(params.endTime) .as('seconds'); - return { start: startDiffInSeconds > 0, end: endDiffInSeconds < 0, @@ -452,10 +489,11 @@ export const TimeSync = ( */ const resampleInputs = (inputs: PluginParams[], params: TimeParams) => inputs.reduce((acc: PluginParams[], _input, index, inputs) => { - const frameStart = index * params.interval; - const frameEnd = (index + 1) * params.interval; + const frameStart = + (index * params.interval) / params.upsamplingResolution; + const frameEnd = + ((index + 1) * params.interval) / params.upsamplingResolution; const inputsFrame = inputs.slice(frameStart, frameEnd); - const resampledInput = resampleInputFrame(inputsFrame); /** Checks if resampled input is not empty, then includes in result. */ @@ -480,8 +518,11 @@ export const TimeSync = ( if (start) { paddedFromBeginning.push( ...getZeroishInputPerSecondBetweenRange( - params.startTime, - parseDate(inputs[0].timestamp), + { + startDate: params.startTime, + endDate: parseDate(inputs[0].timestamp), + timeStep: params.upsamplingResolution, + }, inputs[0] ) ); @@ -496,8 +537,11 @@ export const TimeSync = ( }); paddedArray.push( ...getZeroishInputPerSecondBetweenRange( - lastInputEnd, - params.endTime, + { + startDate: lastInputEnd, + endDate: params.endTime, + timeStep: params.upsamplingResolution, + }, lastInput ) ); @@ -510,21 +554,25 @@ export const TimeSync = ( * Brakes down the given range by 1 second, and generates zeroish values. */ const getZeroishInputPerSecondBetweenRange = ( - startDate: DateTimeMaybeValid, - endDate: DateTimeMaybeValid, - templateInput: PluginParams + params: PluginParams, + input: PluginParams ) => { const array: PluginParams[] = []; - const dateRange = Interval.fromDateTimes(startDate, endDate); + validateIntervalForResample( + params.endDate.diff(params.startDate).as('seconds'), + params.timeStep + ); + const dateRange = Interval.fromDateTimes(params.startDate, params.endDate); - for (const interval of dateRange.splitBy({second: 1})) { + for (const interval of dateRange.splitBy({second: params.timeStep})) { array.push( fillWithZeroishInput( - templateInput, + input, // as far as I can tell, start will never be null // because if we pass an invalid start/endDate to // Interval, we get a zero length array as the range - interval.start || DateTime.invalid('not expected - start is null') + interval.start || DateTime.invalid('not expected - start is null'), + params.timeStep ) ); } diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index e549c3b72..977004dab 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -10,6 +10,8 @@ export const STRINGS = { `Provided module \`${path}\` is invalid or not found. ${error ?? ''} `, INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', + INVALID_UPSAMPLING_RESOLUTION: + 'Upsampling resolution does not adhere to all constraints', UNEXPECTED_TIME_CONFIG: 'Unexpected node-level config provided for time-sync plugin.', INVALID_TIME_INTERVAL: 'Interval is missing.', From 9dddd5dcd226ed75b2a6968df6bdc55ab8374f31 Mon Sep 17 00:00:00 2001 From: manushak Date: Thu, 19 Sep 2024 20:48:24 +0400 Subject: [PATCH 784/863] feat(builtins): refactor , and plugins --- src/if-run/builtins/coefficient/index.ts | 173 +++++--------------- src/if-run/builtins/divide/index.ts | 195 +++++++---------------- src/if-run/builtins/sci/index.ts | 189 +++++++--------------- 3 files changed, 160 insertions(+), 397 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 12de779d8..167fe14e0 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,143 +1,52 @@ -import {z, ZodType} from 'zod'; - -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - getParameterFromArithmeticExpression, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - CoefficientConfig, - ExecutePlugin, - MappingParams, - PluginParametersMetadata, - PluginParams, -} from '@grnsft/if-core/types'; +import {z} from 'zod'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {STRINGS} from '../../config'; - -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; +export const Coefficient = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + coefficient: z.number(), + 'input-parameter': z.string().min(1), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const inputData = { + 'input-parameter': input[config['input-parameter']], + }; + const validationSchema = z.record(z.string(), z.number()); + validate(validationSchema, inputData); -export const Coefficient = ( - config: CoefficientConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; + return input; + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + const inputParameter = config['input-parameter']; + const outputParameter = config['output-parameter']; + const coefficient = config['coefficient']; - /** - * Calculate the product of each input parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const { - 'input-parameter': inputParameter, - 'output-parameter': outputParameter, - } = safeConfig; return inputs.map(input => { - const calculatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: ['input-parameter', 'coefficient'], - }); - - const safeInput = validateSingleInput(input, inputParameter); - const coefficient = Number(calculatedConfig['coefficient']); - const calculatedResult = calculateProduct( - safeInput, - calculatedConfig['input-parameter'], - coefficient - ); - const result = { ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), + [outputParameter]: calculateProduct(input, inputParameter, coefficient), }; - return mapOutputIfNeeded(result, mapping); + return result; }); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - configInputParameter: string - ) => { - const inputParameter = - getParameterFromArithmeticExpression(configInputParameter); - const evaluatedInput = evaluateInput(input); - - const inputData = { - [inputParameter]: evaluatedInput[inputParameter], - }; - const validationSchema = z.record(z.string(), z.number()); - validate(validationSchema, inputData); - - return evaluatedInput; - }; - - /** - * Calculates the product of the energy components. - */ - const calculateProduct = ( - input: PluginParams, - inputParameter: string | number, - coefficient: number - ) => - (isNaN(Number(inputParameter)) ? input[inputParameter] : inputParameter) * - coefficient; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z - .object({ - coefficient: z.preprocess( - value => validateArithmeticExpression('coefficient', value), - z.number() - ), - 'input-parameter': z.string().min(1), - 'output-parameter': z.string().min(1), - }) - .refine(params => { - Object.entries(params).forEach(([param, value]) => - validateArithmeticExpression(param, value) - ); - - return true; - }); - - return validate>( - configSchema as ZodType, - mappedConfig - ); - }; - - return { - metadata, - execute, - }; -}; + }, + allowArithmeticExpressions: ['input-parameter', 'coefficient'], +}); + +/** + * Calculates the product of the energy components. + */ +const calculateProduct = ( + input: PluginParams, + inputParameter: string | number, + coefficient: number +) => + (isNaN(Number(inputParameter)) ? input[inputParameter] : inputParameter) * + coefficient; diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 07ab3ba8a..ff35fd9b5 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -1,110 +1,27 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, - getParameterFromArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {STRINGS} from '../../config'; - -const {ConfigError, MissingInputDataError} = ERRORS; -const {MISSING_CONFIG, MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; - -export const Divide = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Calculate the division of each input parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const {numerator, denominator, output} = safeConfig; - - return inputs.map((input, index) => { - const evaluatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: ['numerator', 'denominator'], - }); - const safeInput = validateSingleInput(input, safeConfig); - const calculatedResult = calculateDivide(safeInput, index, { - numerator: evaluatedConfig.numerator || numerator, - denominator: evaluatedConfig.denominator || denominator, - }); +import {ERRORS} from '@grnsft/if-core/utils'; - const result = { - ...input, - ...safeInput, - ...evaluateArithmeticOutput(output, calculatedResult), - }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - const schema = z - .object({ - numerator: z.string().min(1), - denominator: z.string().or(z.number()), - output: z.string(), - }) - .refine(params => { - Object.entries(params).forEach(([param, value]) => - validateArithmeticExpression(param, value) - ); - - return true; - }); - - return validate>(schema, mappedConfig); - }; +import {STRINGS} from '../../config'; - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - safeConfig: ConfigParams - ) => { - const numerator = getParameterFromArithmeticExpression( - safeConfig.numerator - ); - const denominator = getParameterFromArithmeticExpression( - safeConfig.denominator - ); +const {MissingInputDataError} = ERRORS; +const {MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; +export const Divide = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + numerator: z.string().min(1), + denominator: z.string().or(z.number()), + output: z.string(), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const {numerator, denominator} = config; const schema = z .object({ @@ -119,39 +36,49 @@ export const Divide = ( return true; }); - const evaluatedInput = evaluateInput(input); - return validate>(schema, evaluatedInput); - }; + return validate>(schema, input); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + const {numerator, denominator, output} = config; - /** - * Calculates the division of the given parameter. - */ - const calculateDivide = ( - input: PluginParams, - index: number, - params: { - numerator: number | string; - denominator: number | string; - } - ) => { - const {denominator, numerator} = params; - const finalDenominator = - typeof denominator === 'number' - ? denominator - : input[denominator] || denominator; - const finalNumerator = - typeof numerator === 'number' ? numerator : input[numerator]; - - if (finalDenominator === 0) { - console.warn(ZERO_DIVISION(Divide.name, index)); - return finalNumerator; - } - - return finalNumerator / finalDenominator; - }; + return inputs.map((input, index) => { + const calculatedResult = calculateDivide(input, index, { + numerator: input.numerator || numerator, + denominator: input.denominator || denominator, + }); - return { - metadata, - execute, - }; + return { + ...input, + [output]: calculatedResult, + }; + }); + }, + allowArithmeticExpressions: ['numerator', 'denominator'], +}); + +/** + * Calculates the division of the given parameter. + */ +const calculateDivide = ( + input: PluginParams, + index: number, + params: { + numerator: number | string; + denominator: number | string; + } +) => { + const {denominator, numerator} = params; + const finalDenominator = + typeof denominator === 'number' + ? denominator + : input[denominator] || denominator; + const finalNumerator = + typeof numerator === 'number' ? numerator : input[numerator]; + + if (finalDenominator === 0) { + console.warn(ZERO_DIVISION(Divide.name, index)); + return finalNumerator; + } + + return finalNumerator / finalDenominator; }; diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 7e98a8f0e..852faf2dc 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -1,32 +1,15 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, - getParameterFromArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapInputIfNeeded, - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - PluginParametersMetadata, - ParameterMetadata, - MappingParams, -} from '@grnsft/if-core/types'; -import {validate, allDefined} from '../../../common/util/validations'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; -import {STRINGS} from '../../config'; +import {validate} from '../../../common/util/validations'; + +import {ERRORS} from '@grnsft/if-core/utils'; + +import {allDefined} from '../../../common/util/validations'; -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; +import {STRINGS} from '../../config'; const {MissingInputDataError} = ERRORS; const { @@ -36,36 +19,28 @@ const { ZERO_DIVISION, } = STRINGS; -export const Sci = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', +export const Sci = PluginFactory({ + metadata: { inputs: { - ...({ - carbon: { - description: 'an amount of carbon emitted into the atmosphere', - unit: 'gCO2e', - 'aggregation-method': { - time: 'sum', - component: 'sum', - }, + carbon: { + description: 'an amount of carbon emitted into the atmosphere', + unit: 'gCO2e', + 'aggregation-method': { + time: 'sum', + component: 'sum', }, - 'functional-unit': { - description: - 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', - unit: 'none', - 'aggregation-method': { - time: 'sum', - component: 'sum', - }, + }, + 'functional-unit': { + description: + 'the name of the functional unit in which the final SCI value should be expressed, e.g. requests, users', + unit: 'none', + 'aggregation-method': { + time: 'sum', + component: 'sum', }, - } as ParameterMetadata), - ...parametersMetadata?.inputs, + }, }, - outputs: parametersMetadata?.outputs || { + outputs: { sci: { description: 'carbon expressed in terms of the given functional unit', unit: 'gCO2e', @@ -75,86 +50,22 @@ export const Sci = ( }, }, }, - }; - - /** - * Validates config. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); + }, + configValidation: (config: ConfigParams) => { const schema = z .object({ - 'functional-unit': z - .string() - .refine(param => - validateArithmeticExpression('functional-unit', param) - ), + 'functional-unit': z.string(), }) .refine(data => data['functional-unit'], { message: MISSING_FUNCTIONAL_UNIT_CONFIG, }); - return validate>(schema, mappedConfig); - }; - - /** - * Calculate the total emissions for a list of inputs. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeConfig = validateConfig(); + return validate>(schema, config); + }, + inputValidation: (input: PluginParams, config: ConfigParams) => { + const functionalUnit = config['functional-unit']; - return inputs.map((input, index) => { - const safeInput = Object.assign( - {}, - input, - validateInput(input, safeConfig) - ); - - const evaluatedConfig = evaluateConfig({ - config: safeConfig, - input: safeInput, - parametersToEvaluate: ['functional-unit'], - }); - const functionalUnit = isNaN(evaluatedConfig['functional-unit']) - ? safeInput[evaluatedConfig['functional-unit']] - : evaluatedConfig['functional-unit']; - - if (functionalUnit === 0) { - console.warn(ZERO_DIVISION(Sci.name, index)); - - return { - ...input, - ...safeInput, - sci: safeInput['carbon'], - }; - } - const calculatedResult = safeInput['carbon'] / functionalUnit; - - const result = { - ...input, - ...safeInput, - ...evaluateArithmeticOutput('sci', calculatedResult), - }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Checks for fields in input. - */ - const validateInput = (input: PluginParams, safeConfig: ConfigParams) => { - const mappedInput = mapInputIfNeeded(input, mapping); - - const functionalUnit = getParameterFromArithmeticExpression( - safeConfig['functional-unit'] - ); - - if (!(functionalUnit in mappedInput && mappedInput[functionalUnit] >= 0)) { + if (!(functionalUnit in input && input[functionalUnit] >= 0)) { throw new MissingInputDataError(MISSING_FUNCTIONAL_UNIT_INPUT); } @@ -167,13 +78,29 @@ export const Sci = ( message: SCI_MISSING_FN_UNIT(config['functional-unit']), }); - const evaluatedInput = evaluateInput(mappedInput); + return validate>(schema, input); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + return inputs.map((input, index) => { + const functionalUnit = isNaN(config['functional-unit']) + ? input[config['functional-unit']] + : config['functional-unit']; - return validate>(schema, evaluatedInput); - }; + if (functionalUnit === 0) { + console.warn(ZERO_DIVISION(Sci.name, index)); - return { - metadata, - execute, - }; -}; + return { + ...input, + sci: input['carbon'], + }; + } + const calculatedResult = input['carbon'] / functionalUnit; + + return { + ...input, + sci: calculatedResult, + }; + }); + }, + allowArithmeticExpressions: ['functional-unit'], +}); From 7e5d867d11a311ccd61381de8b0c6edaff258ecb Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 20 Sep 2024 20:17:12 +0400 Subject: [PATCH 785/863] feat(builtins): refactor plugins --- src/if-run/builtins/coefficient/index.ts | 20 +- src/if-run/builtins/copy-param/index.ts | 132 ++---- src/if-run/builtins/csv-lookup/index.ts | 380 ++++++++---------- src/if-run/builtins/divide/index.ts | 2 +- src/if-run/builtins/exponent/index.ts | 168 ++------ src/if-run/builtins/interpolation/index.ts | 309 ++++++-------- .../builtins/mock-observations/index.ts | 296 ++++++-------- src/if-run/builtins/multiply/index.ts | 131 ++---- src/if-run/builtins/subtract/index.ts | 148 ++----- src/if-run/builtins/time-converter/index.ts | 192 +++------ 10 files changed, 624 insertions(+), 1154 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 167fe14e0..1383e6d66 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -24,18 +24,16 @@ export const Coefficient = PluginFactory({ return input; }, implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { - const inputParameter = config['input-parameter']; - const outputParameter = config['output-parameter']; - const coefficient = config['coefficient']; + const { + 'input-parameter': inputParameter, + 'output-parameter': outputParameter, + coefficient, + } = config; - return inputs.map(input => { - const result = { - ...input, - [outputParameter]: calculateProduct(input, inputParameter, coefficient), - }; - - return result; - }); + return inputs.map(input => ({ + ...input, + [outputParameter]: calculateProduct(input, inputParameter, coefficient), + })); }, allowArithmeticExpressions: ['input-parameter', 'coefficient'], }); diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index d10fb5546..17af2568f 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,127 +1,53 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - getParameterFromArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ConfigParams, - ExecutePlugin, - MappingParams, - PluginParametersMetadata, - PluginParams, -} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {STRINGS} from '../../config'; - -const {MISSING_CONFIG} = STRINGS; -const {ConfigError} = 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 = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z.object({ - 'keep-existing': z.boolean(), - from: z.string().min(1).or(z.number()), - to: z.string().min(1), - }); - - return validate>(configSchema, mappedConfig); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - configInputParameter: string | number - ) => { - const inputParameter = getParameterFromArithmeticExpression( - configInputParameter.toString() - ); - const evaluatedInput = evaluateInput(input); +export const Copy = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'keep-existing': z.boolean(), + from: z.string().min(1).or(z.number()), + to: z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const from = config.from; const inputData = { - [inputParameter]: evaluatedInput[inputParameter], + [from]: input[from], }; - const validationSchema = z.record(z.string(), z.string().or(z.number())); - validate(validationSchema, inputData); - - return evaluatedInput; - }; - - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const keepExisting = safeConfig['keep-existing'] === true; - const from = safeConfig['from']; - const to = safeConfig['to']; + return validate(validationSchema, inputData); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + const keepExisting = config['keep-existing'] === true; + const from = config['from']; + const to = config['to']; return inputs.map(input => { - const evaluatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: ['from'], - }); - - const safeInput = validateSingleInput(input, from); - const safeFrom = getParameterFromArithmeticExpression(from.toString()); + const outputValue = !isNaN(config?.from) ? config.from : input[from]; - const outputValue = !isNaN(evaluatedConfig?.from) - ? evaluatedConfig.from - : safeInput[safeFrom]; - - if (safeInput[safeFrom]) { + if (input[from]) { if (!keepExisting) { - delete input[safeFrom]; - delete safeInput[safeFrom]; + delete input[from]; } } - const result = { + return { ...input, - ...safeInput, - ...evaluateArithmeticOutput(to, outputValue), + [to]: outputValue, }; - - return mapOutputIfNeeded(result, mapping); }); - }; - - return { - metadata, - execute, - }; -}; + }, + allowArithmeticExpressions: ['from'], +}); diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 63a4a3496..8fb1e5535 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -1,210 +1,46 @@ /* eslint-disable eqeqeq */ import {readFile} from 'fs/promises'; - import axios from 'axios'; import {z} from 'zod'; import {parse} from 'csv-parse/sync'; + +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; import {ERRORS} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - MappingParams, - PluginParametersMetadata, - PluginParams, -} from '@grnsft/if-core/types'; - -import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const { - FILE_FETCH_FAILED, - FILE_READ_FAILED, - MISSING_CSV_COLUMN, - NO_QUERY_DATA, - MISSING_CONFIG, -} = STRINGS; +const {FILE_FETCH_FAILED, FILE_READ_FAILED, MISSING_CSV_COLUMN, NO_QUERY_DATA} = + STRINGS; const { FetchingFileError, ReadFileError, MissingCSVColumnError, QueryDataNotFoundError, - ConfigError, CSVParseError, } = ERRORS; -export const CSVLookup = ( - config: any, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks if given string is URL. - */ - const isURL = (filepath: string) => { - try { - new URL(filepath); - return true; - } catch (error) { - return false; - } - }; - - /** - * Checks if given `filepath` is url, then tries to fetch it. - * Otherwise tries to read file. - */ - const retrieveFile = async (filepath: string) => { - if (isURL(filepath)) { - const {data} = await axios.get(filepath).catch(error => { - throw new FetchingFileError( - FILE_FETCH_FAILED(filepath, error.response.message) - ); - }); - - return data; - } - - return readFile(filepath).catch(error => { - throw new ReadFileError(FILE_READ_FAILED(filepath, error)); - }); - }; - - /** - * Checks if value is invalid: `undefined`, `null` or an empty string, then sets `nan` instead. - */ - const setNanValue = (value: any) => - value == null || value === '' ? 'nan' : value; - - /** - * Converts empty values to `nan`. - */ - const nanifyEmptyValues = (object: any) => { - if (typeof object === 'object') { - const keys = Object.keys(object); - - keys.forEach(key => { - const value = object[key]; - object[key] = setNanValue(value); - }); - - return object; - } - - return setNanValue(object); - }; - - /** - * If `field` is missing from `object`, then reject with error. - * Otherwise nanify empty values and return data. - */ - const fieldAccessor = (field: string, object: any) => { - if (!(`${field}` in object)) { - throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); - } - - return nanifyEmptyValues(object[field]); - }; - - /** - * 1. If output is anything, then removes query data from csv record to escape duplicates. - * 2. Otherwise checks if it's a miltidimensional array, then grabs multiple fields (). - * 3. If not, then returns single field. - * 4. In case if it's string, then - */ - const filterOutput = ( - dataFromCSV: any, - params: { - output: string | string[] | string[][]; - query: Record; - } - ) => { - const {output, query} = params; - - if (output === '*') { - const keys = Object.keys(query); - - keys.forEach(key => { - delete dataFromCSV[key]; - }); - - return nanifyEmptyValues(dataFromCSV); - } - - if (Array.isArray(output)) { - /** Check if it's a multidimensional array. */ - if (Array.isArray(output[0])) { - const result: any = {}; - - output.forEach(outputField => { - /** Check if there is no renaming request, then export as is */ - const outputTitle = outputField[1] || outputField[0]; - result[outputTitle] = fieldAccessor(outputField[0], dataFromCSV); - }); - - return result; - } - - const outputTitle = output[1] || output[0]; - - return { - [outputTitle as string]: fieldAccessor(output[0], dataFromCSV), - }; - } - - return { - [output]: fieldAccessor(output, dataFromCSV), - }; - }; - - /** - * Asserts CSV record with query data. - */ - const withCriteria = (queryData: Record) => (csvRecord: any) => { - const ifMatchesCriteria = Object.keys(queryData).map( - (key: string) => csvRecord[key] == queryData[key] - ); - - return ifMatchesCriteria.every(value => value === true); - }; - - /** - * Parses CSV file. - */ - const parseCSVFile = (file: string | Buffer) => { - try { - const parsedCSV: any[] = parse(file, { - columns: true, - skip_empty_lines: true, - cast: true, - }); - - return parsedCSV; - } catch (error: any) { - console.error(error); - throw new CSVParseError(error); - } - }; - - /** - * 1. Validates config. - * 2. Tries to retrieve given file (with url or local path). - * 3. Parses given CSV. - * 4. Filters requested information from CSV. - */ - const execute = async (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const {filepath, query, output} = safeConfig; +export const CSVLookup = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + filepath: z.string(), + query: z.record(z.string(), z.string()), + output: z + .string() + .or(z.array(z.string())) + .or(z.array(z.array(z.string()))), + }), + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + /** + * 1. Tries to retrieve given file (with url or local path). + * 2. Parses given CSV. + * 3. Filters requested information from CSV. + */ + const {filepath, query, output} = config; const file = await retrieveFile(filepath); const parsedCSV = parseCSVFile(file); @@ -224,38 +60,158 @@ export const CSVLookup = ( throw new QueryDataNotFoundError(NO_QUERY_DATA); } - const result = { + return { ...input, ...filterOutput(relatedData, {output, query}), }; + }); + }, +}); + +/** + * Checks if given string is URL. + */ +const isURL = (filepath: string) => { + try { + new URL(filepath); + return true; + } catch (error) { + return false; + } +}; - return mapOutputIfNeeded(result, mapping); +/** + * Checks if given `filepath` is url, then tries to fetch it. + * Otherwise tries to read file. + */ +const retrieveFile = async (filepath: string) => { + if (isURL(filepath)) { + const {data} = await axios.get(filepath).catch(error => { + throw new FetchingFileError( + FILE_FETCH_FAILED(filepath, error.response.message) + ); }); - }; - /** - * Checks for `filepath`, `query` and `output` fields in config. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z.object({ - filepath: z.string(), - query: z.record(z.string(), z.string()), - output: z - .string() - .or(z.array(z.string())) - .or(z.array(z.array(z.string()))), + return data; + } + + return readFile(filepath).catch(error => { + throw new ReadFileError(FILE_READ_FAILED(filepath, error)); + }); +}; + +/** + * Checks if value is invalid: `undefined`, `null` or an empty string, then sets `nan` instead. + */ +const setNanValue = (value: any) => + value == null || value === '' ? 'nan' : value; + +/** + * Converts empty values to `nan`. + */ +const nanifyEmptyValues = (object: any) => { + if (typeof object === 'object') { + const keys = Object.keys(object); + + keys.forEach(key => { + const value = object[key]; + object[key] = setNanValue(value); }); - return validate>(configSchema, mappedConfig); - }; + return object; + } + + return setNanValue(object); +}; + +/** + * If `field` is missing from `object`, then reject with error. + * Otherwise nanify empty values and return data. + */ +const fieldAccessor = (field: string, object: any) => { + if (!(`${field}` in object)) { + throw new MissingCSVColumnError(MISSING_CSV_COLUMN(field)); + } + + return nanifyEmptyValues(object[field]); +}; + +/** + * 1. If output is anything, then removes query data from csv record to escape duplicates. + * 2. Otherwise checks if it's a miltidimensional array, then grabs multiple fields (). + * 3. If not, then returns single field. + * 4. In case if it's string, then + */ +const filterOutput = ( + dataFromCSV: any, + params: { + output: string | string[] | string[][]; + query: Record; + } +) => { + const {output, query} = params; + + if (output === '*') { + const keys = Object.keys(query); + + keys.forEach(key => { + delete dataFromCSV[key]; + }); + + return nanifyEmptyValues(dataFromCSV); + } + + if (Array.isArray(output)) { + /** Check if it's a multidimensional array. */ + if (Array.isArray(output[0])) { + const result: any = {}; + + output.forEach(outputField => { + /** Check if there is no renaming request, then export as is */ + const outputTitle = outputField[1] || outputField[0]; + result[outputTitle] = fieldAccessor(outputField[0], dataFromCSV); + }); + + return result; + } + + const outputTitle = output[1] || output[0]; + + return { + [outputTitle as string]: fieldAccessor(output[0], dataFromCSV), + }; + } return { - metadata, - execute, + [output]: fieldAccessor(output, dataFromCSV), }; }; + +/** + * Asserts CSV record with query data. + */ +const withCriteria = (queryData: Record) => (csvRecord: any) => { + const ifMatchesCriteria = Object.keys(queryData).map( + (key: string) => csvRecord[key] == queryData[key] + ); + + return ifMatchesCriteria.every(value => value === true); +}; + +/** + * Parses CSV file. + */ +const parseCSVFile = (file: string | Buffer) => { + try { + const parsedCSV: any[] = parse(file, { + columns: true, + skip_empty_lines: true, + cast: true, + }); + + return parsedCSV; + } catch (error: any) { + console.error(error); + throw new CSVParseError(error); + } +}; diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index ff35fd9b5..d211ff05c 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -38,7 +38,7 @@ export const Divide = PluginFactory({ return validate>(schema, input); }, - implementation: async (inputs: PluginParams[], config: ConfigParams) => { + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const {numerator, denominator, output} = config; return inputs.map((input, index) => { diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 500ea96a3..c401e33dc 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -1,151 +1,65 @@ -import {z, ZodType} from 'zod'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - getParameterFromArithmeticExpression, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - ExecutePlugin, - PluginParams, - ExponentConfig, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; +import {z} from 'zod'; -import {validate} from '../../../common/util/validations'; - -import {STRINGS} from '../../config'; - -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -export const Exponent = ( - config: ExponentConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } +import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; - const mappedConfig = mapConfigIfNeeded(config, mapping); - const configSchema = z - .object({ - 'input-parameter': z.string().min(1), - exponent: z.preprocess( - value => validateArithmeticExpression('exponent', value), - z.number() - ), - 'output-parameter': z.string().min(1), - }) - .refine(params => { - Object.entries(params).forEach(([param, value]) => - validateArithmeticExpression(param, value) - ); - - return true; - }); - - return validate>( - configSchema as ZodType, - mappedConfig - ); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - configInputParameter: string | number - ) => { - const inputParameter = - typeof configInputParameter === 'number' - ? configInputParameter - : getParameterFromArithmeticExpression(configInputParameter); - const evaluatedInput = evaluateInput(input); +import {validate} from '../../../common/util/validations'; +export const Exponent = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'input-parameter': z.string().min(1), + exponent: z.number(), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const inputParameter = config['input-parameter']; const inputData = { [inputParameter]: typeof inputParameter === 'number' ? inputParameter - : evaluatedInput[inputParameter], + : input[inputParameter], }; const validationSchema = z.record(z.string(), z.number()); return validate(validationSchema, inputData); - }; - - /** - * Calculate the input param raised by to the power of the given exponent. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeConfig = validateConfig(); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const { 'input-parameter': inputParameter, exponent, 'output-parameter': outputParameter, - } = safeConfig; + } = config; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameter); - const evaluatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: ['input-parameter', 'exponent'], - }); - const calculatedResult = calculateExponent( - safeInput, - evaluatedConfig['input-parameter'] || inputParameter, - evaluatedConfig.exponent || exponent + input, + inputParameter, + exponent ); - const result = { + return { ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), + [outputParameter]: calculatedResult, }; - - return mapOutputIfNeeded(result, mapping); }); - }; - - /** - * Calculates the input param raised by the power of a given exponent. - */ - const calculateExponent = ( - input: PluginParams, - inputParameter: string | number, - exponent: number - ) => { - const base = - typeof inputParameter === 'number' - ? inputParameter - : input[inputParameter]; - - return Math.pow(base, exponent); - }; - - return { - metadata, - execute, - }; + }, + allowArithmeticExpressions: ['input-parameter', 'exponent'], +}); + +/** + * Calculates the input param raised by the power of a given exponent. + */ +const calculateExponent = ( + input: PluginParams, + inputParameter: string | number, + exponent: number +) => { + const base = + typeof inputParameter === 'number' ? inputParameter : input[inputParameter]; + + return Math.pow(base, exponent); }; diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 468c9d980..f78878fab 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -1,186 +1,27 @@ import Spline from 'typescript-cubic-spline'; import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, - getParameterFromArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - Method, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; + +import {PluginParams, ConfigParams, Method} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {ConfigError} = ERRORS; -const {MISSING_CONFIG, X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE} = - STRINGS; - -export const Interpolation = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Executes the energy consumption calculation for an array of input parameters. - */ - const execute = (inputs: PluginParams[]) => { - const validatedConfig = validateConfig(); - const {'output-parameter': outputParameter} = validatedConfig; - - return inputs.map((input, index) => { - const calculatedConfig = evaluateConfig({ - config: validatedConfig, - input, - parametersToEvaluate: ['input-parameter'], - }); - const safeInput = validateInput(input, index); - - const calculatedResult = calculateResult(calculatedConfig, safeInput); - - const result = { - ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), - }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Calculates the appropriate interpolation value based on the specified method type in the config and input parameters. - */ - const calculateResult = (config: ConfigParams, input: PluginParams) => { - const methodType: {[key: string]: number} = { - linear: getLinearInterpolation(config, input), - spline: getSplineInterpolation(config, input), - polynomial: getPolynomialInterpolation(config, input), - }; - - return methodType[config.method]; - }; - - /** - * Calculates the interpolation when the method is linear. - */ - const getLinearInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = - typeof config['input-parameter'] === 'number' - ? config['input-parameter'] - : input[config['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - - const result = xPoints.reduce( - (acc, xPoint, i) => { - if (parameter === xPoint) { - acc.baseCpu = xPoint; - acc.baseRate = yPoints[i]; - } else if (parameter > xPoint && parameter < xPoints[i + 1]) { - acc.baseCpu = xPoint; - acc.baseRate = yPoints[i]; - acc.ratio = (yPoints[i + 1] - yPoints[i]) / (xPoints[i + 1] - xPoint); - } - - return acc; - }, - {baseRate: 0, baseCpu: 0, ratio: 0} - ); - - return result.baseRate + (parameter - result.baseCpu) * result.ratio; - }; - - /** - * Calculates the interpolation when the method is spline. - */ - const getSplineInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = - typeof config['input-parameter'] === 'number' - ? config['input-parameter'] - : input[config['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - const spline: any = new Spline(xPoints, yPoints); - - return spline.at(parameter); - }; - - /** - * Calculates the interpolation when the method is polynomial. - */ - const getPolynomialInterpolation = ( - config: ConfigParams, - input: PluginParams - ) => { - const parameter = - typeof config['input-parameter'] === 'number' - ? config['input-parameter'] - : input[config['input-parameter']]; - const xPoints: number[] = config.x; - const yPoints: number[] = config.y; - - const result = xPoints.reduce((acc, x, i) => { - const term = - yPoints[i] * - xPoints.reduce((prod, xPoint, j) => { - if (j !== i) { - return (prod * (parameter - xPoint)) / (x - xPoint); - } - return prod; - }, 1); - return acc + term; - }, 0); - - return result; - }; - - /** - * Validates config parameters. - * Sorts elements of `x` and `y`. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - config = mapConfigIfNeeded(config, mapping); +const {X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE} = STRINGS; +export const Interpolation = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: (config: ConfigParams) => { const schema = z .object({ method: z.nativeEnum(Method), x: z.array(z.number()), y: z.array(z.number()), - 'input-parameter': z - .string() - .refine(param => - validateArithmeticExpression('input-parameter', param) - ), + 'input-parameter': z.string(), 'output-parameter': z.string(), }) .refine(data => data.x && data.y && data.x.length === data.y.length, { @@ -197,20 +38,9 @@ export const Interpolation = ( }); return validate>(schema, updatedConfig); - }; - - const sortPoints = (items: number[]) => - items.sort((a: number, b: number) => { - return a - b; - }); - - /** - * Validates inputes parameters. - */ - const validateInput = (input: PluginParams, index: number) => { - const inputParameter = getParameterFromArithmeticExpression( - config['input-parameter'] - ); + }, + inputValidation: async (input: PluginParams, config: ConfigParams = {}) => { + const inputParameter = config['input-parameter']; const schema = z .object({ @@ -227,12 +57,111 @@ export const Interpolation = ( } ); - const evaluatedInput = evaluateInput(input); - return validate>(schema, evaluatedInput, index); - }; + return validate>(schema, input); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + const {'output-parameter': outputParameter} = config; + + return inputs.map(input => { + const calculatedResult = calculateResult(config, input); - return { - metadata, - execute, + return { + ...input, + [outputParameter]: calculatedResult, + }; + }); + }, + allowArithmeticExpressions: ['input-parameter'], +}); + +/** + * Calculates the appropriate interpolation value based on the specified method type in the config and input parameters. + */ +const calculateResult = (config: ConfigParams, input: PluginParams) => { + const methodType: {[key: string]: number} = { + linear: getLinearInterpolation(config, input), + spline: getSplineInterpolation(config, input), + polynomial: getPolynomialInterpolation(config, input), }; + + return methodType[config.method]; +}; + +/** + * Calculates the interpolation when the method is linear. + */ +const getLinearInterpolation = (config: ConfigParams, input: PluginParams) => { + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + + const result = xPoints.reduce( + (acc, xPoint, i) => { + if (parameter === xPoint) { + acc.baseCpu = xPoint; + acc.baseRate = yPoints[i]; + } else if (parameter > xPoint && parameter < xPoints[i + 1]) { + acc.baseCpu = xPoint; + acc.baseRate = yPoints[i]; + acc.ratio = (yPoints[i + 1] - yPoints[i]) / (xPoints[i + 1] - xPoint); + } + + return acc; + }, + {baseRate: 0, baseCpu: 0, ratio: 0} + ); + + return result.baseRate + (parameter - result.baseCpu) * result.ratio; }; + +/** + * Calculates the interpolation when the method is spline. + */ +const getSplineInterpolation = (config: ConfigParams, input: PluginParams) => { + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + const spline: any = new Spline(xPoints, yPoints); + + return spline.at(parameter); +}; + +/** + * Calculates the interpolation when the method is polynomial. + */ +const getPolynomialInterpolation = ( + config: ConfigParams, + input: PluginParams +) => { + const parameter = + typeof config['input-parameter'] === 'number' + ? config['input-parameter'] + : input[config['input-parameter']]; + const xPoints: number[] = config.x; + const yPoints: number[] = config.y; + + const result = xPoints.reduce((acc, x, i) => { + const term = + yPoints[i] * + xPoints.reduce((prod, xPoint, j) => { + if (j !== i) { + return (prod * (parameter - xPoint)) / (x - xPoint); + } + return prod; + }, 1); + return acc + term; + }, 0); + + return result; +}; + +const sortPoints = (items: number[]) => + items.sort((a: number, b: number) => { + return a - b; + }); diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index 1aa72d303..767a2c722 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -1,86 +1,26 @@ import {DateTime, Duration} from 'luxon'; import {z} from 'zod'; -import {ERRORS} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; + +import {PluginFactory} from '@grnsft/if-core/interfaces'; import { - ExecutePlugin, PluginParams, ConfigParams, ObservationParams, - PluginParametersMetadata, - MappingParams, } from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; -import {STRINGS} from '../../config'; - import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -export const MockObservations = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Generate sets of mocked observations based on config. - */ - const execute = (inputs: PluginParams[]) => { - const {duration, timeBuckets, components, generators} = - generateParamsFromConfig(); - const generatorToHistory = new Map(); - - generators.forEach(generator => { - generatorToHistory.set(generator, []); - }); - - const defaults = inputs && inputs[0]; - - const result = 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 result.map(output => mapOutputIfNeeded(output, mapping)); - }; - - /** - * Validates config parameters. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - +export const MockObservations = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: (config: ConfigParams) => { const schema = z.object({ 'timestamp-from': z.string(), 'timestamp-to': z.string(), @@ -92,117 +32,137 @@ export const MockObservations = ( }), }); - return validate>(schema, mappedConfig); - }; - - /** - * Configures the MockObservations Plugin for IF - */ - const generateParamsFromConfig = () => { - const { - 'timestamp-from': timestampFrom, - 'timestamp-to': timestampTo, - duration, - generators, - components, - } = validateConfig(); + return validate>(schema, config); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + const {duration, timeBuckets, components, generators} = + generateParamsFromConfig(config); + const generatorToHistory = new Map(); - const convertedTimestampFrom = DateTime.fromISO(timestampFrom, { - zone: 'UTC', + generators.forEach(generator => { + generatorToHistory.set(generator, []); }); - const convertedTimestampTo = DateTime.fromISO(timestampTo, {zone: 'UTC'}); - return { - duration, - timeBuckets: createTimeBuckets( - convertedTimestampFrom, - convertedTimestampTo, - duration - ), - generators: createGenerators(generators), - components, - }; - }; + const defaults = inputs && inputs[0]; - /* - * create time buckets based on start time, end time and duration of each bucket. - */ - const createTimeBuckets = ( - timestampFrom: DateTime, - timestampTo: DateTime, - duration: number, - timeBuckets: DateTime[] = [] - ): DateTime[] => { - if ( - timestampFrom < timestampTo || - timestampFrom.plus(Duration.fromObject({seconds: duration})) < timestampTo - ) { - return createTimeBuckets( - timestampFrom.plus(Duration.fromObject({seconds: duration})), - timestampTo, - duration, - [...timeBuckets, timestampFrom] - ); - } - return timeBuckets; - }; + return Object.entries(components).reduce((acc: PluginParams[], item) => { + const component: any = item[1]; + timeBuckets.forEach(timeBucket => { + const observation = createObservation( + {duration, component, timeBucket, generators}, + generatorToHistory + ); + + acc.push(Object.assign({}, defaults, observation)); + }); + + return acc; + }, []); + }, +}); + +/** + * Configures the MockObservations Plugin for IF + */ +const generateParamsFromConfig = (config: ConfigParams) => { + const { + 'timestamp-from': timestampFrom, + 'timestamp-to': timestampTo, + duration, + generators, + components, + } = config; + + const convertedTimestampFrom = DateTime.fromISO(timestampFrom, { + zone: 'UTC', + }); + const convertedTimestampTo = DateTime.fromISO(timestampTo, {zone: 'UTC'}); - /* - * create generators based on a given config - */ - const createGenerators = (generatorsConfig: object): Generator[] => { - const createCommonGenerator = (config: any): Generator[] => [ - CommonGenerator(config), - ]; - - const createRandIntGenerators = (config: any): Generator[] => - Object.entries(config).map(([fieldToPopulate, value]) => - RandIntGenerator(fieldToPopulate, value as Record) - ); - - return Object.entries(generatorsConfig).flatMap(([key, value]) => - key === 'randint' - ? createRandIntGenerators(value).flat() - : createCommonGenerator(value) - ); + return { + duration, + timeBuckets: createTimeBuckets( + convertedTimestampFrom, + convertedTimestampTo, + duration + ), + generators: createGenerators(generators), + components, }; +}; - /* - * Creates time buckets based on start time, end time and duration of each bucket. - */ - const createObservation = ( - observationParams: ObservationParams, - generatorToHistory: Map - ): PluginParams => { - const {duration, component, timeBucket, generators} = observationParams; - const timestamp = timeBucket.toISO(); - - const generateObservation = (generator: Generator) => { - const history = generatorToHistory.get(generator) || []; - const generated: Record = generator.next(history); - - generatorToHistory.set(generator, [...history, generated.value]); - - return generated; - }; - - const generateObservations = (gen: Generator) => generateObservation(gen); - const generatedValues = generators.map(generateObservations); - const initialObservation: PluginParams = { - timestamp, +/* + * Creates time buckets based on start time, end time and duration of each bucket. + */ +const createTimeBuckets = ( + timestampFrom: DateTime, + timestampTo: DateTime, + duration: number, + timeBuckets: DateTime[] = [] +): DateTime[] => { + if ( + timestampFrom < timestampTo || + timestampFrom.plus(Duration.fromObject({seconds: duration})) < timestampTo + ) { + return createTimeBuckets( + timestampFrom.plus(Duration.fromObject({seconds: duration})), + timestampTo, duration, - ...component, - }; - const generatedObservation = generatedValues.reduce( - (observation, generated) => Object.assign(observation, generated), - initialObservation + [...timeBuckets, timestampFrom] + ); + } + return timeBuckets; +}; + +/* + * Creates generators based on a given config + */ +const createGenerators = (generatorsConfig: object): Generator[] => { + const createCommonGenerator = (config: any): Generator[] => [ + CommonGenerator(config), + ]; + + const createRandIntGenerators = (config: any): Generator[] => + Object.entries(config).map(([fieldToPopulate, value]) => + RandIntGenerator(fieldToPopulate, value as Record) ); - return generatedObservation as PluginParams; + return Object.entries(generatorsConfig).flatMap(([key, value]) => + key === 'randint' + ? createRandIntGenerators(value).flat() + : createCommonGenerator(value) + ); +}; + +/* + * Creates time buckets based on start time, end time and duration of each bucket. + */ +const createObservation = ( + observationParams: ObservationParams, + generatorToHistory: Map +): PluginParams => { + const {duration, component, timeBucket, generators} = observationParams; + const timestamp = timeBucket.toISO(); + + const generateObservation = (generator: Generator) => { + const history = generatorToHistory.get(generator) || []; + const generated: Record = generator.next(history); + + generatorToHistory.set(generator, [...history, generated.value]); + + return generated; }; - return { - metadata, - execute, + const generateObservations = (gen: Generator) => generateObservation(gen); + const generatedValues = generators.map(generateObservations); + const initialObservation: PluginParams = { + timestamp, + duration, + ...component, }; + const generatedObservation = generatedValues.reduce( + (observation, generated) => Object.assign(observation, generated), + initialObservation + ); + + return generatedObservation as PluginParams; }; diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index a701f9b4e..ae3c78ade 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -1,75 +1,25 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateArithmeticOutput, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - MultiplyConfig, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; -import {validate} from '../../../common/util/validations'; - -import {STRINGS} from '../../config'; - -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -export const Multiply = ( - config: MultiplyConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z - .string() - .min(1) - .refine(param => - validateArithmeticExpression('output-parameter', param) - ), - }); +import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; - return validate>(configSchema, mappedConfig); - }; +import {validate} from '../../../common/util/validations'; - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const evaluatedInput = evaluateInput(input); +export const Multiply = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const inputParameters = config['input-parameters']; const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = evaluatedInput[param]; + (acc: {[x: string]: any}, param: string | number) => { + acc[param] = input[param]; return acc; }, @@ -79,43 +29,30 @@ export const Multiply = ( const validationSchema = z.record(z.string(), z.number()); return validate(validationSchema, inputData); - }; - - /** - * Calculate the product of each input parameter. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeConfig = validateConfig(); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, - } = safeConfig; + } = config; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); - const calculatedResult = calculateProduct(safeInput, inputParameters); + const calculatedResult = calculateProduct(input, inputParameters); - const result = { + return { ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), + [outputParameter]: calculatedResult, }; - - return mapOutputIfNeeded(result, mapping); }); - }; - - /** - * Calculates the product of the components. - */ - const calculateProduct = (input: PluginParams, inputParameters: string[]) => - inputParameters.reduce( - (accumulator, metricToMultiply) => accumulator * input[metricToMultiply], - 1 - ); - - return { - metadata, - execute, - }; -}; + }, + allowArithmeticExpressions: [], +}); + +/** + * Calculates the product of the components. + */ +const calculateProduct = (input: PluginParams, inputParameters: string[]) => + inputParameters.reduce( + (accumulator, metricToMultiply) => accumulator * input[metricToMultiply], + 1 + ); diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 8d4524641..28fa1ec99 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -1,76 +1,25 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - MappingParams, - PluginParametersMetadata, - PluginParams, - SubtractConfig, -} from '@grnsft/if-core/types'; -import {validate} from '../../../common/util/validations'; - -import {STRINGS} from '../../config'; - -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -export const Subtract = ( - config: SubtractConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z - .string() - .min(1) - .refine(value => - validateArithmeticExpression('output-parameter', value) - ), - }); +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; - return validate>(configSchema, mappedConfig); - }; +import {validate} from '../../../common/util/validations'; - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const evaluatedInput = evaluateInput(input); +export const Subtract = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const inputParameters = config['input-parameters']; const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = evaluatedInput[param]; + (acc: {[x: string]: any}, param: string | number) => { + acc[param] = input[param]; return acc; }, @@ -80,58 +29,33 @@ export const Subtract = ( const validationSchema = z.record(z.string(), z.number()); return validate(validationSchema, inputData); - }; - - /** - * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const safeConfig = validateConfig(); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, - } = safeConfig; + } = config; return inputs.map(input => { - const calculatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: safeConfig['input-parameters'], - }); - const safeInput = Object.assign( - {}, - input, - validateSingleInput(input, inputParameters) - ); - const calculatedResult = calculateDiff( - safeInput, - calculatedConfig['input-parameters'] || inputParameters - ); + const calculatedResult = calculateDiff(input, inputParameters); - const result = { + return { ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), + [outputParameter]: calculatedResult, }; - - return mapOutputIfNeeded(result, mapping); }); - }; - - /** - * Calculates the diff between the 1st item in the inputs nad the rest of the items - */ - const calculateDiff = (input: PluginParams, inputParameters: string[]) => { - const [firstItem, ...restItems] = inputParameters; - - return restItems.reduce( - (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], - input[firstItem] // Starting accumulator with the value of the first item - ); - }; - - return { - metadata, - execute, - }; + }, + allowArithmeticExpressions: [], +}); + +/** + * Calculates the diff between the 1st item in the inputs nad the rest of the items + */ +const calculateDiff = (input: PluginParams, inputParameters: string[]) => { + const [firstItem, ...restItems] = inputParameters; + + return restItems.reduce( + (accumulator, metricToSubtract) => accumulator - input[metricToSubtract], + input[firstItem] // Starting accumulator with the value of the first item + ); }; diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index 8e82458ca..ca0f6be56 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -1,123 +1,18 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, - getParameterFromArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - PluginParametersMetadata, - ConfigParams, - MappingParams, -} from '@grnsft/if-core/types'; -import {validate} from '../../../common/util/validations'; +import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; -import {STRINGS} from '../../config'; +import {validate} from '../../../common/util/validations'; import {TIME_UNITS_IN_SECONDS} from './config'; -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -export const TimeConverter = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const { - 'input-parameter': inputParameter, - 'output-parameter': outputParameter, - } = safeConfig; - - return inputs.map(input => { - const safeInput = Object.assign( - {}, - input, - validateInput(input, inputParameter) - ); - const calculatedConfig = evaluateConfig({ - config: safeConfig, - input: safeInput, - parametersToEvaluate: ['input-parameter'], - }); - - const result = { - ...input, - ...safeInput, - ...evaluateArithmeticOutput( - outputParameter, - calculateEnergy(safeInput, calculatedConfig['input-parameter']) - ), - }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Calculates the energy for given period. - */ - const calculateEnergy = ( - input: PluginParams, - inputParameter: string | number - ) => { - const originalTimeUnit = config['original-time-unit']; - const originalTimeUnitInSeoncds = TIME_UNITS_IN_SECONDS[originalTimeUnit]; - const energyPerPeriod = isNaN(Number(inputParameter)) - ? input[inputParameter] - : inputParameter; - const newTimeUnit = - config['new-time-unit'] === 'duration' - ? input.duration - : TIME_UNITS_IN_SECONDS[config['new-time-unit']]; - - const result = (energyPerPeriod / originalTimeUnitInSeoncds) * newTimeUnit; - - return Number(result.toFixed(6)); - }; - - /** - * Checks for required fields in input. - */ - const validateInput = (input: PluginParams, configInputParameter: string) => { - const inputParameter = - getParameterFromArithmeticExpression(configInputParameter); - - const schema = z.object({ - duration: z.number().gte(1), - [inputParameter]: z.number(), - }); - - const evaluatedInput = evaluateInput(input); - return validate>(schema, evaluatedInput); - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - config = mapConfigIfNeeded(config, mapping); +export const TimeConverter = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: (config: ConfigParams) => { const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); const originalTimeUnitValuesWithDuration = [ 'duration', @@ -125,25 +20,56 @@ export const TimeConverter = ( ] as const; const originalTimeUnitValues = timeUnitsValues as [string, ...string[]]; - const configSchema = z - .object({ - 'input-parameter': z.string(), - 'original-time-unit': z.enum(originalTimeUnitValues), - 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), - 'output-parameter': z.string().min(1), - }) - .refine(params => { - Object.entries(params).forEach(([param, value]) => - validateArithmeticExpression(param, value) - ); - - return true; - }); + const configSchema = z.object({ + 'input-parameter': z.string(), + 'original-time-unit': z.enum(originalTimeUnitValues), + 'new-time-unit': z.enum(originalTimeUnitValuesWithDuration), + 'output-parameter': z.string().min(1), + }); return validate>(configSchema, config); - }; - return { - metadata, - execute, - }; + }, + inputValidation: async (input: PluginParams, config: ConfigParams = {}) => { + const inputParameter = config['input-parameter']; + + const schema = z.object({ + duration: z.number().gte(1), + [inputParameter]: z.number(), + }); + + return validate>(schema, input); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + const outputParameter = config['output-parameter']; + + return inputs.map(input => ({ + ...input, + [outputParameter]: calculateEnergy(input, config), + })); + }, + allowArithmeticExpressions: ['input-parameter'], +}); + +/** + * Calculates the energy for given period. + */ +const calculateEnergy = (input: PluginParams, config: ConfigParams) => { + const { + 'original-time-unit': originalTimeUnit, + 'input-parameter': inputParameter, + 'new-time-unit': newTimeUnit, + } = config; + + const originalTimeUnitInSeoncds = TIME_UNITS_IN_SECONDS[originalTimeUnit]; + const energyPerPeriod = isNaN(Number(inputParameter)) + ? input[inputParameter] + : inputParameter; + const timeUnit = + newTimeUnit === 'duration' + ? input.duration + : TIME_UNITS_IN_SECONDS[newTimeUnit]; + + const result = (energyPerPeriod / originalTimeUnitInSeoncds) * timeUnit; + + return Number(result.toFixed(6)); }; From 4ff5d3f4177f4b5b818d39de8e949837b41c63ff Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 20 Sep 2024 20:19:16 +0400 Subject: [PATCH 786/863] test(builtins): temporary skip refcatored plugins' tests --- src/__tests__/if-run/builtins/coefficient.test.ts | 2 +- src/__tests__/if-run/builtins/copy-param.test.ts | 2 +- src/__tests__/if-run/builtins/csv-lookup.test.ts | 2 +- src/__tests__/if-run/builtins/divide.test.ts | 2 +- src/__tests__/if-run/builtins/exponent.test.ts | 2 +- src/__tests__/if-run/builtins/interpolation.test.ts | 2 +- src/__tests__/if-run/builtins/mock-observations.test.ts | 2 +- src/__tests__/if-run/builtins/multiply.test.ts | 2 +- src/__tests__/if-run/builtins/sci.test.ts | 2 +- src/__tests__/if-run/builtins/subtract.test.ts | 2 +- src/__tests__/if-run/builtins/time-converter.test.ts | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 1d6152b55..2edc40c14 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -9,7 +9,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { - describe('Coefficient: ', () => { + describe.skip('Coefficient: ', () => { const config = { 'input-parameter': 'carbon', coefficient: 3, diff --git a/src/__tests__/if-run/builtins/copy-param.test.ts b/src/__tests__/if-run/builtins/copy-param.test.ts index f7d0dea8e..d0b005b72 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -8,7 +8,7 @@ const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/copy: ', () => { - describe('Copy: ', () => { + describe.skip('Copy: ', () => { const config = { 'keep-existing': true, from: 'original', diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index 6861f9c39..29e5c99f7 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -21,7 +21,7 @@ const {MISSING_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { const mock = new AxiosMockAdapter(axios); - describe('CSVLookup: ', () => { + describe.skip('CSVLookup: ', () => { const parametersMetadata = { inputs: {}, outputs: {}, diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index f81561f9f..b6434e2e4 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -8,7 +8,7 @@ const {InputValidationError, ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { - describe('Divide: ', () => { + describe.skip('Divide: ', () => { const config = { numerator: 'vcpus-allocated', denominator: 2, diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index d90a388c5..0ea6a061a 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -8,7 +8,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -describe('builtins/exponent: ', () => { +describe.skip('builtins/exponent: ', () => { describe('Exponent: ', () => { const config = { 'input-parameter': 'energy/base', diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index b3952903e..a2250fe8d 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -9,7 +9,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG, WITHIN_THE_RANGE, ARRAY_LENGTH_NON_EMPTY, X_Y_EQUAL} = STRINGS; -describe('builtins/interpolation: ', () => { +describe.skip('builtins/interpolation: ', () => { describe('Interpolation: ', () => { const config = { method: Method.LINEAR, diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index 046a066f6..b55f2eea1 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../if-run/config'; const {InputValidationError, ConfigError} = ERRORS; const {INVALID_MIN_MAX} = STRINGS; -describe('builtins/mock-observations: ', () => { +describe.skip('builtins/mock-observations: ', () => { const parametersMetadata = { inputs: {}, outputs: {}, diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index 3d92b1d8d..7b9013dd5 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -8,7 +8,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/multiply: ', () => { - describe('Multiply: ', () => { + describe.skip('Multiply: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index bd7378495..04e8900c6 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -9,7 +9,7 @@ const {MissingInputDataError, ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/sci:', () => { - describe('Sci: ', () => { + describe.skip('Sci: ', () => { const config = {'functional-unit': 'users'}; const parametersMetadata = {inputs: {}, outputs: {}}; const sci = Sci(config, parametersMetadata, {}); diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index 8cdb7b0a1..a7f89283b 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -9,7 +9,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/subtract: ', () => { - describe('Subtract: ', () => { + describe.skip('Subtract: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index 90664c64f..6b7a190c2 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../if-run/config'; const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -describe('builtins/time-converter: ', () => { +describe.skip('builtins/time-converter: ', () => { describe('TimeConverter: ', () => { const config = { 'input-parameter': 'energy-per-year', From a9e3fec4a7b31c1635cea95b0594c0b2fd789951 Mon Sep 17 00:00:00 2001 From: manushak Date: Sat, 21 Sep 2024 09:53:23 +0400 Subject: [PATCH 787/863] feat(builtins): refactor sci-embodied plugin --- src/if-run/builtins/sci-embodied/index.ts | 326 ++++++++-------------- 1 file changed, 116 insertions(+), 210 deletions(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index a4451cc63..187ad6c43 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,98 +1,71 @@ -import {z, ZodType} from 'zod'; +import {z} from 'zod'; -import { - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapInputIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - ConfigParams, - ParameterMetadata, - MappingParams, - PluginParametersMetadata, - PluginParams, -} from '@grnsft/if-core/types'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; -import {validate} from '../../../common/util/validations'; - -export const SciEmbodied = ( - config: ConfigParams = {}, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', +export const SciEmbodied = PluginFactory({ + metadata: { inputs: { - ...({ - vCPUs: { - description: 'number of CPUs allocated to an application', - unit: 'CPUs', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + vCPUs: { + description: 'number of CPUs allocated to an application', + unit: 'CPUs', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - memory: { - description: 'RAM available for a resource, in GB', - unit: 'GB', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + memory: { + description: 'RAM available for a resource, in GB', + unit: 'GB', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - ssd: { - description: 'number of SSDs available for a resource', - unit: 'SSDs', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + ssd: { + description: 'number of SSDs available for a resource', + unit: 'SSDs', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - hdd: { - description: 'number of HDDs available for a resource', - unit: 'HDDs', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + hdd: { + description: 'number of HDDs available for a resource', + unit: 'HDDs', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - gpu: { - description: 'number of GPUs available for a resource', - unit: 'GPUs', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + gpu: { + description: 'number of GPUs available for a resource', + unit: 'GPUs', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - 'usage-ratio': { - description: - 'a scaling factor that can be used to describe the ratio of actual resource usage comapred to real device usage, e.g. 0.25 if you are using 2 out of 8 vCPUs, 0.1 if you are responsible for 1 out of 10 GB of storage, etc', - unit: 'dimensionless', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + 'usage-ratio': { + description: + 'a scaling factor that can be used to describe the ratio of actual resource usage comapred to real device usage, e.g. 0.25 if you are using 2 out of 8 vCPUs, 0.1 if you are responsible for 1 out of 10 GB of storage, etc', + unit: 'dimensionless', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - time: { - description: - 'a time unit to scale the embodied carbon by, in seconds. If not provided,time defaults to the value of the timestep duration.', - unit: 'seconds', - 'aggregation-method': { - time: 'copy', - component: 'copy', - }, + }, + time: { + description: + 'a time unit to scale the embodied carbon by, in seconds. If not provided,time defaults to the value of the timestep duration.', + unit: 'seconds', + 'aggregation-method': { + time: 'copy', + component: 'copy', }, - } as ParameterMetadata), - ...parametersMetadata?.inputs, + }, }, - outputs: parametersMetadata?.outputs || { + outputs: { 'embodied-carbon': { description: 'embodied carbon for a resource, scaled by usage', unit: 'gCO2e', @@ -102,144 +75,77 @@ export const SciEmbodied = ( }, }, }, - }; - - /** - * Checks for required fields in input. - */ - const validateConfig = (input: PluginParams) => { - const schema = z.object({ - 'baseline-vcpus': z.preprocess( - value => validateArithmeticExpression('baseline-vcpus', value), - z.number().gte(0).default(1) - ), - 'baseline-memory': z.preprocess( - value => validateArithmeticExpression('baseline-memory', value), - z.number().gte(0).default(16) - ), - 'baseline-emissions': z.preprocess( - value => validateArithmeticExpression('baseline-emissions', value), - z.number().gte(0).default(1000000) - ), - lifespan: z.preprocess( - value => validateArithmeticExpression('lifespan', value), - z.number().gt(0).default(126144000) - ), - 'vcpu-emissions-constant': z.preprocess( - value => validateArithmeticExpression('vcpu-emissions-constant', value), - z.number().gte(0).default(100000) - ), - 'memory-emissions-constant': z.preprocess( - value => - validateArithmeticExpression('memory-emissions-constant', value), - z - .number() - .gte(0) - .default(533 / 384) - ), - 'ssd-emissions-constant': z.preprocess( - value => validateArithmeticExpression('ssd-emissions-constant', value), - z.number().gte(0).default(50000) - ), - 'hdd-emissions-constant': z.preprocess( - value => validateArithmeticExpression('hdd-emissions-constant', value), - z.number().gte(0).default(100000) - ), - 'gpu-emissions-constant': z.preprocess( - value => validateArithmeticExpression('gpu-emissions-constant', value), - z.number().gte(0).default(150000) - ), - 'output-parameter': z.string().optional(), - }); - - const mappedConfig = mapConfigIfNeeded(config, mapping); - const evaluatedConfig = evaluateConfig({ - config: mappedConfig, - input, - parametersToEvaluate: Object.keys(config).filter( - key => key !== 'output-parameter' - ), - }); - - return validate>( - schema as ZodType, - evaluatedConfig - ); - }; - - /** - * Validates single observation for safe calculation. - */ - const validateInput = (input: PluginParams) => { - const schema = z.object({ - duration: z.number().gt(0), - vCPUs: z.number().gt(0).default(1), - memory: z.number().gt(0).default(16), - ssd: z.number().gte(0).default(0), - hdd: z.number().gte(0).default(0), - gpu: z.number().gte(0).default(0), - 'usage-ratio': z.number().gt(0).default(1), - time: z.number().gt(0).optional(), - }); - - const evaluatedInput = evaluateInput(input); - return validate>( - schema as ZodType, - evaluatedInput - ); - }; - - /** - * 1. Validates configuration and assigns defaults values if not provided. - * 2. Maps through observations and validates them. - * 3. Calculates total embodied carbon by substracting and the difference between baseline server and given one. - */ - const execute = (inputs: PluginParams[]) => { + }, + configValidation: z.object({ + 'baseline-vcpus': z.number().gte(0).default(1), + 'baseline-memory': z.number().gte(0).default(16), + 'baseline-emissions': z.number().gte(0).default(1000000), + lifespan: z.number().gt(0).default(126144000), + 'vcpu-emissions-constant': z.number().gte(0).default(100000), + 'memory-emissions-constant': z + .number() + .gte(0) + .default(533 / 384), + 'ssd-emissions-constant': z.number().gte(0).default(50000), + 'hdd-emissions-constant': z.number().gte(0).default(100000), + 'gpu-emissions-constant': z.number().gte(0).default(150000), + 'output-parameter': z.string().optional(), + }), + inputValidation: z.object({ + duration: z.number().gt(0), + vCPUs: z.number().gt(0).default(1), + memory: z.number().gt(0).default(16), + ssd: z.number().gte(0).default(0), + hdd: z.number().gte(0).default(0), + gpu: z.number().gte(0).default(0), + 'usage-ratio': z.number().gt(0).default(1), + time: z.number().gt(0).optional(), + }), + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + /** + * 1. Validates configuration and assigns defaults values if not provided. + * 2. Maps through observations and validates them. + * 3. Calculates total embodied carbon by substracting and the difference between baseline server and given one. + */ return inputs.map(input => { - const safeConfig = validateConfig(input); - const mappedInput = mapInputIfNeeded(input, mapping); - const safeInput = validateInput(mappedInput); - const cpuE = - (safeInput.vCPUs - safeConfig['baseline-vcpus']) * - safeConfig['vcpu-emissions-constant']; + (input.vCPUs - config['baseline-vcpus']) * + config['vcpu-emissions-constant']; const memoryE = - (safeInput.memory - safeConfig['baseline-memory']) * - ((safeConfig['memory-emissions-constant'] * - safeConfig['baseline-memory']) / + (input.memory - config['baseline-memory']) * + ((config['memory-emissions-constant'] * config['baseline-memory']) / 16) * 1000; - const hddE = safeInput.hdd * safeConfig['hdd-emissions-constant']; - const gpuE = safeInput.gpu * safeConfig['gpu-emissions-constant']; - const ssdE = safeInput.ssd * safeConfig['ssd-emissions-constant']; - const time = safeInput['time'] || safeInput.duration; + const hddE = input.hdd * config['hdd-emissions-constant']; + const gpuE = input.gpu * config['gpu-emissions-constant']; + const ssdE = input.ssd * config['ssd-emissions-constant']; + const time = input['time'] || input.duration; const totalEmbodied = - safeConfig['baseline-emissions'] + cpuE + memoryE + ssdE + hddE + gpuE; + config['baseline-emissions'] + cpuE + memoryE + ssdE + hddE + gpuE; - const totalEmbodiedScaledByUsage = - totalEmbodied * safeInput['usage-ratio']; + const totalEmbodiedScaledByUsage = totalEmbodied * input['usage-ratio']; const totalEmbodiedScaledByUsageAndTime = - totalEmbodiedScaledByUsage * (time / safeConfig['lifespan']); + totalEmbodiedScaledByUsage * (time / config['lifespan']); - const embodiedCarbonKey = - safeConfig['output-parameter'] || 'embodied-carbon'; + const embodiedCarbonKey = config['output-parameter'] || 'embodied-carbon'; - const result = { + return { ...input, - ...evaluateArithmeticOutput( - embodiedCarbonKey, - totalEmbodiedScaledByUsageAndTime - ), + [embodiedCarbonKey]: totalEmbodiedScaledByUsageAndTime, }; - - return mapOutputIfNeeded(result, mapping); }); - }; - - return { - execute, - metadata, - }; -}; + }, + allowArithmeticExpressions: [ + 'baseline-vcpus', + 'baseline-memory', + 'baseline-emissions', + 'lifespan', + 'vcpu-emissions-constant', + 'memory-emissions-constant', + 'ssd-emissions-constant', + 'hdd-emissions-constant', + 'gpu-emissions-constant', + ], +}); From f57fd977d3c2b5ff0d09a1735b1c1da6efe34615 Mon Sep 17 00:00:00 2001 From: manushak Date: Sat, 21 Sep 2024 09:54:04 +0400 Subject: [PATCH 788/863] test(builtins): temporary skip sci-embodeied tests --- src/__tests__/if-run/builtins/sci-embodied.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index e79f55dc2..cc3fc3f18 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -4,7 +4,7 @@ import {SciEmbodied} from '../../../if-run/builtins/sci-embodied'; const {InputValidationError} = ERRORS; -describe('builtins/sci-embodied:', () => { +describe.skip('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { const parametersMetadata = { inputs: {}, From 17f823bdcf5af4d39ba3dae1f29991665a34a1f5 Mon Sep 17 00:00:00 2001 From: manushak Date: Sat, 21 Sep 2024 09:57:27 +0400 Subject: [PATCH 789/863] fix(util): fix ts complainig related to unnecessary assigning pluginParameters to {} --- src/if-run/util/helpers.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts index 2939022e2..d9520b0d5 100644 --- a/src/if-run/util/helpers.ts +++ b/src/if-run/util/helpers.ts @@ -54,8 +54,10 @@ export const storeAggregationMethods = ( const plugin = pluginStorage.get(pluginName); if ('inputs' in plugin.metadata || 'outputs' in plugin.metadata) { - const pluginParameters = - {...plugin.metadata.inputs, ...plugin.metadata.outputs} || {}; + const pluginParameters = { + ...plugin.metadata.inputs, + ...plugin.metadata.outputs, + }; Object.entries(pluginParameters).forEach( ([parameterName, parameterMetadata]) => { From 621423d4b19c25d537449e1116c3fd05f79e5566 Mon Sep 17 00:00:00 2001 From: mouhamadalmounayar Date: Sat, 21 Sep 2024 20:34:33 +0200 Subject: [PATCH 790/863] refactor(builtins): add more granular error messages for invalid upsampling resolution Signed-off-by: mouhamadalmounayar --- .../if-run/builtins/time-sync.test.ts | 9 ++++---- src/if-run/builtins/time-sync/index.ts | 21 +++++++++++++------ src/if-run/config/strings.ts | 8 +++++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index dceea1728..153c44db2 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -19,7 +19,8 @@ const { } = ERRORS; const { - INVALID_UPSAMPLING_RESOLUTION, + INCOMPATIBLE_RESOLUTION_WITH_INTERVAL, + INCOMPATIBLE_RESOLUTION_WITH_GAPS, INVALID_OBSERVATION_OVERLAP, INVALID_TIME_NORMALIZATION, AVOIDING_PADDING_BY_EDGES, @@ -964,7 +965,7 @@ describe('builtins/time-sync:', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + new ConfigError(INCOMPATIBLE_RESOLUTION_WITH_INTERVAL) ); } }); @@ -989,7 +990,7 @@ describe('builtins/time-sync:', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + new ConfigError(INCOMPATIBLE_RESOLUTION_WITH_GAPS) ); } }); @@ -1017,7 +1018,7 @@ describe('builtins/time-sync:', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigError(INVALID_UPSAMPLING_RESOLUTION) + new ConfigError(INCOMPATIBLE_RESOLUTION_WITH_GAPS) ); } }); diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 329963bba..f26b62ded 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -33,7 +33,9 @@ const { } = ERRORS; const { - INVALID_UPSAMPLING_RESOLUTION, + INCOMPATIBLE_RESOLUTION_WITH_INTERVAL, + INCOMPATIBLE_RESOLUTION_WITH_GAPS, + INCOMPATIBLE_RESOLUTION_WITH_INPUTS, INVALID_TIME_NORMALIZATION, INVALID_OBSERVATION_OVERLAP, AVOIDING_PADDING_BY_EDGES, @@ -105,7 +107,8 @@ export const TimeSync = ( }; validateIntervalForResample( timeParams.interval, - timeParams.upsamplingResolution + timeParams.upsamplingResolution, + INCOMPATIBLE_RESOLUTION_WITH_INTERVAL ); const pad = checkForPadding(inputs, timeParams); validatePadding(pad, timeParams); @@ -145,7 +148,8 @@ export const TimeSync = ( validateIntervalForResample( input.duration, - timeParams.upsamplingResolution + timeParams.upsamplingResolution, + INCOMPATIBLE_RESOLUTION_WITH_INPUTS ); if (timelineGapSize > 1) { @@ -189,9 +193,13 @@ export const TimeSync = ( /** * Checks if a given duration is compatible with a given timeStep. If not, throws an error */ - const validateIntervalForResample = (duration: number, timeStep: number) => { + const validateIntervalForResample = ( + duration: number, + timeStep: number, + errorMessage: string + ) => { if (duration % timeStep !== 0) { - throw new ConfigError(INVALID_UPSAMPLING_RESOLUTION); + throw new ConfigError(errorMessage); } }; @@ -560,7 +568,8 @@ export const TimeSync = ( const array: PluginParams[] = []; validateIntervalForResample( params.endDate.diff(params.startDate).as('seconds'), - params.timeStep + params.timeStep, + INCOMPATIBLE_RESOLUTION_WITH_GAPS ); const dateRange = Interval.fromDateTimes(params.startDate, params.endDate); diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 977004dab..5f6115bf6 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -10,8 +10,12 @@ export const STRINGS = { `Provided module \`${path}\` is invalid or not found. ${error ?? ''} `, INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', - INVALID_UPSAMPLING_RESOLUTION: - 'Upsampling resolution does not adhere to all constraints', + INCOMPATIBLE_RESOLUTION_WITH_INTERVAL: + 'The upsampling resolution must be a divisor of the given interval, but the provided value does not satisfy this criteria.', + INCOMPATIBLE_RESOLUTION_WITH_INPUTS: + 'The upsampling resolution must be a divisor of all inputs durations, but the provided values do not satisfy this criteria.', + INCOMPATIBLE_RESOLUTION_WITH_GAPS: + 'The upsampling resolution must be a divisor of gaps and paddings in the time-series, but the provided values do not satisfy this criteria.', UNEXPECTED_TIME_CONFIG: 'Unexpected node-level config provided for time-sync plugin.', INVALID_TIME_INTERVAL: 'Interval is missing.', From ba6b1c82ac039964b7a88a4ab93ebcb52116d2ca Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 23 Sep 2024 10:55:20 +0400 Subject: [PATCH 791/863] feat(builtins): refactor sum plugin --- src/if-run/builtins/sum/index.ts | 155 +++++++++---------------------- 1 file changed, 42 insertions(+), 113 deletions(-) diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index e111bce41..23ed71c9d 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -1,129 +1,58 @@ import {z} from 'zod'; -import { - ERRORS, - evaluateInput, - evaluateConfig, - evaluateArithmeticOutput, - validateArithmeticExpression, -} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - SumConfig, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; -import {validate} from '../../../common/util/validations'; - -import {STRINGS} from '../../config'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; -const {ConfigError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; +import {validate} from '../../../common/util/validations'; -export const Sum = ( - config: SumConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; +export const Sum = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + const inputParameters = config['input-parameters']; + const inputData = inputParameters.reduce( + (acc: {[x: string]: any}, param: string | number) => { + acc[param] = input[param]; - /** - * Calculate the sum of each input-paramters. - */ - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); + return acc; + }, + {} as Record + ); + const validationSchema = z.record(z.string(), z.number()); + return validate(validationSchema, inputData); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, - } = safeConfig; + } = config; return inputs.map(input => { - const safeInput = validateSingleInput(input, inputParameters); - - const calculatedConfig = evaluateConfig({ - config: safeConfig, - input, - parametersToEvaluate: config['input-parameters'], - }); - const calculatedResult = calculateSum( - safeInput, - calculatedConfig['input-parameters'] || inputParameters + input, + config['input-parameters'] || inputParameters ); - const result = { + return { ...input, - ...safeInput, - ...evaluateArithmeticOutput(outputParameter, calculatedResult), + [outputParameter]: calculatedResult, }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { - throw new ConfigError(MISSING_CONFIG); - } - - const mappedConfig = mapConfigIfNeeded(config, mapping); - - const configSchema = z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z - .string() - .min(1) - .refine(value => - validateArithmeticExpression('output-parameter', value) - ), }); - - return validate>(configSchema, mappedConfig); - }; - - /** - * Checks for required fields in input. - */ - const validateSingleInput = ( - input: PluginParams, - inputParameters: string[] - ) => { - const evaluatedInput = evaluateInput(input); - const inputData = inputParameters.reduce( - (acc, param) => { - acc[param] = evaluatedInput[param]; - - return acc; - }, - {} as Record - ); - const validationSchema = z.record(z.string(), z.number()); - return validate(validationSchema, inputData); - }; - - /** - * Calculates the sum of the energy components. - */ - const calculateSum = (input: PluginParams, inputParameters: string[]) => - inputParameters.reduce( - (accumulator, metricToSum) => accumulator + input[metricToSum], - 0 - ); - - return { - metadata, - execute, - }; -}; + }, + allowArithmeticExpressions: [], +}); + +/** + * Calculates the sum of the energy components. + */ +const calculateSum = (input: PluginParams, inputParameters: string[]) => + inputParameters.reduce( + (accumulator, metricToSum) => accumulator + input[metricToSum], + 0 + ); From c0f55729eb3d2828f0b4b23682c6aa65f0c42585 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 23 Sep 2024 10:56:52 +0400 Subject: [PATCH 792/863] test(builtins): temporary skip sum plugin tests --- src/__tests__/if-run/builtins/sum.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 1d0e928f2..4df283366 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../if-run/config'; const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -describe('builtins/sum: ', () => { +describe.skip('builtins/sum: ', () => { describe('Sum: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], From 8bff08573caaca3ec602cbd864025e25d2d7d785 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 25 Sep 2024 12:53:55 +0400 Subject: [PATCH 793/863] fix(builtins): fix plugins config validation issue --- src/if-run/builtins/coefficient/index.ts | 34 ++++++++++---- src/if-run/builtins/copy-param/index.ts | 47 ++++++++++++++----- src/if-run/builtins/csv-lookup/index.ts | 38 ++++++++++----- src/if-run/builtins/divide/index.ts | 31 +++++++----- src/if-run/builtins/exponent/index.ts | 34 +++++++++++--- src/if-run/builtins/interpolation/index.ts | 18 +++++-- .../builtins/mock-observations/index.ts | 10 ++++ src/if-run/builtins/multiply/index.ts | 24 ++++++++-- src/if-run/builtins/sci/index.ts | 7 ++- src/if-run/builtins/subtract/index.ts | 24 ++++++++-- src/if-run/builtins/sum/index.ts | 7 +-- src/if-run/builtins/time-converter/index.ts | 12 ++++- 12 files changed, 216 insertions(+), 70 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 1383e6d66..eb62c07f2 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,19 +1,37 @@ -import {z} from 'zod'; -import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {z, ZodType} from 'zod'; + import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Coefficient = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, - configValidation: z.object({ - coefficient: z.number(), - 'input-parameter': z.string().min(1), - 'output-parameter': z.string().min(1), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + coefficient: z.number(), + 'input-parameter': z.string().min(1), + 'output-parameter': z.string().min(1), + }); + + return validate>( + configSchema as ZodType, + config + ); + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const inputData = { 'input-parameter': input[config['input-parameter']], @@ -23,7 +41,7 @@ export const Coefficient = PluginFactory({ return input; }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const { 'input-parameter': inputParameter, 'output-parameter': outputParameter, diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index 17af2568f..bdf777f0a 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -1,9 +1,19 @@ import {z} from 'zod'; -import {PluginFactory} from '@grnsft/if-core/interfaces'; + +import { + ERRORS, + getParameterFromArithmeticExpression, +} from '@grnsft/if-core/utils'; import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + /** * 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) @@ -15,11 +25,26 @@ export const Copy = PluginFactory({ inputs: {}, outputs: {}, }, - configValidation: z.object({ - 'keep-existing': z.boolean(), - from: z.string().min(1).or(z.number()), - to: z.string().min(1), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + 'keep-existing': z.boolean(), + from: z.string().min(1), + to: z.string().min(1), + }); + + const extractedFrom = getParameterFromArithmeticExpression(config.from); + const updatedConfig = config['keep-existing'] + ? config + : {...config, 'pure-from': extractedFrom}; + + validate>(configSchema, updatedConfig); + + return updatedConfig; + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const from = config.from; const inputData = { @@ -29,18 +54,16 @@ export const Copy = PluginFactory({ return validate(validationSchema, inputData); }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const keepExisting = config['keep-existing'] === true; const from = config['from']; const to = config['to']; return inputs.map(input => { - const outputValue = !isNaN(config?.from) ? config.from : input[from]; + const outputValue = !isNaN(from) ? from : input[from]; - if (input[from]) { - if (!keepExisting) { - delete input[from]; - } + if (input[from] || (!isNaN(from) && !keepExisting)) { + delete input[config['pure-from']]; } return { diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index 8fb1e5535..d11bac467 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -6,18 +6,24 @@ import {parse} from 'csv-parse/sync'; import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; -import {ERRORS} from '@grnsft/if-core/utils'; +import {ERRORS, validate} from '@grnsft/if-core/utils'; import {STRINGS} from '../../config'; -const {FILE_FETCH_FAILED, FILE_READ_FAILED, MISSING_CSV_COLUMN, NO_QUERY_DATA} = - STRINGS; +const { + FILE_FETCH_FAILED, + FILE_READ_FAILED, + MISSING_CSV_COLUMN, + MISSING_CONFIG, + NO_QUERY_DATA, +} = STRINGS; const { FetchingFileError, ReadFileError, MissingCSVColumnError, QueryDataNotFoundError, + ConfigError, CSVParseError, } = ERRORS; @@ -26,15 +32,23 @@ export const CSVLookup = PluginFactory({ inputs: {}, outputs: {}, }, - configValidation: z.object({ - filepath: z.string(), - query: z.record(z.string(), z.string()), - output: z - .string() - .or(z.array(z.string())) - .or(z.array(z.array(z.string()))), - }), - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + filepath: z.string(), + query: z.record(z.string(), z.string()), + output: z + .string() + .or(z.array(z.string())) + .or(z.array(z.array(z.string()))), + }); + + return validate>(configSchema, config); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { /** * 1. Tries to retrieve given file (with url or local path). * 2. Parses given CSV. diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index d211ff05c..343033d9b 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -1,25 +1,34 @@ import {z} from 'zod'; -import {PluginFactory} from '@grnsft/if-core/interfaces'; + import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; -import {ERRORS} from '@grnsft/if-core/utils'; - import {STRINGS} from '../../config'; -const {MissingInputDataError} = ERRORS; -const {MISSING_INPUT_DATA, ZERO_DIVISION} = STRINGS; +const {MissingInputDataError, ConfigError} = ERRORS; +const {MISSING_INPUT_DATA, ZERO_DIVISION, MISSING_CONFIG} = STRINGS; + export const Divide = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, - configValidation: z.object({ - numerator: z.string().min(1), - denominator: z.string().or(z.number()), - output: z.string(), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const schema = z.object({ + numerator: z.string().min(1), + denominator: z.string().or(z.number()), + output: z.string(), + }); + + return validate>(schema, config); + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const {numerator, denominator} = config; @@ -38,7 +47,7 @@ export const Divide = PluginFactory({ return validate>(schema, input); }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const {numerator, denominator, output} = config; return inputs.map((input, index) => { diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index c401e33dc..7f2758f98 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -1,20 +1,37 @@ -import {z} from 'zod'; +import {z, ZodType} from 'zod'; import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Exponent = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, - configValidation: z.object({ - 'input-parameter': z.string().min(1), - exponent: z.number(), - 'output-parameter': z.string().min(1), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + 'input-parameter': z.string().min(1), + exponent: z.number(), + 'output-parameter': z.string().min(1), + }); + + return validate>( + configSchema as ZodType, + config + ); + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const inputParameter = config['input-parameter']; const inputData = { @@ -25,7 +42,10 @@ export const Exponent = PluginFactory({ }; const validationSchema = z.record(z.string(), z.number()); - return validate(validationSchema, inputData); + return validate>( + validationSchema, + inputData + ); }, implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { const { diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index f78878fab..b0e1886a1 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -3,12 +3,16 @@ import {z} from 'zod'; import {PluginParams, ConfigParams, Method} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE} = STRINGS; +const {X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE, MISSING_CONFIG} = + STRINGS; + +const {ConfigError} = ERRORS; export const Interpolation = PluginFactory({ metadata: { @@ -16,6 +20,10 @@ export const Interpolation = PluginFactory({ outputs: {}, }, configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z .object({ method: z.nativeEnum(Method), @@ -39,7 +47,11 @@ export const Interpolation = PluginFactory({ return validate>(schema, updatedConfig); }, - inputValidation: async (input: PluginParams, config: ConfigParams = {}) => { + inputValidation: ( + input: PluginParams, + config: ConfigParams, + index: number | undefined + ) => { const inputParameter = config['input-parameter']; const schema = z @@ -57,7 +69,7 @@ export const Interpolation = PluginFactory({ } ); - return validate>(schema, input); + return validate>(schema, input, index); }, implementation: async (inputs: PluginParams[], config: ConfigParams) => { const {'output-parameter': outputParameter} = config; diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index 767a2c722..b58b75e73 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -7,20 +7,30 @@ import { ConfigParams, ObservationParams, } from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + import {CommonGenerator} from './helpers/common-generator'; import {RandIntGenerator} from './helpers/rand-int-generator'; import {Generator} from './interfaces/index'; +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const MockObservations = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z.object({ 'timestamp-from': z.string(), 'timestamp-to': z.string(), diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index ae3c78ade..16b6f21d8 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -2,18 +2,32 @@ import {z} from 'zod'; import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Multiply = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, - configValidation: z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }); + + return validate>(configSchema, config); + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const inputParameters = config['input-parameters']; @@ -30,7 +44,7 @@ export const Multiply = PluginFactory({ return validate(validationSchema, inputData); }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, diff --git a/src/if-run/builtins/sci/index.ts b/src/if-run/builtins/sci/index.ts index 852faf2dc..4238878dd 100644 --- a/src/if-run/builtins/sci/index.ts +++ b/src/if-run/builtins/sci/index.ts @@ -11,12 +11,13 @@ import {allDefined} from '../../../common/util/validations'; import {STRINGS} from '../../config'; -const {MissingInputDataError} = ERRORS; +const {MissingInputDataError, ConfigError} = ERRORS; const { MISSING_FUNCTIONAL_UNIT_CONFIG, MISSING_FUNCTIONAL_UNIT_INPUT, SCI_MISSING_FN_UNIT, ZERO_DIVISION, + MISSING_CONFIG, } = STRINGS; export const Sci = PluginFactory({ @@ -52,6 +53,10 @@ export const Sci = PluginFactory({ }, }, configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + const schema = z .object({ 'functional-unit': z.string(), diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 28fa1ec99..41a42f934 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -2,18 +2,32 @@ import {z} from 'zod'; import {PluginFactory} from '@grnsft/if-core/interfaces'; import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const Subtract = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, - configValidation: z.object({ - 'input-parameters': z.array(z.string()), - 'output-parameter': z.string().min(1), - }), + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + + const configSchema = z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }); + + return validate>(configSchema, config); + }, inputValidation: (input: PluginParams, config: ConfigParams) => { const inputParameters = config['input-parameters']; @@ -30,7 +44,7 @@ export const Subtract = PluginFactory({ return validate(validationSchema, inputData); }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index 23ed71c9d..fabeb890b 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -27,17 +27,14 @@ export const Sum = PluginFactory({ const validationSchema = z.record(z.string(), z.number()); return validate(validationSchema, inputData); }, - implementation: async (inputs: PluginParams[], config: ConfigParams = {}) => { + implementation: async (inputs: PluginParams[], config: ConfigParams) => { const { 'input-parameters': inputParameters, 'output-parameter': outputParameter, } = config; return inputs.map(input => { - const calculatedResult = calculateSum( - input, - config['input-parameters'] || inputParameters - ); + const calculatedResult = calculateSum(input, inputParameters); return { ...input, diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index ca0f6be56..dc6a84d7d 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -2,17 +2,27 @@ import {z} from 'zod'; import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; +import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; import {TIME_UNITS_IN_SECONDS} from './config'; +import {STRINGS} from '../../config'; + +const {ConfigError} = ERRORS; +const {MISSING_CONFIG} = STRINGS; + export const TimeConverter = PluginFactory({ metadata: { inputs: {}, outputs: {}, }, configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); + } + const timeUnitsValues = Object.keys(TIME_UNITS_IN_SECONDS); const originalTimeUnitValuesWithDuration = [ 'duration', @@ -29,7 +39,7 @@ export const TimeConverter = PluginFactory({ return validate>(configSchema, config); }, - inputValidation: async (input: PluginParams, config: ConfigParams = {}) => { + inputValidation: (input: PluginParams, config: ConfigParams) => { const inputParameter = config['input-parameter']; const schema = z.object({ From 2f8eaec0f05ae6346b12631c3392e04381509fc0 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 25 Sep 2024 12:55:55 +0400 Subject: [PATCH 794/863] docs(builtins): update readme files of plugins --- src/if-run/builtins/coefficient/README.md | 7 ++++--- src/if-run/builtins/copy-param/README.md | 8 +++++--- src/if-run/builtins/csv-lookup/README.md | 10 ++++++---- src/if-run/builtins/divide/README.md | 10 ++++++---- src/if-run/builtins/exponent/README.md | 8 +++++--- src/if-run/builtins/interpolation/README.md | 10 ++++++---- src/if-run/builtins/mock-observations/README.md | 6 ++++-- src/if-run/builtins/multiply/README.md | 6 ++++-- src/if-run/builtins/regex/README.md | 10 +++++++--- src/if-run/builtins/sci/README.md | 12 ++++++++---- src/if-run/builtins/shell/README.md | 6 ++++-- src/if-run/builtins/subtract/README.md | 8 +++++--- src/if-run/builtins/sum/README.md | 8 +++++--- 13 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/if-run/builtins/coefficient/README.md b/src/if-run/builtins/coefficient/README.md index 3d19dc4a1..2b82fa78c 100644 --- a/src/if-run/builtins/coefficient/README.md +++ b/src/if-run/builtins/coefficient/README.md @@ -27,13 +27,14 @@ of the parameters of the inputs and outputs - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe parameters of the `output-parameter` of the config. Each parameter has: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. ### Mapping @@ -75,7 +76,7 @@ const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; const coeff = Coefficient(config, parametersMetadata, mapping); -const result = coeff.execute([ +const result = await coeff.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', diff --git a/src/if-run/builtins/copy-param/README.md b/src/if-run/builtins/copy-param/README.md index 224c21703..a13b0915b 100644 --- a/src/if-run/builtins/copy-param/README.md +++ b/src/if-run/builtins/copy-param/README.md @@ -49,13 +49,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameters of the `to` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -93,7 +95,7 @@ const mapping = {}; const plugin = Copy(config, parametersMetadata, mapping); -const result = plugin.execute([ +const result = await plugin.execute([ { timestamp: '2023-12-12T00:00:13.000Z', duration: 30, diff --git a/src/if-run/builtins/csv-lookup/README.md b/src/if-run/builtins/csv-lookup/README.md index 0e77ce0ff..d9d8c3903 100644 --- a/src/if-run/builtins/csv-lookup/README.md +++ b/src/if-run/builtins/csv-lookup/README.md @@ -63,13 +63,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameters in the `output` of the config block. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -117,7 +119,7 @@ const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; const csvLookup = CSVLookup(config, parametersMetadata, mapping); -const input = [ +const result = await csvLookup.execute([ { timestamp: '2023-08-06T00:00' duration: 3600 @@ -125,7 +127,7 @@ const input = [ 'cloud/provider': gcp 'cloud/region': asia-east }, -]; +]); ``` ## Example manifest diff --git a/src/if-run/builtins/divide/README.md b/src/if-run/builtins/divide/README.md index 1d57784a1..6d536696f 100644 --- a/src/if-run/builtins/divide/README.md +++ b/src/if-run/builtins/divide/README.md @@ -22,13 +22,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `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 - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -77,13 +79,13 @@ const mapping = { }; const divide = Divide(config, parametersMetadata, mapping); -const input = [ +const result = await divide.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, 'vcpus-allocated': 24, }, -]; +]); ``` ## Example manifest diff --git a/src/if-run/builtins/exponent/README.md b/src/if-run/builtins/exponent/README.md index d918b4dad..8306be0b4 100644 --- a/src/if-run/builtins/exponent/README.md +++ b/src/if-run/builtins/exponent/README.md @@ -26,13 +26,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. -- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes:: + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + +- `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index c7b1876f2..d328dc9aa 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -35,13 +35,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameters of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -116,9 +118,9 @@ const inputs = [ }, ]; -const results = interpolationPlugin.execute(inputs); +const result = await interpolationPlugin.execute(inputs); -console.log(results); +console.log(result); ``` ### Manifest Usage diff --git a/src/if-run/builtins/mock-observations/README.md b/src/if-run/builtins/mock-observations/README.md index da2444147..8dd8a963f 100644 --- a/src/if-run/builtins/mock-observations/README.md +++ b/src/if-run/builtins/mock-observations/README.md @@ -27,13 +27,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the output parameters. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/multiply/README.md b/src/if-run/builtins/multiply/README.md index 43d189fad..a624c7256 100644 --- a/src/if-run/builtins/multiply/README.md +++ b/src/if-run/builtins/multiply/README.md @@ -25,13 +25,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: diff --git a/src/if-run/builtins/regex/README.md b/src/if-run/builtins/regex/README.md index 246dad3dd..37d60bcd0 100644 --- a/src/if-run/builtins/regex/README.md +++ b/src/if-run/builtins/regex/README.md @@ -26,13 +26,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameters of the `output` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -67,7 +69,7 @@ const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; const regex = Regex(config, parametersMetadata, mapping); -const input = [ +const inputs = [ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -75,6 +77,8 @@ const input = [ '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', }, ]; + +const result = await regex.execute(inputs); ``` ## Example manifest diff --git a/src/if-run/builtins/sci/README.md b/src/if-run/builtins/sci/README.md index 0ccd5ff94..b628a5eb9 100644 --- a/src/if-run/builtins/sci/README.md +++ b/src/if-run/builtins/sci/README.md @@ -18,14 +18,16 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the `sci` parameter which has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -63,10 +65,12 @@ To run the plugin, you must first create an instance of `Sci`. Then, you can cal ```typescript import {Sci} from 'builtins'; + const config = {'functional-unit': 'requests'} const parametersMetadata = {inputs: {}, outputs: {}}; -const mapping = {}; -const sci = Sci(config, parametersMetadata, mapping); + +const sci = Sci(config, parametersMetadata, {}); + const results = await sci.execute( [ { diff --git a/src/if-run/builtins/shell/README.md b/src/if-run/builtins/shell/README.md index d5e51a18e..3eb98c5e6 100644 --- a/src/if-run/builtins/shell/README.md +++ b/src/if-run/builtins/shell/README.md @@ -32,13 +32,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the output parameter. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Inputs The parameters included in the `inputs` field in the `manifest` depend entirely on the plugin itself. A typical plugin might expect the following common data to be provided as `inputs`: diff --git a/src/if-run/builtins/subtract/README.md b/src/if-run/builtins/subtract/README.md index 11d2573ef..a36b4ba11 100644 --- a/src/if-run/builtins/subtract/README.md +++ b/src/if-run/builtins/subtract/README.md @@ -25,13 +25,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -72,7 +74,7 @@ const config = { const parametersMetadata = {inputs: {}, outputs: {}}; const mapping = {}; const subtract = Subtract(config, parametersMetadata, mapping); -const result = subtract subtract.execute([ +const result = await subtract.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', diff --git a/src/if-run/builtins/sum/README.md b/src/if-run/builtins/sum/README.md index 794b6bac7..f140b486e 100644 --- a/src/if-run/builtins/sum/README.md +++ b/src/if-run/builtins/sum/README.md @@ -25,13 +25,15 @@ The `parameter-metadata` section contains information about `description`, `unit - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `outputs`: describe the parameter of the `output-parameter` of the config. The parameter has the following attributes: - `description`: description of the parameter - `unit`: unit of the parameter - `aggregation-method`: aggregation method object of the parameter - `time`: this value is used for `horizontal` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. - - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + - `component`: this value is used for `vertical` aggregation. It can be of the following values: `sum`, `avg`, `copy`, or `none`. + ### Mapping 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. It also maps the output parameter of the plugin. The structure of the `mapping` block is: @@ -74,7 +76,7 @@ const = mapping { }; const sum = Sum(config, parametersMetadata, mapping); -const result = sum.execute([ +const result = await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, From 4fee1acfbdeae238afa33ba5ad3f7c2e4b98bdc1 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 25 Sep 2024 12:57:15 +0400 Subject: [PATCH 795/863] docs(builtins): update time-converter readme file --- src/if-run/builtins/time-converter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/time-converter/README.md b/src/if-run/builtins/time-converter/README.md index 199b44923..6b4ca9dc2 100644 --- a/src/if-run/builtins/time-converter/README.md +++ b/src/if-run/builtins/time-converter/README.md @@ -59,7 +59,7 @@ const config = { }; const timeConverter = TimeConverter(config, parametersMetadata); -const result = timeConverter.execute([ +const result = await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, From 3cee69c6deec41c47dc32a5d1c80e9aa1dc30a06 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 25 Sep 2024 12:57:43 +0400 Subject: [PATCH 796/863] docs(src): update migration guide --- Refactor-migration-guide.md | 119 ++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 52 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index ebdf94b20..b5608ff42 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -199,65 +199,80 @@ Details tbc... ## Plugins -The plugins themselves require some changes to keep them compatible with the refactored IF. +Plugins require some modifications to remain compatible with the refactored IF interface. -Instead of the old class-based model, plugins are now functions. They conform to the following interface: +Each plugin follows the `PluginFactory` interface, which is a higher-order function that accepts a `params` object of type `PluginFactoryParams`. This function returns another function (the inner function), which handles the plugin’s `config`, `parametersMetadata`, and `mapping`. ```ts -export type PluginInterface = { - execute: (inputs: PluginParams[]) => PluginParams[]; - metadata: { - kind: string; - }; - [key: string]: any; -}; +export const PluginFactory = + (params: PluginFactoryParams) => + ( + config: ConfigParams = {}, + parametersMetadata: PluginParametersMetadata, + mapping: MappingParams + ) => ({ + metadata: { + kind: 'execute', + inputs: {...params.metadata.inputs, ...parametersMetadata?.inputs}, + outputs: parametersMetadata?.outputs || params.metadata.outputs, + }, + execute: async (inputs: PluginParams[]) => { + // Generic plugin functionality goes here + // E.g., mapping, arithmetic operations, validation + // Process inputs and mapping logic + }); + }) ``` -The plugin still requires an execute function. This is where you implement the plugin logic. +Inner Function Parameters: + +- `config`: This is of type `ConfigParams` and has a default value of an empty object ({}). This might hold configuration settings for the plugin. +- `parametersMetadata`: A `PluginParametersMetadata` object that describes the metadata for the plugin’s parameters. +- `mapping`: A `MappingParams` object, describing parameters are mapped. -Here's a minimal example for a plugin that sums some inputs defined in config - see inline comments for some important notes: +Implementation Function: + +The plugin requires an `implementation` function, where the actual plugin logic is defined. +Here’s a minimal example of a plugin that sums inputs as defined in the config. See the inline comments for further clarification. ```ts -// Here's the function definition - notice that config is passed in here! -export const Sum = (config: SumConfig): PluginInterface => { - const inputParameters = config['input-parameters'] || []; - const outputParameter = config['output-parameter']; - - // we also return metadata now too - you can add more or just use this default - const metadata = { - kind: 'execute', - }; - - /** - * Calculate the sum of the input metrics for each timestamp. - */ - const execute = async (inputs: PluginParams[]): Promise => { - inputs.map(input => { - return calculateSum(input, inputParameters, outputParameter); +// Here's the function definition! +export const Sum = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: z.object({ + 'input-parameters': z.array(z.string()), + 'output-parameter': z.string().min(1), + }), + inputValidation: (input: PluginParams, config: ConfigParams) => { + return validate(validationSchema, inputData); + }, + implementation: async (inputs: PluginParams[], config: ConfigParams) => { + const { + 'input-parameters': inputParameters, + 'output-parameter': outputParameter, + } = config; + + return inputs.map(input => { + const calculatedResult = calculateSum(input, inputParameters); + + return { + ...input, + [outputParameter]: calculatedResult, + }; }); - return inputs; - }; - - /** - * Calculates the sum of the energy components. - */ - const calculateSum = ( - input: PluginParams, - inputParameters: string[], - outputParameter: string - ) => { - input[outputParameter] = inputParameters.reduce( - (accumulator, metricToSum) => { - return accumulator + input[metricToSum]; - }, - 0 - ); - }; - - // return the metadata and the execute function - return { - metadata, - execute, - }; -}; + }, + allowArithmeticExpressions: [], +}); + +/** + * Calculates the sum of the energy components. + */ +const calculateSum = (input: PluginParams, inputParameters: string[]) => + inputParameters.reduce( + (accumulator, metricToSum) => accumulator + input[metricToSum], + 0 + ); ``` From 577f76f6572b54cc8cba5e138ad1337ffc77153c Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 25 Sep 2024 12:59:04 +0400 Subject: [PATCH 797/863] test(builtins): update plugins' tests --- .../if-run/builtins/coefficient.test.ts | 41 +++++----- .../if-run/builtins/copy-param.test.ts | 31 ++++---- .../if-run/builtins/csv-lookup.test.ts | 2 +- src/__tests__/if-run/builtins/divide.test.ts | 10 +-- .../if-run/builtins/exponent.test.ts | 27 +++---- .../if-run/builtins/interpolation.test.ts | 77 ++++++++++++------- .../if-run/builtins/multiply.test.ts | 18 +++-- .../if-run/builtins/sci-embodied.test.ts | 8 +- src/__tests__/if-run/builtins/sci.test.ts | 14 ++-- .../if-run/builtins/subtract.test.ts | 17 ++-- src/__tests__/if-run/builtins/sum.test.ts | 49 ++++++------ .../if-run/builtins/time-converter.test.ts | 34 ++++---- 12 files changed, 172 insertions(+), 156 deletions(-) diff --git a/src/__tests__/if-run/builtins/coefficient.test.ts b/src/__tests__/if-run/builtins/coefficient.test.ts index 2edc40c14..4a3f8562f 100644 --- a/src/__tests__/if-run/builtins/coefficient.test.ts +++ b/src/__tests__/if-run/builtins/coefficient.test.ts @@ -3,13 +3,12 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Coefficient} from '../../../if-run/builtins/coefficient'; import {STRINGS} from '../../../if-run/config'; -import {CoefficientConfig} from '@grnsft/if-core/types'; const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/coefficient: ', () => { - describe.skip('Coefficient: ', () => { + describe('Coefficient: ', () => { const config = { 'input-parameter': 'carbon', coefficient: 3, @@ -29,7 +28,7 @@ describe('builtins/coefficient: ', () => { }); describe('execute(): ', () => { - it('successfully applies coefficient strategy to given input.', () => { + it('successfully applies coefficient strategy to given input.', async () => { expect.assertions(1); const expectedResult = [ @@ -41,7 +40,7 @@ describe('builtins/coefficient: ', () => { }, ]; - const result = coefficient.execute([ + const result = await coefficient.execute([ { duration: 3600, carbon: 3, @@ -54,7 +53,7 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('succcessfully executes when the mapping has data.', () => { + it('succcessfully executes when the mapping has data.', async () => { const mapping = { carbon: 'carbon-for-production', }; @@ -71,7 +70,7 @@ describe('builtins/coefficient: ', () => { }, ]; - const result = coefficient.execute([ + const result = await coefficient.execute([ { duration: 3600, 'carbon-for-production': 3, @@ -84,7 +83,7 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('succcessfully executes when the mapping map output parameter.', () => { + it('succcessfully executes when the mapping map output parameter.', async () => { const mapping = { 'carbon-product': 'carbon-result', }; @@ -101,7 +100,7 @@ describe('builtins/coefficient: ', () => { }, ]; - const result = coefficient.execute([ + const result = await coefficient.execute([ { duration: 3600, carbon: 3, @@ -114,7 +113,7 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when a parameter has an arithmetic expression.', () => { + it('successfully executes when a parameter has an arithmetic expression.', async () => { expect.assertions(1); const config = { 'input-parameter': '=3*carbon', @@ -136,7 +135,7 @@ describe('builtins/coefficient: ', () => { }, ]; - const result = coefficient.execute([ + const result = await coefficient.execute([ { duration: 3600, carbon: 3, @@ -149,7 +148,7 @@ describe('builtins/coefficient: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when the `coefficient` has wrong arithmetic expression.', () => { + it('throws an error when the `coefficient` has wrong arithmetic expression.', async () => { const config = { 'input-parameter': 'carbon', coefficient: 'mock-param', @@ -159,16 +158,12 @@ describe('builtins/coefficient: ', () => { inputs: {}, outputs: {}, }; - const coefficient = Coefficient( - config as any as CoefficientConfig, - parametersMetadata, - {} - ); + const coefficient = Coefficient(config, parametersMetadata, {}); expect.assertions(2); try { - coefficient.execute([ + await coefficient.execute([ { duration: 3600, carbon: 'some-param', @@ -185,14 +180,14 @@ describe('builtins/coefficient: ', () => { } }); - it('throws an error when config is not provided.', () => { + it('throws an error when config is not provided.', async () => { const config = undefined; const coefficient = Coefficient(config!, parametersMetadata, {}); expect.assertions(1); try { - coefficient.execute([ + await coefficient.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', @@ -204,7 +199,7 @@ describe('builtins/coefficient: ', () => { } }); - it('throws an error on missing `input-parameter` param in input.', () => { + it('throws an error on missing `input-parameter` param in input.', async () => { const invalidConfig = { 'input-parameter': '', coefficient: 3, @@ -217,7 +212,7 @@ describe('builtins/coefficient: ', () => { expect.assertions(1); try { - coefficient.execute([ + await coefficient.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', @@ -231,7 +226,7 @@ describe('builtins/coefficient: ', () => { } }); - it('throws an error on missing `output-parameter` param in input.', () => { + it('throws an error on missing `output-parameter` param in input.', async () => { const invalidConfig = { 'input-parameter': 'carbon', coefficient: 10, @@ -243,7 +238,7 @@ describe('builtins/coefficient: ', () => { expect.assertions(1); try { - coefficient.execute([ + await coefficient.execute([ { duration: 3600, 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 d0b005b72..6edfc7a17 100644 --- a/src/__tests__/if-run/builtins/copy-param.test.ts +++ b/src/__tests__/if-run/builtins/copy-param.test.ts @@ -8,7 +8,7 @@ const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/copy: ', () => { - describe.skip('Copy: ', () => { + describe('Copy: ', () => { const config = { 'keep-existing': true, from: 'original', @@ -28,7 +28,7 @@ describe('builtins/copy: ', () => { }); describe('execute(): ', () => { - it('successfully applies Copy strategy to given input.', () => { + it('successfully applies Copy strategy to given input.', async () => { expect.assertions(1); const expectedResult = [ @@ -40,7 +40,7 @@ describe('builtins/copy: ', () => { }, ]; - const result = copy.execute([ + const result = await copy.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -51,7 +51,7 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executed when `mapping` has valid data.', () => { + it('successfully executed when `mapping` has valid data.', async () => { expect.assertions(1); const mapping = { @@ -68,7 +68,7 @@ describe('builtins/copy: ', () => { }, ]; - const result = copy.execute([ + const result = await copy.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -79,7 +79,7 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executed when the `mapping` map output parameter.', () => { + it('successfully executed when the `mapping` map output parameter.', async () => { expect.assertions(1); const mapping = { @@ -96,7 +96,7 @@ describe('builtins/copy: ', () => { }, ]; - const result = copy.execute([ + const result = await copy.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -107,14 +107,14 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when config is not provided.', () => { + it('throws an error when config is not provided.', async () => { const config = undefined; const copy = Copy(config!, parametersMetadata, {}); expect.assertions(1); try { - copy.execute([ + await copy.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -126,7 +126,7 @@ describe('builtins/copy: ', () => { } }); - it('throws an error on missing params in input.', () => { + it('throws an error on missing params in input.', async () => { const config = { 'keep-existing': true, from: 'original', @@ -136,7 +136,7 @@ describe('builtins/copy: ', () => { expect.assertions(1); try { - copy.execute([ + await copy.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', @@ -150,7 +150,8 @@ describe('builtins/copy: ', () => { ); } }); - it('does not persist the original value when keep-existing==false.', () => { + + it('does not persist the original value when keep-existing==false.', async () => { expect.assertions(1); const config = { 'keep-existing': false, @@ -167,7 +168,7 @@ describe('builtins/copy: ', () => { }, ]; - const result = copy.execute([ + const result = await copy.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -178,7 +179,7 @@ describe('builtins/copy: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when the `from` contains arithmetic expression', () => { + it('successfully executes when the `from` contains arithmetic expression.', async () => { const config = { 'keep-existing': false, from: '=3*size', @@ -203,7 +204,7 @@ describe('builtins/copy: ', () => { ]; expect.assertions(1); - const result = copy.execute(inputs); + const result = await copy.execute(inputs); expect(result).toEqual(expectedResult); }); diff --git a/src/__tests__/if-run/builtins/csv-lookup.test.ts b/src/__tests__/if-run/builtins/csv-lookup.test.ts index 29e5c99f7..6861f9c39 100644 --- a/src/__tests__/if-run/builtins/csv-lookup.test.ts +++ b/src/__tests__/if-run/builtins/csv-lookup.test.ts @@ -21,7 +21,7 @@ const {MISSING_CONFIG, MISSING_CSV_COLUMN, NO_QUERY_DATA} = STRINGS; describe('builtins/CSVLookup: ', () => { const mock = new AxiosMockAdapter(axios); - describe.skip('CSVLookup: ', () => { + describe('CSVLookup: ', () => { const parametersMetadata = { inputs: {}, outputs: {}, diff --git a/src/__tests__/if-run/builtins/divide.test.ts b/src/__tests__/if-run/builtins/divide.test.ts index b6434e2e4..ae48c4a61 100644 --- a/src/__tests__/if-run/builtins/divide.test.ts +++ b/src/__tests__/if-run/builtins/divide.test.ts @@ -8,7 +8,7 @@ const {InputValidationError, ConfigError, MissingInputDataError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA} = STRINGS; describe('builtins/divide: ', () => { - describe.skip('Divide: ', () => { + describe('Divide: ', () => { const config = { numerator: 'vcpus-allocated', denominator: 2, @@ -137,7 +137,7 @@ describe('builtins/divide: ', () => { expect(response).toEqual(expectedResult); }); - it('successfully executes when a parameter contains arithmetic expression.', () => { + it('successfully executes when a parameter contains arithmetic expression.', async () => { expect.assertions(1); const config = { @@ -154,7 +154,7 @@ describe('builtins/divide: ', () => { 'vcpus-allocated': 24, }, ]; - const response = divide.execute(input); + const response = await divide.execute(input); const expectedResult = [ { @@ -168,7 +168,7 @@ describe('builtins/divide: ', () => { expect(response).toEqual(expectedResult); }); - it('throws an error the `numerator` parameter has wrong arithmetic expression.', () => { + it('throws an error the `numerator` parameter has wrong arithmetic expression.', async () => { const config = { numerator: '3*"vcpus-allocated"', denominator: 'duration', @@ -185,7 +185,7 @@ describe('builtins/divide: ', () => { ]; expect.assertions(2); try { - divide.execute(inputs); + await divide.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( diff --git a/src/__tests__/if-run/builtins/exponent.test.ts b/src/__tests__/if-run/builtins/exponent.test.ts index 0ea6a061a..3c2c977bf 100644 --- a/src/__tests__/if-run/builtins/exponent.test.ts +++ b/src/__tests__/if-run/builtins/exponent.test.ts @@ -1,4 +1,3 @@ -import {ExponentConfig} from '@grnsft/if-core/types'; import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../../if-run/config'; @@ -8,7 +7,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -describe.skip('builtins/exponent: ', () => { +describe('builtins/exponent: ', () => { describe('Exponent: ', () => { const config = { 'input-parameter': 'energy/base', @@ -86,6 +85,7 @@ describe.skip('builtins/exponent: ', () => { it('successfully executes when the `mapping` maps output parameter.', async () => { expect.assertions(1); + const mapping = { energy: 'energy-result', }; @@ -94,6 +94,7 @@ describe.skip('builtins/exponent: ', () => { exponent: 3, 'output-parameter': 'energy', }; + const exponent = Exponent(config, parametersMetadata, mapping); const expectedResult = [ { @@ -136,7 +137,7 @@ describe.skip('builtins/exponent: ', () => { it('throws an error on input param value not numeric.', async () => { expect.assertions(1); - const input = [ + const inputs = [ { duration: 3600, 'energy/base': 'i-am-not-a-number', @@ -145,7 +146,7 @@ describe.skip('builtins/exponent: ', () => { ]; try { - await exponent.execute(input); + await exponent.execute(inputs); } catch (error) { expect(error).toStrictEqual( new InputValidationError( @@ -185,7 +186,7 @@ describe.skip('builtins/exponent: ', () => { expect(response).toEqual(expectedResult); }); - it('successfully executes when a parameter contains arithmetic expression.', () => { + it('successfully executes when a parameter contains arithmetic expression.', async () => { const config = { 'input-parameter': "=2*'energy/base'", exponent: 3, @@ -209,7 +210,7 @@ describe.skip('builtins/exponent: ', () => { }, ]; - const result = exponent.execute([ + const result = await exponent.execute([ { duration: 3600, 'energy/base': 4, @@ -220,7 +221,7 @@ describe.skip('builtins/exponent: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when the `exponent` has wrong arithmetic expression.', () => { + it('throws an error when the `exponent` has wrong arithmetic expression.', async () => { const config = { 'input-parameter': "=2*'energy/base'", exponent: "3*'mock-param'", @@ -231,16 +232,12 @@ describe.skip('builtins/exponent: ', () => { outputs: {}, }; - const exponent = Exponent( - config as any as ExponentConfig, - parametersMetadata, - {} - ); + const exponent = Exponent(config, parametersMetadata, {}); expect.assertions(2); try { - exponent.execute([ + await exponent.execute([ { duration: 3600, 'energy/base': 4, @@ -260,12 +257,12 @@ describe.skip('builtins/exponent: ', () => { it('throws an error on missing config.', async () => { const config = undefined; - const divide = Exponent(config!, parametersMetadata, {}); + const exponent = Exponent(config!, parametersMetadata, {}); expect.assertions(1); try { - await divide.execute([ + await exponent.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index a2250fe8d..be379b3d3 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -9,7 +9,7 @@ const {InputValidationError, ConfigError} = ERRORS; const {MISSING_CONFIG, WITHIN_THE_RANGE, ARRAY_LENGTH_NON_EMPTY, X_Y_EQUAL} = STRINGS; -describe.skip('builtins/interpolation: ', () => { +describe('builtins/interpolation: ', () => { describe('Interpolation: ', () => { const config = { method: Method.LINEAR, @@ -40,7 +40,7 @@ describe.skip('builtins/interpolation: ', () => { }); describe('execute(): ', () => { - it('returns result when all parameters are valid.', () => { + it('returns result when all parameters are valid.', async () => { const outputs = [ { timestamp: '2023-07-06T00:00', @@ -50,10 +50,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when `mapping` has valid data.', () => { + it('returns result when `mapping` has valid data.', async () => { const mapping = { 'cpu/utilization': 'cpu/util', }; @@ -81,10 +83,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the `mapping` maps output parameter.', () => { + it('returns result when the `mapping` maps output parameter.', async () => { const mapping = { 'interpolation-result': 'result', }; @@ -112,10 +116,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the `method` is not provided in the config.', () => { + it('returns result when the `method` is not provided in the config.', async () => { const config = { x: [0, 10, 50, 100], y: [0.12, 0.32, 0.75, 1.02], @@ -133,10 +139,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the `method` is `spline`.', () => { + it('returns result when the `method` is `spline`.', async () => { const newConfig = Object.assign({}, config, {method: Method.SPLINE}); const plugin = Interpolation(newConfig, parametersMetadata, {}); @@ -149,10 +157,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the `method` is `polynomial`.', () => { + it('returns result when the `method` is `polynomial`.', async () => { const newConfig = Object.assign({}, config, { method: Method.POLYNOMIAL, }); @@ -167,10 +177,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the elements of `x` is not in acsending order.', () => { + it('returns result when the elements of `x` is not in acsending order.', async () => { const newConfig = Object.assign({}, config, { x: [0, 10, 100, 50], }); @@ -184,10 +196,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('returns result when the `cpu/utilization` is equal to one of the `x` points element.', () => { + it('returns result when the `cpu/utilization` is equal to one of the `x` points element.', async () => { const inputs = [ { timestamp: '2023-07-06T00:00', @@ -204,10 +218,12 @@ describe.skip('builtins/interpolation: ', () => { }, ]; - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('successfully executes when the config parameter contains an arithmetic expression.', () => { + it('successfully executes when the config parameter contains an arithmetic expression.', async () => { const config = { method: Method.LINEAR, x: [0, 10, 50, 100], @@ -234,10 +250,12 @@ describe.skip('builtins/interpolation: ', () => { ]; expect.assertions(1); - expect(plugin.execute(inputs)).toEqual(outputs); + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); }); - it('throws an error the config parameter contains wrong arithmetic expression.', () => { + it('throws an error the config parameter contains wrong arithmetic expression.', async () => { const config = { method: Method.LINEAR, x: [0, 10, 50, 100], @@ -257,7 +275,7 @@ describe.skip('builtins/interpolation: ', () => { expect.assertions(2); try { - plugin.execute(inputs); + await plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( @@ -268,20 +286,20 @@ describe.skip('builtins/interpolation: ', () => { } }); - it('throws an when the config is not provided.', () => { + it('throws an when the config is not provided.', async () => { const config = undefined; const plugin = Interpolation(config!, parametersMetadata, {}); expect.assertions(2); try { - plugin.execute(inputs); + await plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(ConfigError); expect(error).toEqual(new ConfigError(MISSING_CONFIG)); } }); - it('throws an error when `x` and `y` points not equal.', () => { + it('throws an error when `x` and `y` points not equal.', async () => { const newConfig = Object.assign({}, config, { x: [0, 10, 100], }); @@ -289,14 +307,14 @@ describe.skip('builtins/interpolation: ', () => { expect.assertions(2); try { - plugin.execute(inputs); + await plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual(new InputValidationError(X_Y_EQUAL)); } }); - it('throws an error when `cpu/utilization` is out of the range of `x` elements.', () => { + it('throws an error when `cpu/utilization` is out of the range of `x` elements.', async () => { const inputs = [ { timestamp: '2023-07-06T00:00', @@ -306,13 +324,14 @@ describe.skip('builtins/interpolation: ', () => { ]; expect.assertions(2); try { - plugin.execute(inputs); + await plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual(new InputValidationError(WITHIN_THE_RANGE)); } }); - it('throws an error when the the length of the input arrays is <2', () => { + + it('throws an error when the the length of the input arrays is <2', async () => { const basicConfig = { x: [0], y: [0.12], @@ -331,7 +350,7 @@ describe.skip('builtins/interpolation: ', () => { ]; expect.assertions(2); try { - plugin.execute(inputs); + await plugin.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(InputValidationError); expect(error).toEqual( diff --git a/src/__tests__/if-run/builtins/multiply.test.ts b/src/__tests__/if-run/builtins/multiply.test.ts index 7b9013dd5..d7b7a9147 100644 --- a/src/__tests__/if-run/builtins/multiply.test.ts +++ b/src/__tests__/if-run/builtins/multiply.test.ts @@ -3,12 +3,13 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Multiply} from '../../../if-run/builtins/multiply'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, ConfigError} = ERRORS; +const {InputValidationError, ConfigError, WrongArithmeticExpressionError} = + ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/multiply: ', () => { - describe.skip('Multiply: ', () => { + describe('Multiply: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy', @@ -177,7 +178,7 @@ describe('builtins/multiply: ', () => { expect(response).toEqual(expectedResult); }); - it('successfully executes when the config output parameter contains arithmetic expression.', () => { + it('successfully executes when the config output parameter contains arithmetic expression.', async () => { expect.assertions(1); const config = { @@ -194,7 +195,7 @@ describe('builtins/multiply: ', () => { 'memory/energy': 2, }, ]; - const response = multiply.execute(inputs); + const response = await multiply.execute(inputs); const expectedResult = [ { @@ -210,7 +211,7 @@ describe('builtins/multiply: ', () => { expect(response).toEqual(expectedResult); }); - it('throws an error the config output parameter has wrong arithmetic expression.', () => { + it('throws an error the config output parameter has wrong arithmetic expression.', async () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': '2*energy', @@ -227,13 +228,14 @@ describe('builtins/multiply: ', () => { }, ]; expect.assertions(2); + try { - multiply.execute(inputs); + await multiply.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( - new InputValidationError( - 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + new WrongArithmeticExpressionError( + 'The output parameter `2*energy` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' ) ); } diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index cc3fc3f18..64c6afc03 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -153,7 +153,7 @@ describe.skip('builtins/sci-embodied:', () => { } }); - it('successfully executes when a parameter contains arithmetic expression.', () => { + it('successfully executes when a parameter contains arithmetic expression.', async () => { const config = { 'baseline-vcpus': 1, 'baseline-memory': 16, @@ -182,7 +182,7 @@ describe.skip('builtins/sci-embodied:', () => { }, ]; - const result = sciEmbodied.execute(inputs); + const result = await sciEmbodied.execute(inputs); expect.assertions(1); @@ -204,7 +204,7 @@ describe.skip('builtins/sci-embodied:', () => { ]); }); - it('throws an error the `gpu-emissions-constant` parameter has wrong arithmetic expression.', () => { + it('throws an error the `gpu-emissions-constant` parameter has wrong arithmetic expression.', async () => { const config = { 'baseline-vcpus': 1, 'baseline-memory': 16, @@ -230,7 +230,7 @@ describe.skip('builtins/sci-embodied:', () => { expect.assertions(2); try { - sciEmbodied.execute(inputs); + await sciEmbodied.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( diff --git a/src/__tests__/if-run/builtins/sci.test.ts b/src/__tests__/if-run/builtins/sci.test.ts index 04e8900c6..4d4621ad4 100644 --- a/src/__tests__/if-run/builtins/sci.test.ts +++ b/src/__tests__/if-run/builtins/sci.test.ts @@ -9,7 +9,7 @@ const {MissingInputDataError, ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/sci:', () => { - describe.skip('Sci: ', () => { + describe('Sci: ', () => { const config = {'functional-unit': 'users'}; const parametersMetadata = {inputs: {}, outputs: {}}; const sci = Sci(config, parametersMetadata, {}); @@ -225,14 +225,14 @@ describe('builtins/sci:', () => { expect(result).toStrictEqual([{...inputs[0], sci: inputs[0].carbon}]); }); - it('throws an error on missing config.', () => { + it('throws an error on missing config.', async () => { const config = undefined; const sci = Sci(config!, parametersMetadata, {}); expect.assertions(1); try { - sci.execute([ + await sci.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -243,7 +243,7 @@ describe('builtins/sci:', () => { } }); - it('successfully executes when a parameter contains arithmetic expression.', () => { + it('successfully executes when a parameter contains arithmetic expression.', async () => { const config = {'functional-unit': '=10*users'}; const sci = Sci(config, parametersMetadata, {}); expect.assertions(1); @@ -258,7 +258,7 @@ describe('builtins/sci:', () => { duration: 1, }, ]; - const result = sci.execute(inputs); + const result = await sci.execute(inputs); expect.assertions(1); expect(result).toStrictEqual([ @@ -275,7 +275,7 @@ describe('builtins/sci:', () => { ]); }); - it('throws an error the `functional-unit` parameter has wrong arithmetic expression.', () => { + it('throws an error the `functional-unit` parameter has wrong arithmetic expression.', async () => { const config = {'functional-unit': '10*users'}; const sci = Sci(config, parametersMetadata, {}); expect.assertions(1); @@ -294,7 +294,7 @@ describe('builtins/sci:', () => { expect.assertions(2); try { - sci.execute(inputs); + await sci.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( diff --git a/src/__tests__/if-run/builtins/subtract.test.ts b/src/__tests__/if-run/builtins/subtract.test.ts index a7f89283b..3e283f51e 100644 --- a/src/__tests__/if-run/builtins/subtract.test.ts +++ b/src/__tests__/if-run/builtins/subtract.test.ts @@ -4,12 +4,13 @@ import {Subtract} from '../../../if-run/builtins/subtract'; import {STRINGS} from '../../../if-run/config'; -const {InputValidationError, ConfigError} = ERRORS; +const {InputValidationError, ConfigError, WrongArithmeticExpressionError} = + ERRORS; const {MISSING_CONFIG} = STRINGS; describe('builtins/subtract: ', () => { - describe.skip('Subtract: ', () => { + describe('Subtract: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], 'output-parameter': 'energy/diff', @@ -176,7 +177,7 @@ describe('builtins/subtract: ', () => { }); }); - it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + it('successfully executes when the config output parameter contains an arithmetic expression.', async () => { expect.assertions(1); const config = { @@ -196,7 +197,7 @@ describe('builtins/subtract: ', () => { }, ]; - const result = subtract.execute([ + const result = await subtract.execute([ { duration: 3600, 'cpu/energy': 4, @@ -209,7 +210,7 @@ describe('builtins/subtract: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error the config output parameter has wrong arithmetic expression.', () => { + it('throws an error the config output parameter has wrong arithmetic expression.', async () => { expect.assertions(2); const config = { @@ -229,12 +230,12 @@ describe('builtins/subtract: ', () => { ]; try { - subtract.execute(inputs); + await subtract.execute(inputs); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( - new InputValidationError( - 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + new WrongArithmeticExpressionError( + "The output parameter `=2 & 'energy/diff'` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`." ) ); } diff --git a/src/__tests__/if-run/builtins/sum.test.ts b/src/__tests__/if-run/builtins/sum.test.ts index 4df283366..31e49a27b 100644 --- a/src/__tests__/if-run/builtins/sum.test.ts +++ b/src/__tests__/if-run/builtins/sum.test.ts @@ -2,12 +2,9 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {Sum} from '../../../if-run/builtins/sum'; -import {STRINGS} from '../../../if-run/config'; +const {InputValidationError, WrongArithmeticExpressionError} = ERRORS; -const {ConfigError, InputValidationError} = ERRORS; -const {MISSING_CONFIG} = STRINGS; - -describe.skip('builtins/sum: ', () => { +describe('builtins/sum: ', () => { describe('Sum: ', () => { const config = { 'input-parameters': ['cpu/energy', 'network/energy', 'memory/energy'], @@ -27,7 +24,7 @@ describe.skip('builtins/sum: ', () => { }); describe('execute(): ', () => { - it('successfully applies Sum strategy to given input.', () => { + it('successfully applies Sum strategy to given input.', async () => { expect.assertions(1); const expectedResult = [ @@ -41,7 +38,7 @@ describe.skip('builtins/sum: ', () => { }, ]; - const result = sum.execute([ + const result = await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -54,7 +51,7 @@ describe.skip('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when `mapping` has valid data.', () => { + it('successfully executes when `mapping` has valid data.', async () => { expect.assertions(1); const mapping = { @@ -79,7 +76,7 @@ describe.skip('builtins/sum: ', () => { }, ]; - const result = sum.execute([ + const result = await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -92,7 +89,7 @@ describe.skip('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when the `mapping` maps output parameter.', () => { + it('successfully executes when the `mapping` maps output parameter.', async () => { expect.assertions(1); const mapping = { @@ -116,7 +113,7 @@ describe.skip('builtins/sum: ', () => { }, ]; - const result = sum.execute([ + const result = await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -129,14 +126,14 @@ describe.skip('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when config is not provided.', () => { + it('throws an error when config is not provided.', async () => { const config = undefined; const sum = Sum(config!, parametersMetadata, {}); expect.assertions(1); try { - sum.execute([ + await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -146,15 +143,19 @@ describe.skip('builtins/sum: ', () => { }, ]); } catch (error) { - expect(error).toStrictEqual(new ConfigError(MISSING_CONFIG)); + expect(error).toStrictEqual( + new InputValidationError( + '"input-parameters" parameter is required. Error code: invalid_type.,"output-parameter" parameter is required. Error code: invalid_type.' + ) + ); } }); - it('throws an error on missing params in input.', () => { + it('throws an error on missing params in input.', async () => { expect.assertions(1); try { - sum.execute([ + await sum.execute([ { duration: 3600, timestamp: '2021-01-01T00:00:00Z', @@ -169,7 +170,7 @@ describe.skip('builtins/sum: ', () => { } }); - it('returns a result with input params not related to energy.', () => { + it('returns a result with input params not related to energy.', async () => { expect.assertions(1); const newConfig = { 'input-parameters': ['carbon', 'other-carbon'], @@ -185,7 +186,7 @@ describe.skip('builtins/sum: ', () => { 'other-carbon': 2, }, ]; - const response = sum.execute(data); + const response = await sum.execute(data); const expectedResult = [ { @@ -200,7 +201,7 @@ describe.skip('builtins/sum: ', () => { expect(response).toEqual(expectedResult); }); - it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + it('successfully executes when the config output parameter contains an arithmetic expression.', async () => { expect.assertions(1); const config = { @@ -220,7 +221,7 @@ describe.skip('builtins/sum: ', () => { }, ]; - const result = sum.execute([ + const result = await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -233,7 +234,7 @@ describe.skip('builtins/sum: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error the config output parameter has wrong arithmetic expression.', () => { + it('throws an error the config output parameter has wrong arithmetic expression.', async () => { expect.assertions(2); const config = { @@ -244,7 +245,7 @@ describe.skip('builtins/sum: ', () => { const sum = Sum(config, parametersMetadata, {}); try { - sum.execute([ + await sum.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -256,8 +257,8 @@ describe.skip('builtins/sum: ', () => { } catch (error) { expect(error).toBeInstanceOf(Error); expect(error).toEqual( - new InputValidationError( - 'The `output-parameter` contains an invalid arithmetic expression. It should start with `=` and include the symbols `*`, `+`, `-` and `/`.' + new WrongArithmeticExpressionError( + `The output parameter \`${config['output-parameter']}\` contains an invalid arithmetic expression. It should start with \`=\` and include the symbols \`*\`, \`+\`, \`-\` and \`/\`.` ) ); } diff --git a/src/__tests__/if-run/builtins/time-converter.test.ts b/src/__tests__/if-run/builtins/time-converter.test.ts index 6b7a190c2..8b2ce8ea1 100644 --- a/src/__tests__/if-run/builtins/time-converter.test.ts +++ b/src/__tests__/if-run/builtins/time-converter.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../if-run/config'; const {ConfigError, InputValidationError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -describe.skip('builtins/time-converter: ', () => { +describe('builtins/time-converter: ', () => { describe('TimeConverter: ', () => { const config = { 'input-parameter': 'energy-per-year', @@ -29,7 +29,7 @@ describe.skip('builtins/time-converter: ', () => { }); describe('execute(): ', () => { - it('successfully applies TimeConverter strategy to given input.', () => { + it('successfully applies TimeConverter strategy to given input.', async () => { expect.assertions(1); const expectedResult = [ @@ -41,7 +41,7 @@ describe.skip('builtins/time-converter: ', () => { }, ]; - const result = timeConverter.execute([ + const result = await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -52,7 +52,7 @@ describe.skip('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when the `mapping` is not empty object.', () => { + it('successfully executes when the `mapping` is not empty object.', async () => { expect.assertions(1); const mapping = { @@ -72,7 +72,7 @@ describe.skip('builtins/time-converter: ', () => { }, ]; - const result = timeConverter.execute([ + const result = await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -83,7 +83,7 @@ describe.skip('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('successfully executes when the `mapping` maps output parameter.', () => { + it('successfully executes when the `mapping` maps output parameter.', async () => { expect.assertions(1); const mapping = { @@ -103,7 +103,7 @@ describe.skip('builtins/time-converter: ', () => { }, ]; - const result = timeConverter.execute([ + const result = await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -114,14 +114,14 @@ describe.skip('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error when config is not provided.', () => { + it('throws an error when config is not provided.', async () => { const config = undefined; const timeConverter = TimeConverter(config!, parametersMetadata, {}); expect.assertions(1); try { - timeConverter.execute([ + await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -133,11 +133,11 @@ describe.skip('builtins/time-converter: ', () => { } }); - it('throws an error on missing params in input.', () => { + it('throws an error on missing params in input.', async () => { expect.assertions(1); try { - timeConverter.execute([ + await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -152,7 +152,7 @@ describe.skip('builtins/time-converter: ', () => { } }); - it('returns a result when `new-time-unit` is a different time unit than `duration`.', () => { + it('returns a result when `new-time-unit` is a different time unit than `duration`.', async () => { expect.assertions(1); const newConfig = { 'input-parameter': 'energy-per-year', @@ -169,7 +169,7 @@ describe.skip('builtins/time-converter: ', () => { 'energy-per-year': 10000, }, ]; - const response = timeConverter.execute(data); + const response = await timeConverter.execute(data); const expectedResult = [ { timestamp: '2021-01-01T00:00:00Z', @@ -182,7 +182,7 @@ describe.skip('builtins/time-converter: ', () => { expect(response).toEqual(expectedResult); }); - it('successfully executes when the config output parameter contains an arithmetic expression.', () => { + it('successfully executes when the config output parameter contains an arithmetic expression.', async () => { expect.assertions(1); const config = { @@ -202,7 +202,7 @@ describe.skip('builtins/time-converter: ', () => { }, ]; - const result = timeConverter.execute([ + const result = await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, @@ -213,7 +213,7 @@ describe.skip('builtins/time-converter: ', () => { expect(result).toStrictEqual(expectedResult); }); - it('throws an error the config input parameter has wrong arithmetic expression.', () => { + it('throws an error the config input parameter has wrong arithmetic expression.', async () => { expect.assertions(2); const config = { 'input-parameter': '2*"energy-per-year"', @@ -225,7 +225,7 @@ describe.skip('builtins/time-converter: ', () => { const timeConverter = TimeConverter(config, parametersMetadata, {}); try { - timeConverter.execute([ + await timeConverter.execute([ { timestamp: '2021-01-01T00:00:00Z', duration: 3600, From 04aa551fc924c8c5f6eaffba228d7289bb2ad095 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sat, 28 Sep 2024 23:11:46 +0400 Subject: [PATCH 798/863] test(builtins): remove skip from mock observation --- src/__tests__/if-run/builtins/mock-observations.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/builtins/mock-observations.test.ts b/src/__tests__/if-run/builtins/mock-observations.test.ts index b55f2eea1..046a066f6 100644 --- a/src/__tests__/if-run/builtins/mock-observations.test.ts +++ b/src/__tests__/if-run/builtins/mock-observations.test.ts @@ -7,7 +7,7 @@ import {STRINGS} from '../../../if-run/config'; const {InputValidationError, ConfigError} = ERRORS; const {INVALID_MIN_MAX} = STRINGS; -describe.skip('builtins/mock-observations: ', () => { +describe('builtins/mock-observations: ', () => { const parametersMetadata = { inputs: {}, outputs: {}, From 7bce20dc21e7984efc819f9f07186e1addeb5d9f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 29 Sep 2024 09:33:34 +0400 Subject: [PATCH 799/863] test(builtins): tune unit tests for time sync --- .../if-run/builtins/time-sync.test.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 153c44db2..0228f4da6 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -13,7 +13,6 @@ Settings.defaultZone = 'utc'; const { InputValidationError, InvalidPaddingError, - InvalidDateInInputError, InvalidInputError, ConfigError, } = ERRORS; @@ -22,9 +21,7 @@ const { INCOMPATIBLE_RESOLUTION_WITH_INTERVAL, INCOMPATIBLE_RESOLUTION_WITH_GAPS, INVALID_OBSERVATION_OVERLAP, - INVALID_TIME_NORMALIZATION, AVOIDING_PADDING_BY_EDGES, - INVALID_DATE_TYPE, } = STRINGS; jest.mock('luxon', () => { @@ -207,6 +204,7 @@ describe('builtins/time-sync:', () => { interval: 5, 'allow-padding': true, }; + const timeModel = TimeSync( invalidEndTimeConfig, parametersMetadata, @@ -252,7 +250,9 @@ describe('builtins/time-sync:', () => { ]); } catch (error) { expect(error).toStrictEqual( - new ConfigError(INVALID_TIME_NORMALIZATION) + new InputValidationError( + '"start-time" parameter is required. Error code: invalid_type.,"end-time" parameter is required. Error code: invalid_type.,"interval" parameter is required. Error code: invalid_type.,"allow-padding" parameter is required. Error code: invalid_type.' + ) ); } }); @@ -346,7 +346,7 @@ describe('builtins/time-sync:', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toStrictEqual( new InputValidationError( - '"timestamp" parameter is required in input[0]. Error code: invalid_union.' + '"timestamp" parameter is required at index 0. Error code: invalid_union.' ) ); } @@ -378,7 +378,7 @@ describe('builtins/time-sync:', () => { expect(error).toBeInstanceOf(InputValidationError); expect(error).toStrictEqual( new InputValidationError( - '"timestamp" parameter is invalid datetime in input[0]. Error code: invalid_string.' + '"timestamp" parameter is invalid datetime at index 0. Error code: invalid_string.' ) ); } @@ -404,9 +404,11 @@ describe('builtins/time-sync:', () => { try { await timeModel.execute(data); } catch (error) { - expect(error).toBeInstanceOf(InvalidDateInInputError); + expect(error).toBeInstanceOf(InputValidationError); expect(error).toStrictEqual( - new InvalidDateInInputError(INVALID_DATE_TYPE(data[0].timestamp)) + new InputValidationError( + '"timestamp" parameter is expected string, received number at index 0. Error code: invalid_union.' + ) ); } }); @@ -702,7 +704,7 @@ describe('builtins/time-sync:', () => { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'resources-total': 10, - 'time-allocated': 3.2, + 'time-allocated': 3, }, { timestamp: '2023-12-12T00:00:05.000Z', @@ -900,7 +902,7 @@ describe('builtins/time-sync:', () => { expect(DateTime.fromISO(result[0].timestamp).offset === 0); }); - it('successfully executes when the `duration` contains an arithmetic expression.', () => { + it.skip('successfully executes when the `duration` contains an arithmetic expression.', () => { expect.assertions(1); const basicConfig = { @@ -1031,6 +1033,7 @@ describe('builtins/time-sync:', () => { 'allow-padding': true, 'upsampling-resolution': 5, }; + const timeModel = TimeSync(basicConfig, parametersMetadata, {}); const result = await timeModel.execute([ { From 7963d253f6ee1dae45f32cdcf4427488f998804b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 29 Sep 2024 09:34:47 +0400 Subject: [PATCH 800/863] feat(builtins): rewrite regex with plugin factory --- src/if-run/builtins/regex/index.ts | 139 ++++++++++------------------- 1 file changed, 49 insertions(+), 90 deletions(-) diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 171f4a8ad..6aabd521b 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -1,116 +1,75 @@ import {z} from 'zod'; import {ERRORS} from '@grnsft/if-core/utils'; -import { - mapConfigIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; + +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; const {MissingInputDataError, ConfigError, RegexMismatchError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; -export const Regex = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Checks config value are valid. - */ - const validateConfig = () => { - if (!config) { +export const Regex = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: (config: ConfigParams) => { + if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); } - const mappedConfig = mapConfigIfNeeded(config, mapping); - const schema = z.object({ parameter: z.string().min(1), match: z.string().min(1), output: z.string(), }); - return validate>(schema, mappedConfig); - }; + return validate>(schema, config); + }, + inputValidation: (input: PluginParams, config: ConfigParams) => { + const parameter = config['parameter']; - /** - * Checks for required fields in input. - */ - const validateSingleInput = (input: PluginParams, parameter: string) => { if (!input[parameter]) { throw new MissingInputDataError(MISSING_INPUT_DATA(parameter)); } return input; - }; - - /** - * Executes the regex of the given parameter. - */ - const execute = (inputs: PluginParams[]) => { - const safeConfig = validateConfig(); - const {parameter: parameter, match, output} = safeConfig; - - return inputs.map(input => { - const safeInput = Object.assign( - {}, - input, - validateSingleInput(input, parameter) - ); - - const result = { - ...input, - [output]: extractMatching(safeInput, parameter, match), - }; - - return mapOutputIfNeeded(result, mapping); - }); - }; - - /** - * Extracts a substring from the given input parameter that matches the provided regular expression pattern. - */ - const extractMatching = ( - input: PluginParams, - parameter: string, - match: string - ) => { - if (!match.startsWith('/')) { - match = '/' + match; - } - - if (!match.endsWith('/g') && !match.endsWith('/')) { - match += '/'; - } - - const regex = eval(match); - const matchedItems = input[parameter].match(regex); - - if (!matchedItems || matchedItems.length === 0) { - throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); - } - - return matchedItems.join(' '); - }; - - return { - metadata, - execute, - }; + }, + implementation: async (inputs, config) => { + const {parameter: parameter, match, output} = config; + + return inputs.map(input => ({ + ...input, + [output]: extractMatching(input, parameter, match), + })); + }, +}); + +/** + * Extracts a substring from the given input parameter that matches the provided regular expression pattern. + */ +const extractMatching = ( + input: PluginParams, + parameter: string, + match: string +) => { + if (!match.startsWith('/')) { + match = '/' + match; + } + + if (!match.endsWith('/g') && !match.endsWith('/')) { + match += '/'; + } + + const regex = eval(match); + const matchedItems = input[parameter].match(regex); + + if (!matchedItems || matchedItems.length === 0) { + throw new RegexMismatchError(REGEX_MISMATCH(input[parameter], match)); + } + + return matchedItems.join(' '); }; From c1e019ed7f2135e525b2af5b8a3f593cc454a940 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 29 Sep 2024 09:35:15 +0400 Subject: [PATCH 801/863] feat(builtins): rewrite shell with plugin factory --- src/if-run/builtins/shell/index.ts | 97 +++++++++++------------------- 1 file changed, 36 insertions(+), 61 deletions(-) diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index ddf8b619d..9995a1ba1 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -2,15 +2,9 @@ import {spawnSync, SpawnSyncReturns} from 'child_process'; import {loadAll, dump} from 'js-yaml'; import {z} from 'zod'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; import {ERRORS} from '@grnsft/if-core/utils'; -import {mapOutputIfNeeded} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, - PluginParams, - ConfigParams, - PluginParametersMetadata, - MappingParams, -} from '@grnsft/if-core/types'; +import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; @@ -19,34 +13,12 @@ import {STRINGS} from '../../config'; const {ProcessExecutionError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; -export const Shell = ( - config: ConfigParams, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', - inputs: parametersMetadata?.inputs, - outputs: parametersMetadata?.outputs, - }; - - /** - * Calculate the total emissions for a list of inputs. - */ - const execute = (inputs: PluginParams[]): any[] => { - const inputWithConfig = Object.assign({}, inputs[0], validateConfig()); - 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 => mapOutputIfNeeded(output, mapping)); - }; - - /** - * Checks for required fields in input. - */ - const validateConfig = () => { +export const Shell = PluginFactory({ + metadata: { + inputs: {}, + outputs: {}, + }, + configValidation: (config: ConfigParams) => { if (!config) { throw new ConfigError(MISSING_CONFIG); } @@ -56,31 +28,34 @@ export const Shell = ( }); return validate>(schema, config); - }; - - /** - * Runs the model in a shell. Spawns a child process to run an external IMP, - * an executable with a CLI exposing two methods: `--execute` and `--manifest`. - * The shell command then calls the `--command` method passing var manifest as the path to the desired manifest file. - */ - const runModelInShell = (input: string, command: string) => { - try { - const [executable, ...args] = command.split(' '); - - const result: SpawnSyncReturns = spawnSync(executable, args, { - input, - encoding: 'utf8', - }); - const outputs = loadAll(result.stdout); + }, + implementation: async (inputs, config) => { + const inputWithConfig = Object.assign({}, inputs[0], config); + const command = inputWithConfig.command; + const inputAsString: string = dump(inputs, {indent: 2}); + const results = runModelInShell(inputAsString, command); - return {outputs}; - } catch (error: any) { - throw new ProcessExecutionError(error.message); - } - }; + return results?.outputs?.flat() as PluginParams[]; + }, +}); + +/** + * Runs the model in a shell. Spawns a child process to run an external IMP, + * an executable with a CLI exposing two methods: `--execute` and `--manifest`. + * The shell command then calls the `--command` method passing var manifest as the path to the desired manifest file. + */ +const runModelInShell = (input: string, command: string) => { + try { + const [executable, ...args] = command.split(' '); + + const result: SpawnSyncReturns = spawnSync(executable, args, { + input, + encoding: 'utf8', + }); + const outputs = loadAll(result.stdout); - return { - metadata, - execute, - }; + return {outputs}; + } catch (error: any) { + throw new ProcessExecutionError(error.message); + } }; From 5f903fc09bc34f910f1f4bdbfe4a68285c4d6df7 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Sun, 29 Sep 2024 09:35:54 +0400 Subject: [PATCH 802/863] feat(builtins): rewrite time-sync with plugin factory --- src/if-run/builtins/time-sync/index.ts | 925 ++++++++++++------------- 1 file changed, 445 insertions(+), 480 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index f26b62ded..20d5fee24 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -4,16 +4,10 @@ import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; import {ERRORS, evaluateInput} from '@grnsft/if-core/utils'; import { - mapInputIfNeeded, - mapOutputIfNeeded, -} from '@grnsft/if-core/utils/helpers'; -import { - ExecutePlugin, PluginParams, PaddingReceipt, - PluginParametersMetadata, - ParameterMetadata, MappingParams, + ConfigParams, } from '@grnsft/if-core/types'; import {TimeParams, TimeNormalizerConfig} from '../../types/time-sync'; @@ -22,6 +16,7 @@ import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; import {getAggregationInfoFor} from '../../lib/aggregate'; +import {PluginFactory} from '@grnsft/if-core/interfaces'; Settings.defaultZone = 'utc'; @@ -41,8 +36,6 @@ const { AVOIDING_PADDING_BY_EDGES, INVALID_DATE_TYPE, START_LOWER_END, - TIMESTAMP_REQUIRED, - INVALID_DATETIME, } = STRINGS; /** @@ -60,195 +53,28 @@ const { * allow-padding: true * ``` */ -export const TimeSync = ( - config: TimeNormalizerConfig, - parametersMetadata: PluginParametersMetadata, - mapping: MappingParams -): ExecutePlugin => { - const metadata = { - kind: 'execute', +export const TimeSync = PluginFactory({ + metadata: { inputs: { - ...({ - timestamp: { - description: 'refers to the time of occurrence of the input', - unit: 'RFC3339', - 'aggregation-method': { - time: 'none', - component: 'none', - }, + timestamp: { + description: 'refers to the time of occurrence of the input', + unit: 'RFC3339', + 'aggregation-method': { + time: 'none', + component: 'none', }, - duration: { - description: 'refers to the duration of the input', - unit: 'seconds', - 'aggregation-method': { - time: 'sum', - component: 'none', - }, + }, + duration: { + description: 'refers to the duration of the input', + unit: 'seconds', + 'aggregation-method': { + time: 'sum', + component: 'none', }, - } as ParameterMetadata), - ...parametersMetadata?.inputs, - }, - outputs: parametersMetadata?.outputs, - }; - - /** - * Take input array and return time-synchronized input array. - */ - const execute = (inputs: PluginParams[]): PluginParams[] => { - const validatedConfig = validateConfig(); - const timeParams = { - startTime: DateTime.fromISO(validatedConfig['start-time']), - endTime: DateTime.fromISO(validatedConfig['end-time']), - interval: validatedConfig.interval, - allowPadding: validatedConfig['allow-padding'], - upsamplingResolution: validatedConfig['upsampling-resolution'] - ? validatedConfig['upsampling-resolution'] - : 1, - }; - validateIntervalForResample( - timeParams.interval, - timeParams.upsamplingResolution, - INCOMPATIBLE_RESOLUTION_WITH_INTERVAL - ); - const pad = checkForPadding(inputs, timeParams); - validatePadding(pad, timeParams); - const paddedInputs = padInputs(inputs, pad, timeParams); - - const flattenInputs = paddedInputs.reduce( - (acc: PluginParams[], 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. */ - if (index > 0) { - const previousInput = paddedInputs[index - 1]; - const previousInputTimestamp = parseDate(previousInput.timestamp); - - /** Checks for timestamps overlap. */ - if ( - parseDate(previousInput.timestamp).plus({ - seconds: eval(previousInput.duration), - }) > currentMoment - ) { - throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); - } - - const compareableTime = previousInputTimestamp.plus({ - seconds: eval(previousInput.duration), - }); - - const timelineGapSize = currentMoment - .diff(compareableTime) - .as('seconds'); - - validateIntervalForResample( - input.duration, - timeParams.upsamplingResolution, - INCOMPATIBLE_RESOLUTION_WITH_INPUTS - ); - - if (timelineGapSize > 1) { - /** Checks if there is gap in timeline. */ - acc.push( - ...getZeroishInputPerSecondBetweenRange( - { - startDate: compareableTime, - endDate: currentMoment, - timeStep: timeParams.upsamplingResolution, - }, - safeInput - ) - ); - } - } - - /** Break down current observation. */ - for ( - let i = 0; - i <= safeInput.duration - timeParams.upsamplingResolution; - i += timeParams.upsamplingResolution - ) { - const normalizedInput = breakDownInput(safeInput, i, timeParams); - - acc.push(normalizedInput); - } - - return trimInputsByGlobalTimeline(acc, timeParams); }, - [] as PluginParams[] - ); - - const sortedInputs = flattenInputs.sort((a, b) => - parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') - ); - const outputs = resampleInputs(sortedInputs, timeParams) as PluginParams[]; - return outputs.map(output => mapOutputIfNeeded(output, mapping)); - }; - - /** - * Checks if a given duration is compatible with a given timeStep. If not, throws an error - */ - const validateIntervalForResample = ( - duration: number, - timeStep: number, - errorMessage: string - ) => { - if (duration % timeStep !== 0) { - throw new ConfigError(errorMessage); - } - }; - - /** - * Dates are passed to `time-sync` both in ISO 8601 format - * and as a Date object (from the deserialization of a YAML file). - * If the YAML parser fails to identify as a date, it passes as a string. - */ - const parseDate = (date: Date | string) => { - if (!date) { - return DateTime.invalid('Invalid date'); - } - - if (isDate(date)) { - return DateTime.fromJSDate(date); - } - - if (typeof date === 'string') { - return DateTime.fromISO(date); - } - - throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); - }; - - /** - * Validates input parameters. - */ - const validateInput = (input: PluginParams, index: number) => { - const schema = z.object({ - timestamp: z - .string({ - required_error: TIMESTAMP_REQUIRED(index), - }) - .datetime({ - message: INVALID_DATETIME(index), - }) - .or(z.date()), - duration: z.number(), - }); - - const evaluatedInput = evaluateInput(input); - - return validate>(schema, evaluatedInput); - }; - - /** - * Validates config parameters. - */ - const validateConfig = () => { + }, + }, + configValidation: (config: ConfigParams): TimeNormalizerConfig => { if (config === undefined) { throw new ConfigError(INVALID_TIME_NORMALIZATION); } @@ -266,348 +92,487 @@ export const TimeSync = ( }); return validate>(schema, config); - }; - - /** - * Calculates minimal factor. - */ - const convertPerInterval = ( - value: number, - duration: number, - timeStep: number - ) => { - const samplesNumber = duration / timeStep; - return value / samplesNumber; - }; - - /** - * Normalize time per given second. - */ - const normalizeTimePerSecond = ( - currentRoundMoment: Date | string, - i: number - ) => { - const thisMoment = parseDate(currentRoundMoment).startOf('second'); - - return thisMoment.plus({seconds: i}); - }; - - /** - * Breaks down input per minimal time unit. - */ - const breakDownInput = ( - input: PluginParams, - i: number, - params: TimeParams - ) => { - const evaluatedInput = evaluateInput(input); - const metrics = Object.keys(evaluatedInput); - const timeStep = params.upsamplingResolution; - - return metrics.reduce((acc, metric) => { - const aggregationParams = getAggregationInfoFor(metric); - - if (metric === 'timestamp') { - const perSecond = normalizeTimePerSecond(input.timestamp, i); - acc[metric] = perSecond.toUTC().toISO() ?? ''; + }, + inputValidation: (input: PluginParams, _config: any, index?: number) => { + const schema = z.object({ + timestamp: z.string().datetime({}).or(z.date()), + duration: z.number(), + }); - return acc; + return validate>(schema, input, index); + }, + implementation: async ( + inputs: PluginParams[], + config, + mapping?: MappingParams + ) => { + /** + * Checks if a given duration is compatible with a given timeStep. If not, throws an error + */ + const validateIntervalForResample = ( + duration: number, + timeStep: number, + errorMessage: string + ) => { + if (duration % timeStep !== 0) { + throw new ConfigError(errorMessage); } + }; - if (metric === 'duration') { - acc[metric] = timeStep; - - return acc; + /** + * Dates are passed to `time-sync` both in ISO 8601 format + * and as a Date object (from the deserialization of a YAML file). + * If the YAML parser fails to identify as a date, it passes as a string. + */ + const parseDate = (date: Date | string) => { + if (!date) { + return DateTime.invalid('Invalid date'); } - if (aggregationParams.time === 'none') { - acc[metric] = null; - - return acc; + if (isDate(date)) { + return DateTime.fromJSDate(date); } - acc[metric] = - aggregationParams.time === 'sum' - ? convertPerInterval( - evaluatedInput[metric], - evaluatedInput['duration'], - timeStep - ) - : evaluatedInput[metric]; - - return acc; - }, {} as PluginParams); - }; - - /** - * Populates object to fill the gaps in observational timeline using zeroish values. - */ - const fillWithZeroishInput = ( - input: PluginParams, - missingTimestamp: DateTimeMaybeValid, - timeStep: number - ) => { - const metrics = Object.keys(input); - return metrics.reduce((acc, metric) => { - if (metric === 'timestamp') { - acc[metric] = missingTimestamp.startOf('second').toUTC().toISO() ?? ''; - - return acc; + if (typeof date === 'string') { + return DateTime.fromISO(date); } - if (metric === 'duration') { - acc[metric] = timeStep; - - return acc; - } + throw new InvalidDateInInputError(INVALID_DATE_TYPE(date)); + }; - if ( - metric === 'time-reserved' || - (mapping && - mapping['time-reserved'] && - metric === mapping['time-reserved']) - ) { - acc[metric] = acc['duration']; + /** + * Calculates minimal factor. + */ + const convertPerInterval = ( + value: number, + duration: number, + timeStep: number + ) => { + const samplesNumber = duration / timeStep; + return value / samplesNumber; + }; - return acc; - } + /** + * Normalize time per given second. + */ + const normalizeTimePerSecond = ( + currentRoundMoment: Date | string, + i: number + ) => { + const thisMoment = parseDate(currentRoundMoment).startOf('second'); - const aggregationParams = getAggregationInfoFor(metric); + return thisMoment.plus({seconds: i}); + }; - if (aggregationParams.time === 'none') { - acc[metric] = null; + /** + * Breaks down input per minimal time unit. + */ + const breakDownInput = ( + input: PluginParams, + i: number, + params: TimeParams + ) => { + const evaluatedInput = evaluateInput(input); + const metrics = Object.keys(evaluatedInput); + const timeStep = params.upsamplingResolution; + + return metrics.reduce((acc, metric) => { + const aggregationParams = getAggregationInfoFor(metric); - return acc; - } + if (metric === 'timestamp') { + const perSecond = normalizeTimePerSecond(input.timestamp, i); + acc[metric] = perSecond.toUTC().toISO() ?? ''; - if ( - aggregationParams.time === 'avg' || - aggregationParams.time === 'sum' - ) { - acc[metric] = 0; + return acc; + } - return acc; - } + if (metric === 'duration') { + acc[metric] = timeStep; - if (aggregationParams.time === 'copy') { - acc[metric] = input[metric]; - return acc; - } + return acc; + } - return acc; - }, {} as PluginParams); - }; + if (aggregationParams.time === 'none') { + acc[metric] = null; - /** - * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. - */ - const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { - const {start, end} = pad; - const isPaddingNeeded = start || end; + return acc; + } - if (!params.allowPadding && isPaddingNeeded) { - throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); - } - }; + acc[metric] = + aggregationParams.time === 'sum' + ? convertPerInterval( + evaluatedInput[metric], + evaluatedInput['duration'], + timeStep + ) + : evaluatedInput[metric]; - /** - * Checks if padding is needed either at start of the timeline or the end and returns status. - */ - const checkForPadding = ( - inputs: PluginParams[], - params: TimeParams - ): PaddingReceipt => { - const startDiffInSeconds = parseDate(inputs[0].timestamp) - .diff(params.startTime) - .as('seconds'); - - const lastInput = inputs[inputs.length - 1]; - - const endDiffInSeconds = parseDate(lastInput.timestamp) - .plus({second: eval(lastInput.duration)}) - .diff(params.endTime) - .as('seconds'); - return { - start: startDiffInSeconds > 0, - end: endDiffInSeconds < 0, + return acc; + }, {} as PluginParams); }; - }; - - /** - * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. - * For methods is `avg` and `none` calculating average of the frame. - */ - const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => - inputsInTimeslot.reduce((acc, input, index, inputs) => { - const metrics = Object.keys(input); - - metrics.forEach(metric => { - const aggregationParams = getAggregationInfoFor(metric); + /** + * Populates object to fill the gaps in observational timeline using zeroish values. + */ + const fillWithZeroishInput = ( + input: PluginParams, + missingTimestamp: DateTimeMaybeValid, + timeStep: number + ) => { + const metrics = Object.keys(input); + return metrics.reduce((acc, metric) => { if (metric === 'timestamp') { - acc[metric] = inputs[0][metric]; + acc[metric] = + missingTimestamp.startOf('second').toUTC().toISO() ?? ''; - return; + return acc; } if (metric === 'duration') { - aggregationParams.time = 'sum'; + acc[metric] = timeStep; + + return acc; } + if ( + metric === 'time-reserved' || + (mapping && + mapping['time-reserved'] && + metric === mapping['time-reserved']) + ) { + acc[metric] = acc['duration']; + + return acc; + } + + const aggregationParams = getAggregationInfoFor(metric); + if (aggregationParams.time === 'none') { acc[metric] = null; - return; - } - acc[metric] = acc[metric] ?? 0; + return acc; + } - if (aggregationParams.time === 'sum') { - acc[metric] += input[metric]; + if ( + aggregationParams.time === 'avg' || + aggregationParams.time === 'sum' + ) { + acc[metric] = 0; - return; + return acc; } if (aggregationParams.time === 'copy') { acc[metric] = input[metric]; - - return; + return acc; } - /** - * If timeslot contains records more than one, then divide each metric by the timeslot length, - * so that their sum yields the timeslot average. - */ - if ( - inputsInTimeslot.length > 1 && - index === inputsInTimeslot.length - 1 - ) { - acc[metric] /= inputsInTimeslot.length; + return acc; + }, {} as PluginParams); + }; + + /** + * Checks if `error on padding` is enabled and padding is needed. If so, then throws error. + */ + const validatePadding = (pad: PaddingReceipt, params: TimeParams): void => { + const {start, end} = pad; + const isPaddingNeeded = start || end; + + if (!params.allowPadding && isPaddingNeeded) { + throw new InvalidPaddingError(AVOIDING_PADDING_BY_EDGES(start, end)); + } + }; + + /** + * Checks if padding is needed either at start of the timeline or the end and returns status. + */ + const checkForPadding = ( + inputs: PluginParams[], + params: TimeParams + ): PaddingReceipt => { + const startDiffInSeconds = parseDate(inputs[0].timestamp) + .diff(params.startTime) + .as('seconds'); + + const lastInput = inputs[inputs.length - 1]; + + const endDiffInSeconds = parseDate(lastInput.timestamp) + .plus({second: eval(lastInput.duration)}) + .diff(params.endTime) + .as('seconds'); + return { + start: startDiffInSeconds > 0, + end: endDiffInSeconds < 0, + }; + }; + + /** + * Iterates over given inputs frame, meanwhile checking if aggregation method is `sum`, then calculates it. + * For methods is `avg` and `none` calculating average of the frame. + */ + const resampleInputFrame = (inputsInTimeslot: PluginParams[]) => + inputsInTimeslot.reduce((acc, input, index, inputs) => { + const metrics = Object.keys(input); + + metrics.forEach(metric => { + const aggregationParams = getAggregationInfoFor(metric); + + if (metric === 'timestamp') { + acc[metric] = inputs[0][metric]; + + return; + } + + if (metric === 'duration') { + aggregationParams.time = 'sum'; + } + + if (aggregationParams.time === 'none') { + acc[metric] = null; + return; + } + + acc[metric] = acc[metric] ?? 0; + + if (aggregationParams.time === 'sum') { + acc[metric] += input[metric]; + + return; + } + + if (aggregationParams.time === 'copy') { + acc[metric] = input[metric]; + + return; + } + + /** + * If timeslot contains records more than one, then divide each metric by the timeslot length, + * so that their sum yields the timeslot average. + */ + if ( + inputsInTimeslot.length > 1 && + index === inputsInTimeslot.length - 1 + ) { + acc[metric] /= inputsInTimeslot.length; + + return; + } - return; + acc[metric] += input[metric]; + }); + + return acc; + }, {} as PluginParams); + + /** + * Takes each array frame with interval length, then aggregating them together as from units.yaml file. + */ + const resampleInputs = (inputs: PluginParams[], params: TimeParams) => + inputs.reduce((acc: PluginParams[], _input, index, inputs) => { + const frameStart = + (index * params.interval) / params.upsamplingResolution; + const frameEnd = + ((index + 1) * params.interval) / params.upsamplingResolution; + + const inputsFrame = inputs.slice(frameStart, frameEnd); + const resampledInput = resampleInputFrame(inputsFrame); + + /** Checks if resampled input is not empty, then includes in result. */ + if (Object.keys(resampledInput).length > 0) { + acc.push(resampledInput); } - acc[metric] += input[metric]; - }); + return acc; + }, [] as PluginParams[]); + + /** + * Pads zeroish inputs from the beginning or at the end of the inputs if needed. + */ + const padInputs = ( + inputs: PluginParams[], + pad: PaddingReceipt, + params: TimeParams + ): PluginParams[] => { + const {start, end} = pad; + const paddedFromBeginning = []; + + if (start) { + paddedFromBeginning.push( + ...getZeroishInputPerSecondBetweenRange( + { + startDate: params.startTime, + endDate: parseDate(inputs[0].timestamp), + timeStep: params.upsamplingResolution, + }, + inputs[0] + ) + ); + } - return acc; - }, {} as PluginParams); - - /** - * Takes each array frame with interval length, then aggregating them together as from units.yaml file. - */ - const resampleInputs = (inputs: PluginParams[], params: TimeParams) => - inputs.reduce((acc: PluginParams[], _input, index, inputs) => { - const frameStart = - (index * params.interval) / params.upsamplingResolution; - const frameEnd = - ((index + 1) * params.interval) / params.upsamplingResolution; - const inputsFrame = inputs.slice(frameStart, frameEnd); - const resampledInput = resampleInputFrame(inputsFrame); - - /** Checks if resampled input is not empty, then includes in result. */ - if (Object.keys(resampledInput).length > 0) { - acc.push(resampledInput); + const paddedArray = paddedFromBeginning.concat(inputs); + + if (end) { + const lastInput = inputs[inputs.length - 1]; + const lastInputEnd = parseDate(lastInput.timestamp).plus({ + seconds: eval(lastInput.duration), + }); + paddedArray.push( + ...getZeroishInputPerSecondBetweenRange( + { + startDate: lastInputEnd, + endDate: params.endTime, + timeStep: params.upsamplingResolution, + }, + lastInput + ) + ); } - return acc; - }, [] as PluginParams[]); + return paddedArray; + }; - /** - * Pads zeroish inputs from the beginning or at the end of the inputs if needed. - */ - const padInputs = ( - inputs: PluginParams[], - pad: PaddingReceipt, - params: TimeParams - ): PluginParams[] => { - const {start, end} = pad; - const paddedFromBeginning = []; - - if (start) { - paddedFromBeginning.push( - ...getZeroishInputPerSecondBetweenRange( - { - startDate: params.startTime, - endDate: parseDate(inputs[0].timestamp), - timeStep: params.upsamplingResolution, - }, - inputs[0] - ) + /** + * Brakes down the given range by 1 second, and generates zeroish values. + */ + const getZeroishInputPerSecondBetweenRange = ( + params: PluginParams, + input: PluginParams + ) => { + const array: PluginParams[] = []; + validateIntervalForResample( + params.endDate.diff(params.startDate).as('seconds'), + params.timeStep, + INCOMPATIBLE_RESOLUTION_WITH_GAPS + ); + const dateRange = Interval.fromDateTimes( + params.startDate, + params.endDate ); - } - const paddedArray = paddedFromBeginning.concat(inputs); + for (const interval of dateRange.splitBy({second: params.timeStep})) { + array.push( + fillWithZeroishInput( + input, + // as far as I can tell, start will never be null + // because if we pass an invalid start/endDate to + // Interval, we get a zero length array as the range + interval.start || DateTime.invalid('not expected - start is null'), + params.timeStep + ) + ); + } - if (end) { - const lastInput = inputs[inputs.length - 1]; - const lastInputEnd = parseDate(lastInput.timestamp).plus({ - seconds: eval(lastInput.duration), - }); - paddedArray.push( - ...getZeroishInputPerSecondBetweenRange( - { - startDate: lastInputEnd, - endDate: params.endTime, - timeStep: params.upsamplingResolution, - }, - lastInput - ) - ); - } + return array; + }; - return paddedArray; - }; + /* + * Checks if input's timestamp is included in global specified period then leaves it, otherwise. + */ + const trimInputsByGlobalTimeline = ( + inputs: PluginParams[], + params: TimeParams + ): PluginParams[] => + inputs.reduce((acc: PluginParams[], item) => { + const {timestamp} = item; - /** - * Brakes down the given range by 1 second, and generates zeroish values. - */ - const getZeroishInputPerSecondBetweenRange = ( - params: PluginParams, - input: PluginParams - ) => { - const array: PluginParams[] = []; + if ( + parseDate(timestamp) >= params.startTime && + parseDate(timestamp) <= params.endTime + ) { + acc.push(item); + } + + return acc; + }, [] as PluginParams[]); + + /** Implementation */ + const timeParams = { + startTime: DateTime.fromISO(config['start-time'] as string), + endTime: DateTime.fromISO(config['end-time'] as string), + interval: config.interval, + allowPadding: config['allow-padding'], + upsamplingResolution: config['upsampling-resolution'] + ? config['upsampling-resolution'] + : 1, + }; validateIntervalForResample( - params.endDate.diff(params.startDate).as('seconds'), - params.timeStep, - INCOMPATIBLE_RESOLUTION_WITH_GAPS + timeParams.interval, + timeParams.upsamplingResolution, + INCOMPATIBLE_RESOLUTION_WITH_INTERVAL ); - const dateRange = Interval.fromDateTimes(params.startDate, params.endDate); - - for (const interval of dateRange.splitBy({second: params.timeStep})) { - array.push( - fillWithZeroishInput( - input, - // as far as I can tell, start will never be null - // because if we pass an invalid start/endDate to - // Interval, we get a zero length array as the range - interval.start || DateTime.invalid('not expected - start is null'), - params.timeStep - ) - ); - } + const pad = checkForPadding(inputs, timeParams); + validatePadding(pad, timeParams); + const paddedInputs = padInputs(inputs, pad, timeParams); - return array; - }; + const flattenInputs = paddedInputs.reduce( + (acc: PluginParams[], input, index) => { + const currentMoment = parseDate(input.timestamp); - /* - * Checks if input's timestamp is included in global specified period then leaves it, otherwise. - */ - const trimInputsByGlobalTimeline = ( - inputs: PluginParams[], - params: TimeParams - ): PluginParams[] => - inputs.reduce((acc: PluginParams[], item) => { - const {timestamp} = item; - - if ( - parseDate(timestamp) >= params.startTime && - parseDate(timestamp) <= params.endTime - ) { - acc.push(item); - } + /** Checks if not the first input, then check consistency with previous ones. */ + if (index > 0) { + const previousInput = paddedInputs[index - 1]; + const previousInputTimestamp = parseDate(previousInput.timestamp); + + /** Checks for timestamps overlap. */ + if ( + parseDate(previousInput.timestamp).plus({ + seconds: eval(previousInput.duration), + }) > currentMoment + ) { + throw new InvalidInputError(INVALID_OBSERVATION_OVERLAP); + } + + const compareableTime = previousInputTimestamp.plus({ + seconds: eval(previousInput.duration), + }); + + const timelineGapSize = currentMoment + .diff(compareableTime) + .as('seconds'); + + validateIntervalForResample( + input.duration, + timeParams.upsamplingResolution, + INCOMPATIBLE_RESOLUTION_WITH_INPUTS + ); + + if (timelineGapSize > 1) { + /** Checks if there is gap in timeline. */ + acc.push( + ...getZeroishInputPerSecondBetweenRange( + { + startDate: compareableTime, + endDate: currentMoment, + timeStep: timeParams.upsamplingResolution, + }, + input + ) + ); + } + } + + /** Break down current observation. */ + for ( + let i = 0; + i <= input.duration - timeParams.upsamplingResolution; + i += timeParams.upsamplingResolution + ) { + const normalizedInput = breakDownInput(input, i, timeParams); + + acc.push(normalizedInput); + } - return acc; - }, [] as PluginParams[]); + return trimInputsByGlobalTimeline(acc, timeParams); + }, + [] as PluginParams[] + ); + + const sortedInputs = flattenInputs.sort((a, b) => + parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') + ); - return {metadata, execute}; -}; + const a = resampleInputs(sortedInputs, timeParams) as PluginParams[]; + return a; + }, +}); From 23e074254854deac1aaaa881883cc1f1c8f6e6ce Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 30 Sep 2024 10:17:54 +0400 Subject: [PATCH 803/863] test(builtins): fix tests for `time-sync` and `sci-embodied` plugins --- .../if-run/builtins/sci-embodied.test.ts | 50 +++++++++++++++++-- .../if-run/builtins/time-sync.test.ts | 6 +-- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/__tests__/if-run/builtins/sci-embodied.test.ts b/src/__tests__/if-run/builtins/sci-embodied.test.ts index 64c6afc03..33261ea30 100644 --- a/src/__tests__/if-run/builtins/sci-embodied.test.ts +++ b/src/__tests__/if-run/builtins/sci-embodied.test.ts @@ -4,7 +4,7 @@ import {SciEmbodied} from '../../../if-run/builtins/sci-embodied'; const {InputValidationError} = ERRORS; -describe.skip('builtins/sci-embodied:', () => { +describe('builtins/sci-embodied:', () => { describe('SciEmbodied: ', () => { const parametersMetadata = { inputs: {}, @@ -43,12 +43,22 @@ describe.skip('builtins/sci-embodied:', () => { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 2, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, 'embodied-carbon': 31.39269406392694, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 4, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, 'embodied-carbon': 37.10045662100457, }, ]); @@ -63,6 +73,7 @@ describe.skip('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, + 'device/cpu-cores': 1, }, { timestamp: '2021-01-01T00:00:00Z', @@ -79,12 +90,23 @@ describe.skip('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, + 'device/cpu-cores': 1, 'embodied-carbon': 28.538812785388128, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, 'device/cpu-cores': 2, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, 'embodied-carbon': 31.39269406392694, }, ]); @@ -103,7 +125,6 @@ describe.skip('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - 'device/cpu-cores': 2, }, ]; @@ -115,12 +136,23 @@ describe.skip('builtins/sci-embodied:', () => { { timestamp: '2021-01-01T00:00:00Z', duration: 3600, + vCPUs: 1, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, carbon: 28.538812785388128, }, { timestamp: '2021-01-01T00:00:00Z', duration: 3600, - 'device/cpu-cores': 2, + vCPUs: 1, + memory: 16, + gpu: 0, + hdd: 0, + ssd: 0, + 'usage-ratio': 1, carbon: 28.538812785388128, }, ]); @@ -146,7 +178,7 @@ describe.skip('builtins/sci-embodied:', () => { } catch (error) { expect(error).toStrictEqual( new InputValidationError( - '"vCPUs" parameter is expected number, received string. Error code: invalid_type.' + '"vCPUs" parameter is expected number, received string at index 0. Error code: invalid_type.' ) ); expect(error).toBeInstanceOf(InputValidationError); @@ -191,6 +223,11 @@ describe.skip('builtins/sci-embodied:', () => { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 2, + gpu: 0, + hdd: 0, + memory: 16, + ssd: 0, + 'usage-ratio': 1, 'embodied-carbon': 47.945205479452056, 'mock-param': 150000, }, @@ -198,6 +235,11 @@ describe.skip('builtins/sci-embodied:', () => { timestamp: '2021-01-01T00:00:00Z', duration: 3600, vCPUs: 4, + gpu: 0, + hdd: 0, + memory: 16, + ssd: 0, + 'usage-ratio': 1, 'embodied-carbon': 52.51141552511416, 'mock-param': 100000, }, diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 0228f4da6..9994dace5 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -704,7 +704,7 @@ describe('builtins/time-sync:', () => { timestamp: '2023-12-12T00:00:00.000Z', duration: 5, 'resources-total': 10, - 'time-allocated': 3, + 'time-allocated': 3.2, }, { timestamp: '2023-12-12T00:00:05.000Z', @@ -902,7 +902,7 @@ describe('builtins/time-sync:', () => { expect(DateTime.fromISO(result[0].timestamp).offset === 0); }); - it.skip('successfully executes when the `duration` contains an arithmetic expression.', () => { + it('successfully executes when the `duration` contains an arithmetic expression.', async () => { expect.assertions(1); const basicConfig = { @@ -913,7 +913,7 @@ describe('builtins/time-sync:', () => { }; const timeModel = TimeSync(basicConfig, parametersMetadata, {}); - const result = timeModel.execute([ + const result = await timeModel.execute([ { timestamp: '2023-12-12T00:00:00.000Z', duration: 3, From 93f6b5fb8ec6ccacd6be12f33f9c349bc8100c5a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 30 Sep 2024 10:19:24 +0400 Subject: [PATCH 804/863] fix(builtins): fix arithmetic feature logic in the coeffient and sci-embodied pluings --- src/if-run/builtins/coefficient/index.ts | 7 ++- src/if-run/builtins/sci-embodied/index.ts | 66 ++++++++++++++++++----- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index eb62c07f2..0e80be3e7 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -1,8 +1,8 @@ import {z, ZodType} from 'zod'; +import {ERRORS, validateArithmeticExpression} from '@grnsft/if-core/utils'; import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; -import {ERRORS} from '@grnsft/if-core/utils'; import {validate} from '../../../common/util/validations'; @@ -22,7 +22,10 @@ export const Coefficient = PluginFactory({ } const configSchema = z.object({ - coefficient: z.number(), + coefficient: z.preprocess( + value => validateArithmeticExpression('coefficient', value, 'number'), + z.number() + ), 'input-parameter': z.string().min(1), 'output-parameter': z.string().min(1), }); diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index 187ad6c43..f48af0781 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -1,5 +1,6 @@ import {z} from 'zod'; +import {validateArithmeticExpression} from '@grnsft/if-core/utils'; import {ConfigParams, PluginParams} from '@grnsft/if-core/types'; import {PluginFactory} from '@grnsft/if-core/interfaces'; @@ -77,18 +78,59 @@ export const SciEmbodied = PluginFactory({ }, }, configValidation: z.object({ - 'baseline-vcpus': z.number().gte(0).default(1), - 'baseline-memory': z.number().gte(0).default(16), - 'baseline-emissions': z.number().gte(0).default(1000000), - lifespan: z.number().gt(0).default(126144000), - 'vcpu-emissions-constant': z.number().gte(0).default(100000), - 'memory-emissions-constant': z - .number() - .gte(0) - .default(533 / 384), - 'ssd-emissions-constant': z.number().gte(0).default(50000), - 'hdd-emissions-constant': z.number().gte(0).default(100000), - 'gpu-emissions-constant': z.number().gte(0).default(150000), + 'baseline-vcpus': z.preprocess( + value => validateArithmeticExpression('baseline-vcpus', value, 'number'), + z.number().gte(0).default(1) + ), + 'baseline-memory': z.preprocess( + value => validateArithmeticExpression('baseline-memory', value, 'number'), + z.number().gte(0).default(16) + ), + 'baseline-emissions': z.preprocess( + value => + validateArithmeticExpression('baseline-emissions', value, 'number'), + z.number().gte(0).default(1000000) + ), + lifespan: z.preprocess( + value => validateArithmeticExpression('lifespan', value, 'number'), + z.number().gt(0).default(126144000) + ), + 'vcpu-emissions-constant': z.preprocess( + value => + validateArithmeticExpression( + 'vcpu-emissions-constant', + value, + 'number' + ), + z.number().gte(0).default(100000) + ), + 'memory-emissions-constant': z.preprocess( + value => + validateArithmeticExpression( + 'memory-emissions-constant', + value, + 'number' + ), + z + .number() + .gte(0) + .default(533 / 384) + ), + 'ssd-emissions-constant': z.preprocess( + value => + validateArithmeticExpression('ssd-emissions-constant', value, 'number'), + z.number().gte(0).default(50000) + ), + 'hdd-emissions-constant': z.preprocess( + value => + validateArithmeticExpression('hdd-emissions-constant', value, 'number'), + z.number().gte(0).default(100000) + ), + 'gpu-emissions-constant': z.preprocess( + value => + validateArithmeticExpression('gpu-emissions-constant', value, 'number'), + z.number().gte(0).default(150000) + ), 'output-parameter': z.string().optional(), }), inputValidation: z.object({ From 01646f1d12aac3d9782a7d7478b02c0063442962 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 30 Sep 2024 13:23:16 +0400 Subject: [PATCH 805/863] revert(types): remove time sync --- src/if-run/types/time-sync.ts | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/if-run/types/time-sync.ts diff --git a/src/if-run/types/time-sync.ts b/src/if-run/types/time-sync.ts deleted file mode 100644 index c2674b652..000000000 --- a/src/if-run/types/time-sync.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {DateTime} from 'luxon'; - -export type TimeNormalizerConfig = { - 'start-time': Date | string; - 'end-time': Date | string; - interval: number; - 'allow-padding': boolean; - 'upsampling-resolution'?: number; -}; - -export type PaddingReceipt = { - start: boolean; - end: boolean; -}; - -export type TimeParams = { - startTime: DateTime; - endTime: DateTime; - interval: number; - allowPadding: boolean; - upsamplingResolution: number; -}; From 4f7361e0612bd67f3dfb0978070ee4b73114fa49 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 30 Sep 2024 13:24:12 +0400 Subject: [PATCH 806/863] fix(builtins): minor issues in time sync, import types from if-core --- src/if-run/builtins/time-sync/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 20d5fee24..40fd6f6ab 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -8,10 +8,10 @@ import { PaddingReceipt, MappingParams, ConfigParams, + TimeParams, + TimeNormalizerConfig, } from '@grnsft/if-core/types'; -import {TimeParams, TimeNormalizerConfig} from '../../types/time-sync'; - import {validate} from '../../../common/util/validations'; import {STRINGS} from '../../config'; @@ -149,6 +149,7 @@ export const TimeSync = PluginFactory({ timeStep: number ) => { const samplesNumber = duration / timeStep; + return value / samplesNumber; }; @@ -572,7 +573,6 @@ export const TimeSync = PluginFactory({ parseDate(a.timestamp).diff(parseDate(b.timestamp)).as('seconds') ); - const a = resampleInputs(sortedInputs, timeParams) as PluginParams[]; - return a; + return resampleInputs(sortedInputs, timeParams) as PluginParams[]; }, }); From 3cc04726cb562e5e3e359d0092e79f1bd1a44c23 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 30 Sep 2024 13:26:28 +0400 Subject: [PATCH 807/863] feat(builtins): drop empty metadata objects --- src/if-run/builtins/coefficient/index.ts | 4 ---- src/if-run/builtins/copy-param/index.ts | 4 ---- src/if-run/builtins/csv-lookup/index.ts | 4 ---- src/if-run/builtins/divide/index.ts | 4 ---- src/if-run/builtins/exponent/index.ts | 4 ---- src/if-run/builtins/interpolation/index.ts | 4 ---- src/if-run/builtins/mock-observations/index.ts | 4 ---- src/if-run/builtins/multiply/index.ts | 4 ---- src/if-run/builtins/regex/index.ts | 4 ---- src/if-run/builtins/shell/index.ts | 4 ---- src/if-run/builtins/subtract/index.ts | 4 ---- src/if-run/builtins/sum/index.ts | 4 ---- src/if-run/builtins/time-converter/index.ts | 4 ---- 13 files changed, 52 deletions(-) diff --git a/src/if-run/builtins/coefficient/index.ts b/src/if-run/builtins/coefficient/index.ts index 0e80be3e7..99895482c 100644 --- a/src/if-run/builtins/coefficient/index.ts +++ b/src/if-run/builtins/coefficient/index.ts @@ -12,10 +12,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Coefficient = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/copy-param/index.ts b/src/if-run/builtins/copy-param/index.ts index bdf777f0a..3e0dfb761 100644 --- a/src/if-run/builtins/copy-param/index.ts +++ b/src/if-run/builtins/copy-param/index.ts @@ -21,10 +21,6 @@ const {MISSING_CONFIG} = STRINGS; */ export const Copy = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/csv-lookup/index.ts b/src/if-run/builtins/csv-lookup/index.ts index d11bac467..08f7760c6 100644 --- a/src/if-run/builtins/csv-lookup/index.ts +++ b/src/if-run/builtins/csv-lookup/index.ts @@ -28,10 +28,6 @@ const { } = ERRORS; export const CSVLookup = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/divide/index.ts b/src/if-run/builtins/divide/index.ts index 343033d9b..9252bc305 100644 --- a/src/if-run/builtins/divide/index.ts +++ b/src/if-run/builtins/divide/index.ts @@ -12,10 +12,6 @@ const {MissingInputDataError, ConfigError} = ERRORS; const {MISSING_INPUT_DATA, ZERO_DIVISION, MISSING_CONFIG} = STRINGS; export const Divide = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/exponent/index.ts b/src/if-run/builtins/exponent/index.ts index 7f2758f98..464ce9367 100644 --- a/src/if-run/builtins/exponent/index.ts +++ b/src/if-run/builtins/exponent/index.ts @@ -12,10 +12,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Exponent = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index b0e1886a1..30226e5a6 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -15,10 +15,6 @@ const {X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE, MISSING_CONFIG} = const {ConfigError} = ERRORS; export const Interpolation = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/mock-observations/index.ts b/src/if-run/builtins/mock-observations/index.ts index b58b75e73..138386940 100644 --- a/src/if-run/builtins/mock-observations/index.ts +++ b/src/if-run/builtins/mock-observations/index.ts @@ -22,10 +22,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const MockObservations = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/multiply/index.ts b/src/if-run/builtins/multiply/index.ts index 16b6f21d8..544b87add 100644 --- a/src/if-run/builtins/multiply/index.ts +++ b/src/if-run/builtins/multiply/index.ts @@ -12,10 +12,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Multiply = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/regex/index.ts b/src/if-run/builtins/regex/index.ts index 6aabd521b..ed904d25f 100644 --- a/src/if-run/builtins/regex/index.ts +++ b/src/if-run/builtins/regex/index.ts @@ -12,10 +12,6 @@ const {MissingInputDataError, ConfigError, RegexMismatchError} = ERRORS; const {MISSING_CONFIG, MISSING_INPUT_DATA, REGEX_MISMATCH} = STRINGS; export const Regex = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/shell/index.ts b/src/if-run/builtins/shell/index.ts index 9995a1ba1..a6752f3a0 100644 --- a/src/if-run/builtins/shell/index.ts +++ b/src/if-run/builtins/shell/index.ts @@ -14,10 +14,6 @@ const {ProcessExecutionError, ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Shell = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/subtract/index.ts b/src/if-run/builtins/subtract/index.ts index 41a42f934..3bd852b0a 100644 --- a/src/if-run/builtins/subtract/index.ts +++ b/src/if-run/builtins/subtract/index.ts @@ -12,10 +12,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const Subtract = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); diff --git a/src/if-run/builtins/sum/index.ts b/src/if-run/builtins/sum/index.ts index fabeb890b..5081f0c1d 100644 --- a/src/if-run/builtins/sum/index.ts +++ b/src/if-run/builtins/sum/index.ts @@ -6,10 +6,6 @@ import {PluginParams, ConfigParams} from '@grnsft/if-core/types'; import {validate} from '../../../common/util/validations'; export const Sum = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), diff --git a/src/if-run/builtins/time-converter/index.ts b/src/if-run/builtins/time-converter/index.ts index dc6a84d7d..f50c51614 100644 --- a/src/if-run/builtins/time-converter/index.ts +++ b/src/if-run/builtins/time-converter/index.ts @@ -14,10 +14,6 @@ const {ConfigError} = ERRORS; const {MISSING_CONFIG} = STRINGS; export const TimeConverter = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: (config: ConfigParams) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); From bea643bcb14f5e4028e4777b2d5b01b35bc1f262 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 30 Sep 2024 17:18:15 +0400 Subject: [PATCH 808/863] feat(package): update if-core dependency version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3aa9582e4..874b062db 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.23", + "@grnsft/if-core": "^0.0.24", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.23", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.23.tgz", - "integrity": "sha512-lP+ViXjlhcTSosomLGOAO4PM8Ug5qtb5LEdOouUvg01PoVUJwLLf/MJgYxCegP8maAMCv1n4s1uPx15ffZqMXg==", + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.24.tgz", + "integrity": "sha512-AtufC8XKEKxotYlz4r0635j6tGpa6X7yii+HwCb/Tak3yuftTQVX0VKrhGJpWH0z19BOjmiuKhnucV+jE9FnrQ==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 8386c8f10..e2b508f5d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.23", + "@grnsft/if-core": "^0.0.24", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From b8892856d534200694187a2197dc74ca275ea767 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 30 Sep 2024 18:00:11 +0400 Subject: [PATCH 809/863] feat(doc): drop empty metadata from example --- Refactor-migration-guide.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index b5608ff42..00a199cc5 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -238,10 +238,6 @@ Here’s a minimal example of a plugin that sums inputs as defined in the config ```ts // Here's the function definition! export const Sum = PluginFactory({ - metadata: { - inputs: {}, - outputs: {}, - }, configValidation: z.object({ 'input-parameters': z.array(z.string()), 'output-parameter': z.string().min(1), From ef18aaae39b2025ebfe735e365921a14aa480884 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:44:38 +0400 Subject: [PATCH 810/863] revert(types): drop interface --- src/if-run/types/interface.ts | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 src/if-run/types/interface.ts diff --git a/src/if-run/types/interface.ts b/src/if-run/types/interface.ts deleted file mode 100644 index 3884305a2..000000000 --- a/src/if-run/types/interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {ExecutePlugin} from '@grnsft/if-core/types'; - -export type PluginInterface = ExecutePlugin; - -export const isExecute = (plugin: ExecutePlugin): plugin is ExecutePlugin => - (plugin as ExecutePlugin).metadata.kind === 'execute'; From 72245f21f75725d15f0509424ea9316ad73cb34f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:48:27 +0400 Subject: [PATCH 811/863] feat(doc): update github processes --- github-processes.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/github-processes.md b/github-processes.md index 81f2301d5..032115558 100644 --- a/github-processes.md +++ b/github-processes.md @@ -3,24 +3,18 @@ - [`if`](https://github.com/Green-Software-Foundation/if) - source code for the IF +- [`if-core`](https://github.com/Green-Software-Foundation/if-core) + - helper types, interfaces and utilities for IF and plugin development - [`if-plugins`](https://github.com/Green-Software-Foundation/if-plugins) **DEPRECATED** - source code for standard library of plugins - IF core team commit to maintaining these plugins -- [`if-unofficial-plugins`](https://github.com/Green-Software-Foundation/if-unofficial-plugins) +- [`if-unofficial-plugins`](https://github.com/Green-Software-Foundation/if-unofficial-plugins) **DEPRECATED** - source code for plugins relying on third-party data/APIs - intended to be deprecated and removed in mid-term future - plugins in this repo should be handed over to relevant organizations to maintain - [`if-plugin-template`](https://github.com/Green-Software-Foundation/if-plugin-template) - template for new plugins - intended for builders to bootstrap IF-compatible plugin development -- [`if-standards`](https://github.com/Green-Software-Foundation/if-standards) - - not currently used, but intended to be the home of params.ts - - will have a dedicated discussion board and governance to set IF standards -- [`if-exhaust plugins`](https://github.com/Green-Software-Foundation/if-exhaust-plugins) - - not currently used - - intended to become a separate repo just for exhaust plugins - - requires strict rules from if - ## Branch names and purposes From 8b4a7eb8191ca47d2edfa910d902d8d24e68860d Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:50:13 +0400 Subject: [PATCH 812/863] revert(types): drop exhaust plugin interface --- src/if-run/types/exhaust-plugin-interface.ts | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/if-run/types/exhaust-plugin-interface.ts diff --git a/src/if-run/types/exhaust-plugin-interface.ts b/src/if-run/types/exhaust-plugin-interface.ts deleted file mode 100644 index de6183842..000000000 --- a/src/if-run/types/exhaust-plugin-interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {Context} from '../../common/types/manifest'; - -export interface ExhaustPluginInterface { - /** - * Execute exhaust based on `context` and `tree`, produce output to a file in `outputPath`. - */ - execute(tree: any, context: Context, outputPath?: string): void; -} From 1d3b7d0e2590c5549a343991945ec3be77723414 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:50:54 +0400 Subject: [PATCH 813/863] feat(util): use plugin interface from if core --- src/if-run/util/plugin-storage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/util/plugin-storage.ts b/src/if-run/util/plugin-storage.ts index ca2907fcc..06caac434 100644 --- a/src/if-run/util/plugin-storage.ts +++ b/src/if-run/util/plugin-storage.ts @@ -1,9 +1,9 @@ import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginInterface} from '@grnsft/if-core/types'; import {STRINGS} from '../config'; import {PluginStorage} from '../types/plugin-storage'; -import {PluginInterface} from '../types/interface'; const {PluginInitializationError} = ERRORS; const {NOT_INITALIZED_PLUGIN} = STRINGS; From 83c0263d75b7bc2f364a5a33a76d68c0f10c8d7c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:51:28 +0400 Subject: [PATCH 814/863] revert(util): drop unused store aggregation methods --- src/if-run/util/helpers.ts | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/if-run/util/helpers.ts b/src/if-run/util/helpers.ts index d9520b0d5..4a578955b 100644 --- a/src/if-run/util/helpers.ts +++ b/src/if-run/util/helpers.ts @@ -1,9 +1,6 @@ import {ERRORS} from '@grnsft/if-core/utils'; import {logger} from '../../common/util/logger'; -import {GlobalPlugins} from '../../common/types/manifest'; -import {PluginStorageInterface} from '../types/plugin-storage'; -import {storeAggregationMetrics} from '../lib/aggregate'; import {STRINGS} from '../config'; @@ -42,34 +39,3 @@ export const mergeObjects = (defaults: any, input: any) => { return merged; }; - -/** - * Stores `'aggregation-method'` of the plugins in the pipeline. - */ -export const storeAggregationMethods = ( - plugins: GlobalPlugins, - pluginStorage: PluginStorageInterface -) => { - Object.keys(plugins).forEach(pluginName => { - const plugin = pluginStorage.get(pluginName); - - if ('inputs' in plugin.metadata || 'outputs' in plugin.metadata) { - const pluginParameters = { - ...plugin.metadata.inputs, - ...plugin.metadata.outputs, - }; - - Object.entries(pluginParameters).forEach( - ([parameterName, parameterMetadata]) => { - const {'aggregation-method': aggregationMethod} = parameterMetadata; - - if (aggregationMethod) { - const metrics = {[parameterName]: aggregationMethod}; - - storeAggregationMetrics(metrics); - } - } - ); - } - }); -}; From 19cb96dfd5196fcec5bae629032899f847aaf9c5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:52:28 +0400 Subject: [PATCH 815/863] refactor(util): rename inputs to outputs in aggregation helper --- src/if-run/util/aggregation-helper.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index 211364f1a..defa71726 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -13,25 +13,25 @@ const {AGGREGATION_TIME_METRICS} = CONFIG; /** * Aggregates child node level metrics. Appends aggregation additional params to metrics. - * Otherwise iterates over inputs by aggregating per given `metrics`. + * Otherwise iterates over outputs by aggregating per given `metrics`. */ -export const aggregateInputsIntoOne = ( - inputs: PluginParams[], +export const aggregateOutputsIntoOne = ( + outputs: PluginParams[], metrics: string[], isTemporal?: boolean ) => { const metricsWithTime = metrics.concat(AGGREGATION_TIME_METRICS); - return inputs.reduce((acc, input, index) => { + return outputs.reduce((acc, output, index) => { for (const metric of metricsWithTime) { - if (!(metric in input)) { + if (!(metric in output)) { throw new MissingAggregationParamError(METRIC_MISSING(metric, index)); } /** Checks if metric is timestamp or duration, then adds to aggregated value. */ if (AGGREGATION_TIME_METRICS.includes(metric)) { if (isTemporal) { - acc[metric] = input[metric]; + acc[metric] = output[metric]; } } else { const aggregationParams = getAggregationInfoFor(metric); @@ -43,17 +43,17 @@ export const aggregateInputsIntoOne = ( } if (aggregationParams[aggregationType] === 'copy') { - acc[metric] = input[metric]; + acc[metric] = output[metric]; return acc; } acc[metric] = acc[metric] ?? 0; - acc[metric] += parseFloat(input[metric]); + acc[metric] += parseFloat(output[metric]); /** Checks for the last iteration. */ - if (index === inputs.length - 1) { + if (index === outputs.length - 1) { if (aggregationParams[aggregationType] === 'avg') { - acc[metric] /= inputs.length; + acc[metric] /= outputs.length; } } } From 0607f3e71f15ce5706a8f74c3b1a37b03349ce90 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:53:09 +0400 Subject: [PATCH 816/863] refactor(types): use plugin interface from if core in plugin storage --- src/if-run/types/plugin-storage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/types/plugin-storage.ts b/src/if-run/types/plugin-storage.ts index 0d3d865c5..70a317483 100644 --- a/src/if-run/types/plugin-storage.ts +++ b/src/if-run/types/plugin-storage.ts @@ -1,5 +1,5 @@ +import {PluginInterface} from '@grnsft/if-core/types'; import {pluginStorage} from '../util/plugin-storage'; -import {PluginInterface} from './interface'; export type PluginStorage = { [key: string]: PluginInterface; From b4aa9de68e38f7b0412349e4b8b0b2a63937cded Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:53:49 +0400 Subject: [PATCH 817/863] refactor(lib): use plugin interface from if core in initalize --- src/if-run/lib/initialize.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 9239fe3d1..554b4f9c0 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -1,6 +1,7 @@ import * as path from 'node:path'; import {ERRORS} from '@grnsft/if-core/utils'; +import {PluginInterface} from '@grnsft/if-core/types'; import {logger} from '../../common/util/logger'; import {memoizedLog} from '../util/log-memoize'; @@ -8,7 +9,6 @@ import {pluginStorage} from '../util/plugin-storage'; import {CONFIG, STRINGS} from '../config'; -import {PluginInterface} from '../types/interface'; import {Context, PluginOptions} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; import {storeAggregationMetrics} from './aggregate'; @@ -42,7 +42,7 @@ const importModuleFrom = async (path: string) => { }; /** - * Imports `module` from given `path`, then checks if it's `ModelPluginInterface` extension. + * Imports `module` from given `path` and returns requested `method`. */ const importAndVerifyModule = async (method: string, path: string) => { const pluginModule = await importModuleFrom(path); From 19e480f59f48446e7513ec3deca4064ec9fbf403 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:54:39 +0400 Subject: [PATCH 818/863] refactor(lib): drop isExecute type guard from compute --- src/if-run/lib/compute.ts | 69 +++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 1e29bdc68..5e73cbbb4 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -11,7 +11,6 @@ import {mergeObjects} from '../util/helpers'; import {STRINGS} from '../config/strings'; import {ComputeParams, Node, PhasedPipeline} from '../types/compute'; -import {isExecute} from '../types/interface'; const { MERGING_DEFAULTS_WITH_INPUT_DATA, @@ -53,6 +52,19 @@ const mergeDefaults = ( return defaults ? [defaults] : []; }; +/** + * Warns if the `config` is provided in the manifest. + */ +const warnIfConfigProvided = (node: any) => { + if ('config' in node) { + const plugins = Object.keys(node.config || {}); + const joinedPlugins = plugins.join(', '); + const isMore = plugins.length > 1; + + logger.warn(CONFIG_WARN(joinedPlugins, isMore)); + } +}; + /** * 1. If the node has it's own pipeline, defaults or config then use that, * otherwise use whatever has been passed down from further up the tree. @@ -113,17 +125,15 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { const plugin = params.pluginStorage.get(pluginName); const nodeConfig = config && config[pluginName]; - if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); - node.inputs = inputStorage; - - if (params.context.explainer) { - addExplainData({ - pluginName, - metadata: plugin.metadata, - pluginData: params.context.initialize!.plugins[pluginName], - }); - } + inputStorage = await plugin.execute(inputStorage, nodeConfig); + node.inputs = inputStorage; + + if (params.context.explainer) { + addExplainData({ + pluginName, + metadata: plugin.metadata, + pluginData: params.context.initialize!.plugins[pluginName], + }); } } } @@ -164,6 +174,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { */ if ((noFlags || params.compute) && pipelineCopy.compute) { const originalOutputs = params.append ? node.outputs || [] : []; + while (pipelineCopy.compute.length !== 0) { const pluginName = pipelineCopy.compute.shift() as string; const plugin = params.pluginStorage.get(pluginName); @@ -172,19 +183,17 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); debugLogger.setExecutingPluginName(pluginName); - if (isExecute(plugin)) { - inputStorage = await plugin.execute(inputStorage, nodeConfig); - debugLogger.setExecutingPluginName(); + inputStorage = await plugin.execute(inputStorage, nodeConfig); + debugLogger.setExecutingPluginName(); - node.outputs = inputStorage; + node.outputs = inputStorage; - if (params.context.explainer) { - addExplainData({ - pluginName, - metadata: plugin.metadata, - pluginData: params.context.initialize!.plugins[pluginName], - }); - } + if (params.context.explainer) { + addExplainData({ + pluginName, + metadata: plugin.metadata, + pluginData: params.context.initialize!.plugins[pluginName], + }); } } @@ -192,20 +201,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { node.outputs = originalOutputs.concat(node.outputs || []); } } - console.debug('\n'); -}; - -/** - * Warns if the `config` is provided in the manifest. - */ -const warnIfConfigProvided = (node: any) => { - if ('config' in node) { - const plugins = Object.keys(node.config || {}); - const joinedPlugins = plugins.join(', '); - const isMore = plugins.length > 1; - logger.warn(CONFIG_WARN(joinedPlugins, isMore)); - } + console.debug('\n'); }; /** From 8e9b1c3c48fe13cbeaf4b7998ea38fe986a7590b Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:55:13 +0400 Subject: [PATCH 819/863] refactor(lib): rename aggregate inputs into one function in aggregate --- src/if-run/lib/aggregate.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/if-run/lib/aggregate.ts b/src/if-run/lib/aggregate.ts index bee7d3031..ef3142b38 100644 --- a/src/if-run/lib/aggregate.ts +++ b/src/if-run/lib/aggregate.ts @@ -9,7 +9,7 @@ import { AggregationMetricsWithMethod, } from '../../common/types/manifest'; -import {aggregateInputsIntoOne} from '../util/aggregation-helper'; +import {aggregateOutputsIntoOne} from '../util/aggregation-helper'; import {memoizedLog} from '../util/log-memoize'; import {STRINGS} from '../config/strings'; @@ -44,7 +44,7 @@ const temporalAggregation = (node: any, metrics: string[]) => { for (let i = 0; i < values[0].outputs.length; i++) { const ithSliceOfOutputs = getIthElementsFromChildren(node.children, i); - outputs.push(aggregateInputsIntoOne(ithSliceOfOutputs, metrics, true)); + outputs.push(aggregateOutputsIntoOne(ithSliceOfOutputs, metrics, true)); } return outputs; @@ -76,14 +76,14 @@ const aggregateNode = (node: any, aggregationParams: AggregationParamsSure) => { if (!node.children) { /** `time` aggregation is the new name of `horizontal`. */ if (type === 'horizontal' || type === 'time' || type === 'both') { - node.aggregated = aggregateInputsIntoOne(node.outputs, metrics); + node.aggregated = aggregateOutputsIntoOne(node.outputs, metrics); } } else { /** `component` aggregation is the new name of `vertical`. */ if (type === 'vertical' || type === 'component' || type === 'both') { const outputs = temporalAggregation(node, metrics); node.outputs = outputs; - node.aggregated = aggregateInputsIntoOne(outputs, metrics); + node.aggregated = aggregateOutputsIntoOne(outputs, metrics); } } }; From d3a44636ba2255379874f10746254fe3d6424ba3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 17:55:55 +0400 Subject: [PATCH 820/863] fix(util): check args before usage in debug logger --- src/common/util/debug-logger.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/util/debug-logger.ts b/src/common/util/debug-logger.ts index 488903c96..9caab3083 100644 --- a/src/common/util/debug-logger.ts +++ b/src/common/util/debug-logger.ts @@ -111,7 +111,8 @@ const debugLog = (level: LogLevel, args: any[], debugMode: boolean) => { const date = new Date().toISOString(); const plugin = pluginNameManager.currentPluginName; - const isExeption = args[0].includes('**Computing'); + const isExeption = + typeof args[0] === 'string' && args[0].includes('**Computing'); const message = `${level}: ${date}: ${plugin ? plugin + ': ' : ''}${args.join( ', ' )}`; From 71d97e24ecb924031061bf725f5087f442d7bacc Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 18:29:19 +0400 Subject: [PATCH 821/863] revert(scripts): drop run yamls, impact test --- scripts/impact-test.sh | 23 ------- scripts/run-yamls.sh | 8 --- scripts/yaml-to-csv/yaml-to-csv.md | 73 --------------------- scripts/yaml-to-csv/yaml-to-csv.py | 102 ----------------------------- 4 files changed, 206 deletions(-) delete mode 100755 scripts/impact-test.sh delete mode 100644 scripts/run-yamls.sh delete mode 100644 scripts/yaml-to-csv/yaml-to-csv.md delete mode 100644 scripts/yaml-to-csv/yaml-to-csv.py diff --git a/scripts/impact-test.sh b/scripts/impact-test.sh deleted file mode 100755 index 9bdd213c3..000000000 --- a/scripts/impact-test.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -echo "Starting impact tests" -prefix="manifests/examples" - -# Using find to traverse files recursively within the manifests/examples folder -find "$prefix" -type f | while read -r file; do - # Remove the prefix and store the output file path - outfile="${file#$prefix/}" - - echo "" - echo "Executing $file, outfile is $outfile" - echo "" - - # Ensure the output directory exists before running the command - output_dir="manifests/outputs/$(dirname "$outfile")" - mkdir -p "$output_dir" - - # Run the npm command with the correct file and output path - npm run if-run -- -m "$file" -o "$output_dir/$(basename "$outfile")" -done - -exit 0 diff --git a/scripts/run-yamls.sh b/scripts/run-yamls.sh deleted file mode 100644 index fbe394c6b..000000000 --- a/scripts/run-yamls.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -echo 'Running all manifests' - - -for f in ./examples/manifests/*.yml; do - echo "Processing $f file..."; - npm run if-run -- --manifest $f - done diff --git a/scripts/yaml-to-csv/yaml-to-csv.md b/scripts/yaml-to-csv/yaml-to-csv.md deleted file mode 100644 index 02979cb39..000000000 --- a/scripts/yaml-to-csv/yaml-to-csv.md +++ /dev/null @@ -1,73 +0,0 @@ -# YML to CSV shell plugin - -This is a shell plugin (python script) that produces a CSV file from an output YML file - -## Usage - -> python path/to/your/if-yaml-to-csv.py -c path/to/your/output.csv - -In this default usage: - -1. The script will listen on STDIN for input impl. -2. The output CSV will be created / overwritten in the specified path. -3. By default, only _timestamp_, _duration_, _energy_ and _carbon_ fields are projected as columns to the CSV file. To change this, see 'Optional arguments' - -### Optional arguments: - -> _-y_ - -Path to input yml file (output). Using this option will override the default input method of listening on STDIN. - -> _-p_ - -Comma separated (no spaces!) names of fields to project from input yml to output CSV as columns. Default = _timestamp,duration,energy,carbon_. Putting an emply list here (""") will project all output output fields. - -> _-j_ - -Left-join the resulting CSV data to existing CSV file. Boolean switch, no argument values. - -- Default join keys are _timestamp,duration_. To change this, use the _-jk_ option. -- In case of identical column names between existing and new data, new column names will be added with _"\_new"_ suffix. -- If there is no pre-existing file at the path specified under _-c_, _-j_ is ignored (along with other join-related options) - -> _-jk_ - -Comma separated (no spaces!) names of columns to join by. Default = _timestamp,duration_. Relevant only when using --join (-j) option. - -> _-js_ - -Suffix to add to ALL projected columns in the new data CSV data. Relevant only when using --join (-j) option. - -#### Example: - -> python path/to/your/if-yaml-to-csv.py -y path/to/your/output.yml -c path/to/your/output.csv -p timestamp,duration,energy,carbon,location -j -jk duration,location -js "\_MY_SUFFIX" - -This will: - -- Convert the content of _path/to/your/output.yml_ file into CSV format data, instead of listening to input on SDTIN. -- project the _location_ field to the CSV data, alongside the default timestamp, duration, energy and carbon fields. -- left-join the resulting CSV data to the data already existing in the path specified under _-c_, using duration, location columns as join keys. -- will add "\_MY_SUFFIX" suffix to ALL columns in the new CSV data. - -## Integrating the script in your IMPL as a shell plugin - - initialize: - plugins: - ... - ... - yaml-to-csv: - method: Shell - path: "@grnsft/if-plugins" - - graph: - children: - child: - pipeline: - ... - ... - - yaml-to-csv - config: - ... - ... - yaml-to-csv: - executable: python path/to/your/if-yaml-to-csv.py -c path/to/your/output.csv -j diff --git a/scripts/yaml-to-csv/yaml-to-csv.py b/scripts/yaml-to-csv/yaml-to-csv.py deleted file mode 100644 index aa269d9ed..000000000 --- a/scripts/yaml-to-csv/yaml-to-csv.py +++ /dev/null @@ -1,102 +0,0 @@ -import sys -import yaml -import pandas -import os -import argparse - - -default_projection_list = 'timestamp,duration,energy,carbon' -default_join_keys = 'timestamp,duration' - - -def parse_arguments(): - parser = argparse.ArgumentParser(description='Impact Framework yaml-to-csv parser') - parser.add_argument('-y', '--yml', type=str, help='Path to input yml file') - parser.add_argument('-c', '--csv', type=str, help='Path to output csv file') - parser.add_argument('-p', '--project', type=str, default=default_projection_list, help=f'Comma separated (no spaces!) names of fields to project from input yml to output CSV as columns. Default ={default_projection_list}') - parser.add_argument('-j', '--join', action='store_true', help='Join the resulting CSV data to existing CSV file') - parser.add_argument('-jk', '--join_keys', type=str, default=default_join_keys, help=f'Comma separated (no spaces!) names of columns to join by. Default ={default_join_keys}. Relevant only when using --join (-j) option') - parser.add_argument('-js', '--join_suffix', type=str, help='Suffix to add to projected columns in resulting CSV data. Relevant only when using --join (-j) option') - args = parser.parse_args() - return args - - -def get_yaml_data(input_yaml_path): - if input_yaml_path is not None: - return read_yaml_file(input_yaml_path) - else: - input_yaml_string = sys.stdin.read() - return input_yaml_string - - -def read_yaml_file(input_yaml): - try: - with open(input_yaml, 'r') as yaml_file: - yaml_string = yaml_file.read() - yaml_data = yaml.safe_load(yaml_string) - return yaml_data["graph"]["children"]["child"] - except FileNotFoundError: - print(f"Input YAML file '{input_yaml}' not found.") - sys.exit(1) - - -def read_and_project_yaml_data(yaml_data, projection_list): - yaml_obj = yaml.safe_load(yaml_data) - output_yaml_data = yaml_obj["inputs"] - outputs_df = pandas.json_normalize(output_yaml_data) - filtered_df = outputs_df[projection_list] if projection_list else outputs_df - return filtered_df - - -def write_to_csv_file(df_to_write, output_csv_path): - csv_data = df_to_write.to_csv() - with open(output_csv_path, 'w', newline='') as csv_file: - csv_file.write(csv_data) - - -def validate_file_exists(file_path): - if not os.path.exists(file_path): - raise Exception(f"unable to join: file {file_path} doesn't exist") - - -def rename_columns(df, join_keys, projection_list, suff): - cols_to_rename = list(filter(lambda x: x not in join_keys, projection_list)) - new_column_names = [col_name + "_" + suff for col_name in cols_to_rename] - rename_dict = dict(zip(cols_to_rename, new_column_names)) - df_result = df.rename(columns=rename_dict) - return df_result - - -def do_new(yaml_data, output_csv_path, projection_list): - filtered_df = read_and_project_yaml_data(yaml_data, projection_list) - write_to_csv_file(filtered_df, output_csv_path) - - -def do_join(yaml_data, output_csv_path, projection_list, join_keys, suff=""): - if not os.path.exists(output_csv_path): - do_new(yaml_data, output_csv_path, projection_list) - else: - filtered_df = read_and_project_yaml_data(yaml_data, projection_list) - if suff is None or len(suff) == 0: - outputs_df_to_join = filtered_df - else: - outputs_df_to_join = rename_columns(filtered_df, join_keys, projection_list, suff) - df_existing = pandas.read_csv(output_csv_path) - df_merged = df_existing.merge(outputs_df_to_join, on=join_keys, how="left", suffixes=("", "_new")) - write_to_csv_file(df_merged, output_csv_path) - - -args = parse_arguments() - -input_yaml_path = args.yml -output_csv_path = args.csv -projection_list = args.project.split(',') - -yaml_data = get_yaml_data(input_yaml_path) -if args.join: - join_keys = args.join_keys.split(',') - join_suffix = args.join_suffix - do_join(yaml_data, output_csv_path, projection_list, join_keys, join_suffix) -else: - do_new(yaml_data, output_csv_path, projection_list) -sys.stdout.write(str(yaml_data)) From 08f179d2979c8bb1335c74d86d320d50391301b3 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 2 Oct 2024 18:29:52 +0400 Subject: [PATCH 822/863] revert(src): drop grafana --- grafana/IF_GRAFANA_SETUP.md | 71 ------- grafana/if_grafana_config.json | 370 --------------------------------- 2 files changed, 441 deletions(-) delete mode 100644 grafana/IF_GRAFANA_SETUP.md delete mode 100644 grafana/if_grafana_config.json diff --git a/grafana/IF_GRAFANA_SETUP.md b/grafana/IF_GRAFANA_SETUP.md deleted file mode 100644 index 99b0575d8..000000000 --- a/grafana/IF_GRAFANA_SETUP.md +++ /dev/null @@ -1,71 +0,0 @@ -# Setting up the Impact Framework Grafana dashboard -(for any questions please contact paz.barda@intel.com / pazbarda@gmail.com) - -## Download and Install Grafana -https://grafana.com/get/?plcmt=top-nav&cta=downloads&tab=self-managed - -This is the self managed version: you install it and can run it on your local machine. - -## Open Grafana on your local machine -Web browser: localhost:3000 - -You should see the Grafana welcome page. - -## Download and Install Grafana CSV plugin -https://grafana.com/grafana/plugins/marcusolsson-csv-datasource/?tab=installation - -After installation, go to Menu -> Plugins, search for "CSV" and make sure CSV plugin is there - -## Import the dashboard json config - -Menu -> Dashboards -> New -> Import - -1. Drag and drop "grafana_config.json" from this folder to Grafana webpage -2. Optional - change the name of the dashboard and the details text on the right -3. Click import. - -Dashboard should now appear, but with no data fed into the charts (yet). - -## Create a data source for your OMPL CSV file -Menu -> Connections -> Data Sources -> Add data source - -1. Search for "CSV", you should see the CSV plugin. Click it. -2. Name you new data source. -3. Switch from "HTTP" to "Local". -4. Type/paste in the path to your ompl csv ("your/path/to/csvs/if-iee-demo.csv" in our example) - -Click Save & Test - - - -## Connect your OMPL CSV data source to your dashboard - -Menu -> Dashboards -> Select your new dashboard - -For each blank chart: - -1. Click the chart menu -> edit -2. Below the chart go to Quary tab -3. At the top of the tab select the ompl CSV datasource you created -4. Go to Transform tab, and select the fields you'd like to show on the chart. -5. Start with "timestamp" and convert it to "Time". -6. Any other numeric value you'd like to show should be converted to "Number" - -Click Apply - -Click Save - -NOTE: when you select a CSV file (step 3) it might initially not show the columns in the transformation dropdown. if that happens - save the dashboard, exit it refresh the Grafana webpage (localhost:3000). Once you go into the dashboard again it should show the columns for transformation. - - -## Enable auto-refresh of the dashboard - -On the top right of the dashboard, look for the "refresh dashboard" button - -Click the dropdown next to it, and choose the auto-refresh interval - -Click Save - -## Your dashboard is now ready to go! -With every change to you CSV file you should see it reflect on the dashboard momentarily. - diff --git a/grafana/if_grafana_config.json b/grafana/if_grafana_config.json deleted file mode 100644 index 2fe00915b..000000000 --- a/grafana/if_grafana_config.json +++ /dev/null @@ -1,370 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 5, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "gridPos": { - "h": 3, - "w": 18, - "x": 0, - "y": 0 - }, - "id": 3, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "

\n Dashboard Title goes here", - "mode": "html" - }, - "pluginVersion": "10.1.1", - "targets": [ - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "decimalSeparator": ".", - "delimiter": ",", - "header": true, - "ignoreUnknown": false, - "refId": "A", - "schema": [ - { - "name": "", - "type": "string" - } - ], - "skipRows": 0 - } - ], - "transparent": true, - "type": "text" - }, - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "description": "", - "gridPos": { - "h": 3, - "w": 5, - "x": 19, - "y": 0 - }, - "id": 2, - "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false - }, - "content": "

\n Some detailed text:
goes here

", - "mode": "html" - }, - "pluginVersion": "10.1.1", - "targets": [ - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "decimalSeparator": ".", - "delimiter": ",", - "header": true, - "ignoreUnknown": false, - "refId": "A", - "schema": [ - { - "name": "", - "type": "string" - } - ], - "skipRows": 0 - } - ], - "transparent": true, - "type": "text" - }, - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 3 - }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "decimalSeparator": ".", - "delimiter": ",", - "header": true, - "ignoreUnknown": false, - "refId": "A", - "schema": [ - { - "name": "", - "type": "string" - } - ], - "skipRows": 0 - } - ], - "title": "Energy [kWh]", - "transformations": [ - { - "id": "convertFieldType", - "options": { - "conversions": [ - { - "destinationType": "time", - "targetField": "timestamp" - }, - { - "destinationType": "number", - "targetField": "energy" - } - ], - "fields": {} - } - } - ], - "type": "timeseries" - }, - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 5, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "marcusolsson-csv-datasource", - "uid": "" - }, - "decimalSeparator": ".", - "delimiter": ",", - "header": true, - "ignoreUnknown": false, - "refId": "A", - "schema": [ - { - "name": "", - "type": "string" - } - ], - "skipRows": 0 - } - ], - "title": "Carbon [gCO2]", - "transformations": [ - { - "id": "convertFieldType", - "options": { - "conversions": [ - { - "destinationType": "time", - "targetField": "timestamp" - }, - { - "destinationType": "number", - "targetField": "carbon" - } - ], - "fields": {} - } - } - ], - "type": "timeseries" - } - ], - "refresh": "", - "schemaVersion": 38, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "2023-11-02T08:35:31.000Z", - "to": "2023-11-02T08:35:42.000Z" - }, - "timepicker": {}, - "timezone": "", - "title": "IF_dashboard", - "uid": "", - "version": 40, - "weekStart": "" -} \ No newline at end of file From cbbb67df747aee1b137de328d0ab099178186a22 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:15:46 +0400 Subject: [PATCH 823/863] test(lib): drop kind field --- src/__tests__/if-run/lib/compute.test.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/__tests__/if-run/lib/compute.test.ts b/src/__tests__/if-run/lib/compute.test.ts index a7e2b2cd2..9c883f961 100644 --- a/src/__tests__/if-run/lib/compute.test.ts +++ b/src/__tests__/if-run/lib/compute.test.ts @@ -15,18 +15,14 @@ describe('lib/compute: ', () => { return input; }), - metadata: { - kind: 'execute', - }, + metadata: {}, }); const mockObservePlugin = () => ({ execute: () => [ {timestamp: '2024-09-02', duration: 40, 'cpu/utilization': 30}, {timestamp: '2024-09-03', duration: 60, 'cpu/utilization': 40}, ], - metadata: { - kind: 'execute', - }, + metadata: {}, }); const mockObservePluginTimeSync = () => ({ execute: () => [ @@ -41,9 +37,7 @@ describe('lib/compute: ', () => { 'cpu/utilization': 40, }, ], - metadata: { - kind: 'execute', - }, + metadata: {}, }); const mockTimeSync = () => ({ execute: () => [ @@ -68,9 +62,7 @@ describe('lib/compute: ', () => { 'cpu/utilization': 40, }, ], - metadata: { - kind: 'execute', - }, + metadata: {}, }); /** * Compute params. From af17b4044919c90ac7bd547c51d38d90bff33128 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:16:15 +0400 Subject: [PATCH 824/863] test(util): rename aggregate inputs into one --- src/__tests__/if-run/util/aggregation-helper.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/__tests__/if-run/util/aggregation-helper.test.ts b/src/__tests__/if-run/util/aggregation-helper.test.ts index 32a749a47..f27eb7874 100644 --- a/src/__tests__/if-run/util/aggregation-helper.test.ts +++ b/src/__tests__/if-run/util/aggregation-helper.test.ts @@ -4,7 +4,7 @@ import {PluginParams} from '@grnsft/if-core/types'; import {AggregationParams} from '../../../common/types/manifest'; -import {aggregateInputsIntoOne} from '../../../if-run/util/aggregation-helper'; +import {aggregateOutputsIntoOne} from '../../../if-run/util/aggregation-helper'; import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; import {STRINGS} from '../../../if-run/config'; @@ -33,7 +33,7 @@ describe('util/aggregation-helper: ', () => { }); }); - describe('aggregateInputsIntoOne(): ', () => { + describe('aggregateOutputsIntoOne(): ', () => { it('throws error if aggregation criteria is not found in input.', () => { const inputs: PluginParams[] = [{timestamp: '', duration: 10}]; const metrics: string[] = ['cpu/utilization']; @@ -42,7 +42,7 @@ describe('util/aggregation-helper: ', () => { expect.assertions(2); try { - aggregateInputsIntoOne(inputs, metrics, isTemporal); + aggregateOutputsIntoOne(inputs, metrics, isTemporal); } catch (error) { expect(error).toBeInstanceOf(MissingAggregationParamError); @@ -71,7 +71,7 @@ describe('util/aggregation-helper: ', () => { duration: 10, carbon: inputs[0].carbon + inputs[1].carbon, }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + const aggregated = aggregateOutputsIntoOne(inputs, metrics, isTemporal); expect(aggregated).toEqual(expectedValue); }); @@ -86,7 +86,7 @@ describe('util/aggregation-helper: ', () => { const expectedValue = { carbon: inputs[0].carbon + inputs[1].carbon, }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + const aggregated = aggregateOutputsIntoOne(inputs, metrics, isTemporal); expect(aggregated).toEqual(expectedValue); }); @@ -121,7 +121,7 @@ describe('util/aggregation-helper: ', () => { (inputs[0]['cpu/utilization'] + inputs[1]['cpu/utilization']) / inputs.length, }; - const aggregated = aggregateInputsIntoOne(inputs, metrics, isTemporal); + const aggregated = aggregateOutputsIntoOne(inputs, metrics, isTemporal); expect(aggregated).toEqual(expectedValue); expect(aggregated.timestamp).toBeUndefined(); expect(aggregated.duration).toBeUndefined(); From d05744d7a7e09f69f6af1ce83accb8155c7e8692 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:16:57 +0400 Subject: [PATCH 825/863] test(util): drop storeAggregationMethods --- src/__tests__/if-run/util/helpers.test.ts | 102 +--------------------- 1 file changed, 1 insertion(+), 101 deletions(-) diff --git a/src/__tests__/if-run/util/helpers.test.ts b/src/__tests__/if-run/util/helpers.test.ts index 796f6b201..dedc76634 100644 --- a/src/__tests__/if-run/util/helpers.test.ts +++ b/src/__tests__/if-run/util/helpers.test.ts @@ -4,15 +4,7 @@ const mockError = jest.fn(); import {ERRORS} from '@grnsft/if-core/utils'; -import {GlobalPlugins} from '../../../common/types/manifest'; - -import {storeAggregationMetrics} from '../../../if-run/lib/aggregate'; - -import { - andHandle, - mergeObjects, - storeAggregationMethods, -} from '../../../if-run/util/helpers'; +import {andHandle, mergeObjects} from '../../../if-run/util/helpers'; const {WriteFileError} = ERRORS; @@ -179,96 +171,4 @@ describe('if-run/util/helpers: ', () => { expect(result).toEqual(expectedResult); }); }); - - describe('storeAggregationMethods(): ', () => { - // @typescript-eslint/no-unused-vars - const mockPluginStorage = { - get: jest.fn(), - set: jest.fn(() => {}), - }; - - const mockPlugins: GlobalPlugins = { - multiply: { - path: 'builtin', - method: 'Multiply', - }, - sci: { - path: 'builtin', - method: 'Sci', - }, - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('succefully executes with correct metrics.', () => { - const mockPlugin1 = { - execute: () => [{}], - metadata: { - kind: 'execute', - inputs: { - carbon: { - description: 'mock description', - unit: 'none', - 'aggregation-method': 'sum', - }, - }, - outputs: { - cpu: { - description: 'mock description', - unit: 'none', - 'aggregation-method': 'avg', - }, - }, - }, - }; - - const mockPlugin2 = { - metadata: { - inputs: {}, - outputs: { - carbon: {'aggregation-method': 'none'}, - }, - }, - }; - - mockPluginStorage.get - .mockReturnValueOnce(mockPlugin1) - .mockReturnValueOnce(mockPlugin2); - - // @ts-ignore - storeAggregationMethods(mockPlugins, mockPluginStorage); - - expect(storeAggregationMetrics).toHaveBeenCalledTimes(3); - expect(storeAggregationMetrics).toHaveBeenNthCalledWith(1, { - carbon: 'sum', - }); - expect(storeAggregationMetrics).toHaveBeenNthCalledWith(2, { - cpu: 'avg', - }); - expect(storeAggregationMetrics).toHaveBeenNthCalledWith(3, { - carbon: 'none', - }); - }); - - it('does not execute if there are no inputs or outputs.', () => { - mockPluginStorage.get.mockReturnValueOnce({ - execute: () => [{}], - metadata: {}, - }); - - const mockPlugin = { - execute: () => [{}], - metadata: { - kind: 'execute', - }, - }; - - mockPluginStorage.get.mockReturnValueOnce(mockPlugin); - // @ts-ignore - storeAggregationMethods(mockPlugins, mockPluginStorage); - expect(storeAggregationMetrics).not.toHaveBeenCalled(); - }); - }); }); From d3c83cccaae5f68babfaacf634a81907519d781a Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:17:21 +0400 Subject: [PATCH 826/863] test(util): drop metadata kind from plugin storage --- src/__tests__/if-run/util/plugin-storage.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/if-run/util/plugin-storage.test.ts b/src/__tests__/if-run/util/plugin-storage.test.ts index 885ccb107..90709ea78 100644 --- a/src/__tests__/if-run/util/plugin-storage.test.ts +++ b/src/__tests__/if-run/util/plugin-storage.test.ts @@ -20,7 +20,7 @@ describe('util/pluginStorage: ', () => { const pluginName = 'mock-plugin'; const pluginBody = { execute: () => [{}], - metadata: {kind: 'mock-kind'}, + metadata: {}, }; describe('get(): ', () => { From 682bdbe4f5a9b4c0aeec1d81156bdb7511a6c0f1 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:17:49 +0400 Subject: [PATCH 827/863] feat(builtins): drop evaluate input from time sync --- src/if-run/builtins/time-sync/index.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index 40fd6f6ab..f0734d61c 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -2,7 +2,7 @@ import {isDate} from 'node:util/types'; import {Settings, DateTime, DateTimeMaybeValid, Interval} from 'luxon'; import {z} from 'zod'; -import {ERRORS, evaluateInput} from '@grnsft/if-core/utils'; +import {ERRORS} from '@grnsft/if-core/utils'; import { PluginParams, PaddingReceipt, @@ -173,8 +173,7 @@ export const TimeSync = PluginFactory({ i: number, params: TimeParams ) => { - const evaluatedInput = evaluateInput(input); - const metrics = Object.keys(evaluatedInput); + const metrics = Object.keys(input); const timeStep = params.upsamplingResolution; return metrics.reduce((acc, metric) => { @@ -201,12 +200,8 @@ export const TimeSync = PluginFactory({ acc[metric] = aggregationParams.time === 'sum' - ? convertPerInterval( - evaluatedInput[metric], - evaluatedInput['duration'], - timeStep - ) - : evaluatedInput[metric]; + ? convertPerInterval(input[metric], input['duration'], timeStep) + : input[metric]; return acc; }, {} as PluginParams); From 73ddaf76974df07a6bcf2557b3da23643f589b2c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 13:21:48 +0400 Subject: [PATCH 828/863] chore(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 874b062db..d960a041a 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.24", + "@grnsft/if-core": "^0.0.25", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.24.tgz", - "integrity": "sha512-AtufC8XKEKxotYlz4r0635j6tGpa6X7yii+HwCb/Tak3yuftTQVX0VKrhGJpWH0z19BOjmiuKhnucV+jE9FnrQ==", + "version": "0.0.25", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.25.tgz", + "integrity": "sha512-1W4SXsXhXos06q4SBPc8QpgQPDhHEc03njrGcd/X2UiJyh0ycBKTqGCjuRPRipEayGgUxO0DwRNOgNcgzzcDkA==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index e2b508f5d..bea408854 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.24", + "@grnsft/if-core": "^0.0.25", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From a05383894cc29ecc02db262bf78ba93d563587cd Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 16:19:54 +0400 Subject: [PATCH 829/863] fix(builtins): fix typo in sci embodied outputs.unit --- src/if-run/builtins/sci-embodied/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/sci-embodied/index.ts b/src/if-run/builtins/sci-embodied/index.ts index f48af0781..0a45b419d 100644 --- a/src/if-run/builtins/sci-embodied/index.ts +++ b/src/if-run/builtins/sci-embodied/index.ts @@ -69,7 +69,7 @@ export const SciEmbodied = PluginFactory({ outputs: { 'embodied-carbon': { description: 'embodied carbon for a resource, scaled by usage', - unit: 'gCO2e', + unit: 'gCO2eq', 'aggregation-method': { time: 'sum', component: 'sum', From 02635c9777caec25196a8a4bb2c47b7acb210aa5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 3 Oct 2024 18:47:55 +0400 Subject: [PATCH 830/863] fix(doc): drop kind execute from migration guide --- Refactor-migration-guide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Refactor-migration-guide.md b/Refactor-migration-guide.md index 00a199cc5..abffd6884 100644 --- a/Refactor-migration-guide.md +++ b/Refactor-migration-guide.md @@ -212,7 +212,6 @@ export const PluginFactory = mapping: MappingParams ) => ({ metadata: { - kind: 'execute', inputs: {...params.metadata.inputs, ...parametersMetadata?.inputs}, outputs: parametersMetadata?.outputs || params.metadata.outputs, }, From 2c62619c2a6d68470060e8d88e173fbee9c9cd35 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 15:56:22 +0400 Subject: [PATCH 831/863] fix(manifests): fix failed manifests --- ...-config.yml => failure-missing-config.yml} | 16 +- .../examples/builtins/time-sync/success.yml | 16 +- .../bugs/aggregation-error-wrong-metric.yaml | 62 ++-- .../sci-embodied-missing-resources-total.yaml | 72 ----- ...ailure-invalid-default-emission-value.yaml | 48 ++- .../failure-missing-expected-lifespan.yaml | 69 ----- .../builtins/sci-embodied/scenario-1.yaml | 17 +- .../builtins/sci-embodied/scenario-2.yaml | 9 +- .../builtins/sci-embodied/success.yaml | 13 +- manifests/outputs/pipelines/nesting.yaml | 293 +++++++++++++++++- .../outputs/pipelines/pipeline-teads-sci.yaml | 30 +- manifests/outputs/pipelines/sci.yaml | 30 +- 12 files changed, 438 insertions(+), 237 deletions(-) rename manifests/examples/builtins/time-sync/{failure-missing-global-config.yml => failure-missing-config.yml} (53%) delete mode 100644 manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml delete mode 100644 manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml diff --git a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml b/manifests/examples/builtins/time-sync/failure-missing-config.yml similarity index 53% rename from manifests/examples/builtins/time-sync/failure-missing-global-config.yml rename to manifests/examples/builtins/time-sync/failure-missing-config.yml index 2938d3bb1..b9ef55155 100644 --- a/manifests/examples/builtins/time-sync/failure-missing-global-config.yml +++ b/manifests/examples/builtins/time-sync/failure-missing-config.yml @@ -5,14 +5,10 @@ initialize: output: - yaml plugins: - "time-sync": + 'time-sync': method: TimeSync - path: "builtin" + path: 'builtin' config: - # start-time: '2023-12-12T00:00:00.000Z' - # end-time: '2023-12-12T00:01:00.000Z' - # interval: 5 - # allow-padding: true tree: children: child: @@ -20,15 +16,15 @@ tree: compute: - time-sync inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' duration: 3 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 energy-cpu: 0.001 diff --git a/manifests/examples/builtins/time-sync/success.yml b/manifests/examples/builtins/time-sync/success.yml index 95a94e5d3..0fd0cbcf3 100644 --- a/manifests/examples/builtins/time-sync/success.yml +++ b/manifests/examples/builtins/time-sync/success.yml @@ -5,12 +5,12 @@ initialize: output: - yaml plugins: - "time-sync": + 'time-sync': method: TimeSync - path: "builtin" + path: 'builtin' config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true tree: @@ -20,15 +20,15 @@ tree: compute: - time-sync inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 energy-cpu: 0.001 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 energy-cpu: 0.001 diff --git a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml index c6e8284ca..d45f433e0 100644 --- a/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml +++ b/manifests/outputs/bugs/aggregation-error-wrong-metric.yaml @@ -19,7 +19,7 @@ initialize: - 10 - 50 - 100 - "y": + 'y': - 0.12 - 0.32 - 0.75 @@ -83,34 +83,33 @@ initialize: method: TimeSync path: builtin config: - start-time: "2023-12-12T00:00:00.000Z" - end-time: "2023-12-12T00:01:00.000Z" + start-time: '2023-12-12T00:00:00.000Z' + end-time: '2023-12-12T00:01:00.000Z' interval: 5 allow-padding: true execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/aggregation-error-wrong-metric.yml -o - manifests/outputs/bugs/aggregation-error-wrong-metric + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/outputs/bugs/aggregation-error-wrong-metric.yaml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-01T19:25:34.759Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-10-04T08:38:25.343Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.25' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -130,9 +129,10 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- - MissingInputDataError: `functional-unit` value is missing from input data or it is not a positive integer + MissingAggregationParamError: Aggregation metric dummy-param is not found in + inputs[0]. tree: children: child-1: @@ -160,25 +160,25 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' cloud/instance-type: A1 cloud/region: uk-west duration: 1 cpu/utilization: 10 requests: 100 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 20 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 15 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cloud/instance-type: A1 cloud/region: uk-west @@ -209,25 +209,25 @@ tree: vcpus-allocated: 1 vcpus-total: 8 inputs: - - timestamp: "2023-12-12T00:00:00.000Z" + - timestamp: '2023-12-12T00:00:00.000Z' duration: 1 cpu/utilization: 30 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: "2023-12-12T00:00:01.000Z" + - timestamp: '2023-12-12T00:00:01.000Z' duration: 5 cpu/utilization: 28 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: "2023-12-12T00:00:06.000Z" + - timestamp: '2023-12-12T00:00:06.000Z' duration: 7 cpu/utilization: 40 cloud/instance-type: A1 cloud/region: uk-west requests: 100 - - timestamp: "2023-12-12T00:00:13.000Z" + - timestamp: '2023-12-12T00:00:13.000Z' duration: 30 cpu/utilization: 33 cloud/instance-type: A1 diff --git a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml b/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml deleted file mode 100644 index 486947ebd..000000000 --- a/manifests/outputs/bugs/sci-embodied-missing-resources-total.yaml +++ /dev/null @@ -1,72 +0,0 @@ -name: sci-embodied -description: >- - receiving incorrect error message when running sci-embodied without - `resources-total` issue -tags: null -initialize: - plugins: - sci-embodied: - method: SciEmbodied - path: builtin -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/bugs/sci-embodied-missing-resources-total.yml -o - manifests/outputs/bugs/sci-embodied-missing-resources-total - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-01T20:17:30.390Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - InputValidationError: "vcpus-allocated" parameter is required. Error code: - invalid_union. -tree: - children: - child: - pipeline: - compute: - - sci-embodied - defaults: - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - resources-reserved: 1 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml b/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml index f6af79041..4a11178b3 100644 --- a/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml +++ b/manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml @@ -1,7 +1,6 @@ name: sci-embodied description: >- - failure with `defaults.device/emissions-embodied` being string instead of - number + failure with `vCPUs` being string instead of number tags: null initialize: plugins: @@ -11,28 +10,26 @@ initialize: execution: status: fail command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value.yml - -o - manifests/outputs/plugins/sci-embodied/failure-invalid-default-emission-value + /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node + /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m + manifests/outputs/builtins/sci-embodied/failure-invalid-default-emission-value.yaml environment: - if-version: 0.4.0 + if-version: 0.6.0 os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T20:49:08.280Z (UTC) + os-version: 14.6.1 + node-version: 18.20.4 + date-time: 2024-10-04T08:59:52.608Z (UTC) dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" + - '@babel/core@7.22.10' + - '@babel/preset-typescript@7.23.3' + - '@commitlint/cli@18.6.0' + - '@commitlint/config-conventional@18.6.0' + - '@grnsft/if-core@0.0.25' + - '@jest/globals@29.7.0' + - '@types/jest@29.5.8' + - '@types/js-yaml@4.0.9' + - '@types/luxon@3.4.2' + - '@types/node@20.9.0' - axios-mock-adapter@1.22.0 - axios@1.7.2 - cross-env@7.0.3 @@ -52,10 +49,10 @@ execution: - typescript-cubic-spline@1.0.1 - typescript@5.2.2 - winston@3.11.0 - - zod@3.22.4 + - zod@3.23.8 error: >- - InputValidationError: "device/emissions-embodied" parameter is invalid - number. please provide it as `gco2e` to input. Error code: invalid_union. + InputValidationError: "vCPUs" parameter is expected number, received string + at index 0. Error code: invalid_type. tree: children: child: @@ -63,9 +60,8 @@ tree: compute: - sci-embodied defaults: - device/emissions-embodied: fail + vCPUs: fail time-reserved: 3600 - device/expected-lifespan: 94608000 resources-reserved: 1 resources-total: 8 inputs: diff --git a/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml b/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml deleted file mode 100644 index 43f22163e..000000000 --- a/manifests/outputs/builtins/sci-embodied/failure-missing-expected-lifespan.yaml +++ /dev/null @@ -1,69 +0,0 @@ -name: sci-embodied -description: missing device/expected-lifespan -tags: null -initialize: - plugins: - sci-embodied: - method: SciEmbodied - path: builtin -execution: - status: fail - command: >- - /Users/mariamkhalatova/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/mariamkhalatova/Projects/UK/if/src/index.ts -m - manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan.yml - -o manifests/outputs/plugins/sci-embodied/failure-missing-expected-lifespan - environment: - if-version: 0.4.0 - os: macOS - os-version: "13.2" - node-version: 18.14.2 - date-time: 2024-07-02T20:42:51.951Z (UTC) - dependencies: - - "@babel/core@7.22.10" - - "@babel/preset-typescript@7.23.3" - - "@commitlint/cli@18.6.0" - - "@commitlint/config-conventional@18.6.0" - - "@grnsft/if-core@0.0.10" - - "@jest/globals@29.7.0" - - "@types/jest@29.5.8" - - "@types/js-yaml@4.0.9" - - "@types/luxon@3.4.2" - - "@types/node@20.9.0" - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.22.4 - error: >- - InputValidationError: "device/expected-lifespan" parameter is required. - Error code: invalid_union. -tree: - children: - child: - pipeline: - compute: - - sci-embodied - defaults: - device/emissions-embodied: 1533.12 - time-reserved: 3600 - resources-reserved: 1 - resources-total: 8 - inputs: - - timestamp: 2023-07-06T00:00 - duration: 3600 diff --git a/manifests/outputs/builtins/sci-embodied/scenario-1.yaml b/manifests/outputs/builtins/sci-embodied/scenario-1.yaml index ec07d4df1..878c88fe3 100644 --- a/manifests/outputs/builtins/sci-embodied/scenario-1.yaml +++ b/manifests/outputs/builtins/sci-embodied/scenario-1.yaml @@ -16,20 +16,19 @@ execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/builtins/sci-embodied/scenario-1.yml -o - manifests/outputs/builtins/sci-embodied/scenario-1.yml + manifests/outputs/builtins/sci-embodied/scenario-1.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:14:16.990Z (UTC) + date-time: 2024-10-04T09:06:05.353Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -73,10 +72,20 @@ tree: - timestamp: 2023-08-06T00:00 duration: 3600 hdd: 2 + vCPUs: 1 + memory: 16 + ssd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 34.24657534246575 - timestamp: 2023-08-06T10:00 duration: 3600 hdd: 2 + vCPUs: 1 + memory: 16 + ssd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 34.24657534246575 aggregated: embodied-carbon: 68.4931506849315 diff --git a/manifests/outputs/builtins/sci-embodied/scenario-2.yaml b/manifests/outputs/builtins/sci-embodied/scenario-2.yaml index 2ecf249cf..a6d3f7eeb 100644 --- a/manifests/outputs/builtins/sci-embodied/scenario-2.yaml +++ b/manifests/outputs/builtins/sci-embodied/scenario-2.yaml @@ -21,20 +21,19 @@ execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/builtins/sci-embodied/scenario-2.yml -o - manifests/outputs/builtins/sci-embodied/scenario-2.yml + manifests/outputs/builtins/sci-embodied/scenario-2.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:14:14.168Z (UTC) + date-time: 2024-10-04T09:08:03.615Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -88,6 +87,7 @@ tree: hdd: 1 gpu: 1 total-vcpus: 16 + usage-ratio: 1 embodied-carbon: 487.48858447488584 - timestamp: 2023-08-06T10:00 duration: 3600 @@ -97,4 +97,5 @@ tree: hdd: 1 gpu: 1 total-vcpus: 16 + usage-ratio: 1 embodied-carbon: 487.48858447488584 diff --git a/manifests/outputs/builtins/sci-embodied/success.yaml b/manifests/outputs/builtins/sci-embodied/success.yaml index da0a86549..023cf59ea 100644 --- a/manifests/outputs/builtins/sci-embodied/success.yaml +++ b/manifests/outputs/builtins/sci-embodied/success.yaml @@ -21,20 +21,19 @@ execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/builtins/sci-embodied/success.yml -o - manifests/outputs/builtins/sci-embodied/success.yml + manifests/outputs/builtins/sci-embodied/success.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:14:11.145Z (UTC) + date-time: 2024-10-04T09:08:28.940Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -92,4 +91,10 @@ tree: resources-reserved: 1 resources-total: 8 vcpus-allocated: 1 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 28.538812785388128 diff --git a/manifests/outputs/pipelines/nesting.yaml b/manifests/outputs/pipelines/nesting.yaml index 0a834b082..85f69f515 100644 --- a/manifests/outputs/pipelines/nesting.yaml +++ b/manifests/outputs/pipelines/nesting.yaml @@ -247,20 +247,19 @@ execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/nesting.yml -o manifests/outputs/pipelines/nesting.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T11:46:37.516Z (UTC) + date-time: 2024-10-04T11:05:09.727Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -361,6 +360,12 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 carbon: 0.04647057331303907 @@ -385,6 +390,12 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 carbon: 0.044977517757483515 @@ -409,6 +420,12 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -433,6 +450,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -457,6 +480,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -481,6 +510,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -505,6 +540,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -529,6 +570,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -553,6 +600,12 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 carbon: 0.02689692732115677 @@ -577,6 +630,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -601,6 +660,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -625,6 +690,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -703,6 +774,12 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 carbon: 0.04647057331303907 @@ -727,6 +804,12 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 carbon: 0.044977517757483515 @@ -751,6 +834,12 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -775,6 +864,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -799,6 +894,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -823,6 +924,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -847,6 +954,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -871,6 +984,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -895,6 +1014,12 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 carbon: 0.02689692732115677 @@ -919,6 +1044,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -943,6 +1074,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -967,6 +1104,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1047,6 +1190,12 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 carbon: 0.04647057331303907 @@ -1071,6 +1220,12 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 carbon: 0.044977517757483515 @@ -1095,6 +1250,12 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1119,6 +1280,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1143,6 +1310,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1167,6 +1340,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1191,6 +1370,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1215,6 +1400,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1239,6 +1430,12 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 carbon: 0.02689692732115677 @@ -1263,6 +1460,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1287,6 +1490,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1311,6 +1520,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1389,6 +1604,12 @@ tree: cpu-energy-raw: 0.00006833333333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.000008541666666666668 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.006833333333333334 carbon: 0.04647057331303907 @@ -1413,6 +1634,12 @@ tree: cpu-energy-raw: 0.00005340277777777778 vcpu-ratio: 8 cpu-energy-kwh: 0.000006675347222222222 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005340277777777777 carbon: 0.044977517757483515 @@ -1437,6 +1664,12 @@ tree: cpu-energy-raw: 0.00005190972222222222 vcpu-ratio: 8 cpu-energy-kwh: 0.0000064887152777777775 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1461,6 +1694,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1485,6 +1724,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1509,6 +1754,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1533,6 +1784,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1557,6 +1814,12 @@ tree: cpu-energy-raw: 0.00005190972222222223 vcpu-ratio: 8 cpu-energy-kwh: 0.000006488715277777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970573 carbon-operational: 0.005190972222222222 carbon: 0.04482821220192795 @@ -1581,6 +1844,12 @@ tree: cpu-energy-raw: 0.000031145833333333336 vcpu-ratio: 8 cpu-energy-kwh: 0.000003893229166666667 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.02378234398782344 carbon-operational: 0.0031145833333333334 carbon: 0.02689692732115677 @@ -1605,6 +1874,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1629,6 +1904,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 @@ -1653,6 +1934,12 @@ tree: cpu-energy-raw: 0 vcpu-ratio: 8 cpu-energy-kwh: 0 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0 carbon-operational: 0 carbon: 0 diff --git a/manifests/outputs/pipelines/pipeline-teads-sci.yaml b/manifests/outputs/pipelines/pipeline-teads-sci.yaml index b9a6377f5..aca6ca4b9 100644 --- a/manifests/outputs/pipelines/pipeline-teads-sci.yaml +++ b/manifests/outputs/pipelines/pipeline-teads-sci.yaml @@ -96,19 +96,19 @@ execution: /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m manifests/examples/pipelines/pipeline-teads-sci.yml -o - manifests/outputs/pipelines/pipeline-teads-sci.yml + manifests/outputs/pipelines/pipeline-teads-sci.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:13:31.812Z (UTC) + date-time: 2024-10-04T09:52:09.777Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -205,6 +205,12 @@ tree: cpu-energy-raw: 0.000020833333333333333 vcpu-ratio: 8 cpu-energy-kwh: 0.0000026041666666666666 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.007927447995941146 carbon-operational: 0.0020833333333333333 carbon: 0.010010781329274479 @@ -229,6 +235,12 @@ tree: cpu-energy-raw: 0.000059375 vcpu-ratio: 8 cpu-energy-kwh: 0.000007421875 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.0059375 carbon: 0.045574739979705736 @@ -253,6 +265,12 @@ tree: cpu-energy-raw: 0.00007267361111111111 vcpu-ratio: 8 cpu-energy-kwh: 0.000009084201388888889 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.05549213597158803 carbon-operational: 0.007267361111111111 carbon: 0.06275949708269914 @@ -277,6 +295,12 @@ tree: cpu-energy-raw: 0.00031145833333333335 vcpu-ratio: 8 cpu-energy-kwh: 0.00003893229166666667 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.2378234398782344 carbon-operational: 0.031145833333333334 carbon: 0.2689692732115677 diff --git a/manifests/outputs/pipelines/sci.yaml b/manifests/outputs/pipelines/sci.yaml index 7a967c9ef..7f080e67c 100644 --- a/manifests/outputs/pipelines/sci.yaml +++ b/manifests/outputs/pipelines/sci.yaml @@ -95,19 +95,19 @@ execution: command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/sci.yml -o manifests/outputs/pipelines/sci.yml + manifests/examples/pipelines/sci.yml -o manifests/outputs/pipelines/sci.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:13:59.916Z (UTC) + date-time: 2024-10-04T09:57:49.899Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -210,6 +210,12 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000005208333333333333 energy: 0.000006208333333333333 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.007927447995941146 carbon-operational: 0.004966666666666666 carbon: 0.012894114662607812 @@ -237,6 +243,12 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00001484375 energy: 0.00001584375 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.03963723997970574 carbon-operational: 0.012674999999999999 carbon: 0.05231223997970574 @@ -264,6 +276,12 @@ tree: vcpu-ratio: 4 cpu/energy: 0.000018168402777777778 energy: 0.000019168402777777778 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.05549213597158803 carbon-operational: 0.015334722222222222 carbon: 0.07082685819381025 @@ -291,6 +309,12 @@ tree: vcpu-ratio: 4 cpu/energy: 0.00007786458333333334 energy: 0.00007886458333333333 + vCPUs: 1 + memory: 16 + ssd: 0 + hdd: 0 + gpu: 0 + usage-ratio: 1 embodied-carbon: 0.2378234398782344 carbon-operational: 0.06309166666666667 carbon: 0.30091510654490106 From fc357df850ac0d7fcea5a2787eb69554aa1155a4 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 15:58:35 +0400 Subject: [PATCH 832/863] fix(builtins): fix config missing error in time-sync --- src/if-run/builtins/time-sync/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-run/builtins/time-sync/index.ts b/src/if-run/builtins/time-sync/index.ts index f0734d61c..0c1ecfb22 100644 --- a/src/if-run/builtins/time-sync/index.ts +++ b/src/if-run/builtins/time-sync/index.ts @@ -31,11 +31,11 @@ const { INCOMPATIBLE_RESOLUTION_WITH_INTERVAL, INCOMPATIBLE_RESOLUTION_WITH_GAPS, INCOMPATIBLE_RESOLUTION_WITH_INPUTS, - INVALID_TIME_NORMALIZATION, INVALID_OBSERVATION_OVERLAP, AVOIDING_PADDING_BY_EDGES, INVALID_DATE_TYPE, START_LOWER_END, + MISSING_CONFIG, } = STRINGS; /** @@ -75,8 +75,8 @@ export const TimeSync = PluginFactory({ }, }, configValidation: (config: ConfigParams): TimeNormalizerConfig => { - if (config === undefined) { - throw new ConfigError(INVALID_TIME_NORMALIZATION); + if (!config || !Object.keys(config)?.length) { + throw new ConfigError(MISSING_CONFIG); } const schema = z From 8a4c379fdf1fd144067bd8116765114d04111526 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 16:01:30 +0400 Subject: [PATCH 833/863] test(builtins): fix test related to config missing error --- src/__tests__/if-run/builtins/time-sync.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/__tests__/if-run/builtins/time-sync.test.ts b/src/__tests__/if-run/builtins/time-sync.test.ts index 9994dace5..58863272b 100644 --- a/src/__tests__/if-run/builtins/time-sync.test.ts +++ b/src/__tests__/if-run/builtins/time-sync.test.ts @@ -250,9 +250,7 @@ describe('builtins/time-sync:', () => { ]); } catch (error) { expect(error).toStrictEqual( - new InputValidationError( - '"start-time" parameter is required. Error code: invalid_type.,"end-time" parameter is required. Error code: invalid_type.,"interval" parameter is required. Error code: invalid_type.,"allow-padding" parameter is required. Error code: invalid_type.' - ) + new ConfigError('Config is not provided.') ); } }); From ee814c06dedf4eddfb5d1766fa26d24dd897caab Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 16:05:37 +0400 Subject: [PATCH 834/863] fix(config): clean up not used strings --- src/if-run/config/strings.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/if-run/config/strings.ts b/src/if-run/config/strings.ts index 5f6115bf6..41b9dc013 100644 --- a/src/if-run/config/strings.ts +++ b/src/if-run/config/strings.ts @@ -1,15 +1,12 @@ export const STRINGS = { MISSING_METHOD: "Initalization param 'method' is missing.", MISSING_PATH: "Initalization param 'path' is missing.", - UNSUPPORTED_PLUGIN: - "Plugin interface doesn't implement 'execute' or 'metadata' methods.", NOT_NATIVE_PLUGIN: (path: string) => ` You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`, INVALID_MODULE_PATH: (path: string, error?: any) => `Provided module \`${path}\` is invalid or not found. ${error ?? ''} `, - INVALID_TIME_NORMALIZATION: 'Start time or end time is missing.', INCOMPATIBLE_RESOLUTION_WITH_INTERVAL: 'The upsampling resolution must be a divisor of the given interval, but the provided value does not satisfy this criteria.', INCOMPATIBLE_RESOLUTION_WITH_INPUTS: @@ -18,21 +15,14 @@ export const STRINGS = { 'The upsampling resolution must be a divisor of gaps and paddings in the time-series, but the provided values do not satisfy this criteria.', UNEXPECTED_TIME_CONFIG: 'Unexpected node-level config provided for time-sync plugin.', - INVALID_TIME_INTERVAL: 'Interval is missing.', - AVOIDING_PADDING: (description: string) => - `Avoiding padding at ${description}`, AVOIDING_PADDING_BY_EDGES: (start: boolean, end: boolean) => `Avoiding padding at ${ start && end ? 'start and end' : start ? 'start' : 'end' }`, - INVALID_AGGREGATION_METHOD: (metric: string) => - `Aggregation is not possible for given ${metric} since method is 'none'.`, METRIC_MISSING: (metric: string, index: number) => `Aggregation metric ${metric} is not found in inputs[${index}].`, INVALID_GROUP_KEY: (key: string) => `Invalid group ${key}.`, REGROUP_ERROR: 'not an array or should contain at least one key', - INVALID_EXHAUST_PLUGIN: (pluginName: string) => - `Invalid exhaust plugin: ${pluginName}.`, UNKNOWN_PARAM: (name: string) => `Unknown parameter: ${name}. Omitting from the output.`, NOT_INITALIZED_PLUGIN: (name: string) => @@ -80,8 +70,6 @@ https://if.greensoftware.foundation/major-concepts/manifest-file`, /** Plugins messages */ INVALID_NAME: '`name` config parameter is empty or contains all spaces', START_LOWER_END: '`start-time` should be lower than `end-time`', - TIMESTAMP_REQUIRED: (index: number) => `required in input[${index}]`, - INVALID_DATETIME: (index: number) => `invalid datetime in input[${index}]`, X_Y_EQUAL: 'The length of `x` and `y` should be equal', ARRAY_LENGTH_NON_EMPTY: 'the length of the input arrays must be greater than 1', From e07f40b0fa8c49a50ea43b40a1129345b68b37b6 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 17:13:28 +0400 Subject: [PATCH 835/863] fix(manifests): fix time-sync manifests --- .../builtins/time-sync/failure-missing-config.yml | 1 - ...obal-config.yaml => failure-missing-config.yaml} | 13 +++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) rename manifests/outputs/builtins/time-sync/{failure-missing-global-config.yaml => failure-missing-config.yaml} (81%) diff --git a/manifests/examples/builtins/time-sync/failure-missing-config.yml b/manifests/examples/builtins/time-sync/failure-missing-config.yml index b9ef55155..d0ab31a05 100644 --- a/manifests/examples/builtins/time-sync/failure-missing-config.yml +++ b/manifests/examples/builtins/time-sync/failure-missing-config.yml @@ -8,7 +8,6 @@ initialize: 'time-sync': method: TimeSync path: 'builtin' - config: tree: children: child: diff --git a/manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml b/manifests/outputs/builtins/time-sync/failure-missing-config.yaml similarity index 81% rename from manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml rename to manifests/outputs/builtins/time-sync/failure-missing-config.yaml index 664da36d1..58339a417 100644 --- a/manifests/outputs/builtins/time-sync/failure-missing-global-config.yaml +++ b/manifests/outputs/builtins/time-sync/failure-missing-config.yaml @@ -8,26 +8,25 @@ initialize: time-sync: method: TimeSync path: builtin - config: null execution: status: fail command: >- /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/builtins/time-sync/failure-missing-global-config.yml -o - manifests/outputs/builtins/time-sync/failure-missing-global-config.yml + manifests/examples/builtins/time-sync/failure-missing-config.yml -o + manifests/outputs/builtins/time-sync/failure-missing-config.yaml environment: if-version: 0.6.0 os: macOS os-version: 14.6.1 node-version: 18.20.4 - date-time: 2024-09-12T06:16:16.464Z (UTC) + date-time: 2024-10-04T13:07:11.870Z (UTC) dependencies: - '@babel/core@7.22.10' - '@babel/preset-typescript@7.23.3' - '@commitlint/cli@18.6.0' - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' + - '@grnsft/if-core@0.0.25' - '@jest/globals@29.7.0' - '@types/jest@29.5.8' - '@types/js-yaml@4.0.9' @@ -53,9 +52,7 @@ execution: - typescript@5.2.2 - winston@3.11.0 - zod@3.23.8 - error: >- - ManifestValidationError: "initialize.plugins.time-sync.config" parameter is - expected object, received null. Error code: invalid_type. + error: 'ConfigError: Config is not provided.' tree: children: child: From 39a056ad66f5d364677a6cdf1e8f225e1c6fa073 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 4 Oct 2024 18:05:52 +0400 Subject: [PATCH 836/863] revert(src): drop .gitmodules --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 8f4f4893f..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "third-party/ccf-coefficients"] - path = third-party/ccf-coefficients - url = https://github.com/cloud-carbon-footprint/ccf-coefficients From d0894b65cc274bb31527649154f569211b8a321f Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 4 Oct 2024 18:06:22 +0400 Subject: [PATCH 837/863] chore(package): update keywords --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bea408854..aceda9ff5 100644 --- a/package.json +++ b/package.json @@ -58,11 +58,12 @@ "homepage": "https://greensoftware.foundation", "keywords": [ "engine", + "framework", "green software foundation", "greensoftware", "if", "impact", - "models" + "plugins" ], "license": "MIT", "publishConfig": { From 1bf698e5a3fea688525ce4f1d34c23e128f8b7e3 Mon Sep 17 00:00:00 2001 From: manushak Date: Fri, 4 Oct 2024 20:08:12 +0400 Subject: [PATCH 838/863] fix(manifests): drop manifests that contains regroup --- .../outputs/features/regroup/success.yaml | 92 - .../pipeline-with-aggregate.yaml | 1212 ------------- .../outputs-if-diff/pipeline-with-mocks.yaml | 1507 ----------------- .../pipelines/pipeline-with-aggregate.yaml | 1167 ------------- .../pipelines/pipeline-with-mocks.yaml | 1187 ------------- manifests/outputs/pipelines/scenario-3.yaml | 146 -- manifests/outputs/pipelines/scenario-5.yaml | 125 -- 7 files changed, 5436 deletions(-) delete mode 100644 manifests/outputs/features/regroup/success.yaml delete mode 100644 manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml delete mode 100644 manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml delete mode 100644 manifests/outputs/pipelines/pipeline-with-aggregate.yaml delete mode 100644 manifests/outputs/pipelines/pipeline-with-mocks.yaml delete mode 100644 manifests/outputs/pipelines/scenario-3.yaml delete mode 100644 manifests/outputs/pipelines/scenario-5.yaml diff --git a/manifests/outputs/features/regroup/success.yaml b/manifests/outputs/features/regroup/success.yaml deleted file mode 100644 index efc6d847f..000000000 --- a/manifests/outputs/features/regroup/success.yaml +++ /dev/null @@ -1,92 +0,0 @@ -name: regroup -description: successful path -initialize: - plugins: {} -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/features/regroup/success.yml -o - manifests/outputs/features/regroup/success.yml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:13:12.222Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - my-app: - pipeline: - regroup: - - cloud/region - - cloud/instance-type - children: - uk-west: - children: - A1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - B1: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 diff --git a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml deleted file mode 100644 index 906968735..000000000 --- a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml +++ /dev/null @@ -1,1212 +0,0 @@ -name: pipeline-with-aggregate -description: a full pipeline with the aggregate feature enabled -tags: null -aggregation: - metrics: - - carbon - type: both -initialize: - plugins: - interpolate: - path: builtin - method: Interpolation - config: - method: linear - x: - - 0 - - 10 - - 50 - - 100 - 'y': - - 0.12 - - 0.32 - - 0.75 - - 1.02 - input-parameter: cpu/utilization - output-parameter: cpu-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: - time: avg - component: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: - time: avg - component: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: - time: sum - component: sum - wattage-times-duration: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - wattage-to-energy-kwh: - path: builtin - method: Divide - config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: - time: none - component: none - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: - time: none - component: none - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: none - component: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: - time: avg - component: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - sci: - path: builtin - method: Sci - config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: - time: sum - component: sum - sum-carbon: - path: builtin - method: Sum - config: - input-parameters: - - carbon-operational - - embodied-carbon - output-parameter: carbon - parameter-metadata: - inputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - embodied-carbon: - unit: gCO2eq - description: Embodied carbon footprint - aggregation-method: - time: sum - component: sum - outputs: - carbon: - unit: gCO2eq - description: Total carbon footprint - aggregation-method: - time: sum - component: sum - time-sync: - path: builtin - method: TimeSync - config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: - time: none - component: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: - time: sum - component: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: - time: none - component: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: - time: none - component: none - time-reserved: - unit: seconds - description: time reserved for a component - aggregation-method: - time: avg - component: avg -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml -o - manifests/outputs/pipelines/outputs-if-diff/pipeline-with-aggregate.yaml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:13:45.889Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - aggregated: - carbon: 0.38611984715880265 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 10 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 15 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 14 - requests: 14 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3205 - cpu-wattage: 66.19999999999999 - cpu-wattage-times-duration: 203 - cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: null - cpu-energy-kwh: 0.000007048611111111113 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.0056388888888888895 - carbon: 0.045276128868594626 - sci: 0.0032340092048996163 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 13 - cloud/instance-type: null - cloud/region: null - requests: 9.571428571428571 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.30975 - cpu-wattage: 29.907142857142862 - cpu-wattage-times-duration: 192.25 - cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: null - cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.005340277777777777 - carbon: 0.044977517757483515 - sci: 0.004699143646304248 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 12 - cloud/instance-type: null - cloud/region: null - requests: 8.428571428571429 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 18.50952380952381 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005318601447686367 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 9 - requests: 3 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 1533.12 - time-reserved: 2160.2 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.22425 - cpu-wattage: 3.7375 - cpu-wattage-times-duration: 112.125 - cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: null - cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.02378234398782344 - carbon-operational: 0.0031145833333333334 - carbon: 0.02689692732115677 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.38611984715880265 - outputs: - - carbon: 0.045276128868594626 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.044977517757483515 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02689692732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.38611984715880265 - outputs: - - carbon: 0.045276128868594626 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.044977517757483515 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02689692732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - child-2: - pipeline: - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - aggregated: - carbon: 0.4092622082699138 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 150 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 110 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 180 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cpu/utilization: 22.8 - cloud/instance-type: null - cloud/region: null - requests: 220 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.41509999999999997 - cpu-wattage: 94.57999999999998 - cpu-wattage-times-duration: 258.9 - cpu-energy-raw: 0.00007191666666666668 - vcpu-ratio: null - cpu-energy-kwh: 0.000008989583333333334 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007191666666666666 - carbon: 0.046828906646372404 - sci: 0.00021285866657442002 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 29.6 - cloud/instance-type: null - cloud/region: null - requests: 92.85714285714285 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.48819999999999997 - cpu-wattage: 46.98428571428572 - cpu-wattage-times-duration: 308.35 - cpu-energy-raw: 0.00008565277777777778 - vcpu-ratio: null - cpu-energy-kwh: 0.000010706597222222223 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.008565277777777778 - carbon: 0.04820251775748351 - sci: 0.0005191040373882839 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 30.6 - cloud/instance-type: null - cloud/region: null - requests: 59.14285714285714 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.49894999999999995 - cpu-wattage: 31.31738095238095 - cpu-wattage-times-duration: 306.2 - cpu-energy-raw: 0.00008505555555555556 - vcpu-ratio: null - cpu-energy-kwh: 0.000010631944444444445 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.008505555555555556 - carbon: 0.04814279553526128 - sci: 0.0008140086201614227 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: null - cloud/region: null - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: null - cloud/region: null - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: null - cloud/region: null - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: null - cloud/region: null - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: null - cloud/region: null - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: null - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cpu/utilization: 19.8 - cloud/instance-type: null - cloud/region: null - requests: 18 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 1533.12 - time-reserved: 2160.2 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.34035000000000004 - cpu-wattage: 5.6725 - cpu-wattage-times-duration: 170.175 - cpu-energy-raw: 0.00004727083333333333 - vcpu-ratio: null - cpu-energy-kwh: 0.000005908854166666666 - embodied-carbon: 0.02378234398782344 - carbon-operational: 0.004727083333333333 - carbon: 0.02850942732115677 - sci: 0.0015838570733975985 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: null - cloud/region: null - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: null - cloud/region: null - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: null - cloud/region: null - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 0.8 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.4092622082699138 - outputs: - - carbon: 0.046828906646372404 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04820251775748351 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04814279553526128 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02850942732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.4092622082699138 - outputs: - - carbon: 0.046828906646372404 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04820251775748351 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04814279553526128 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02850942732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - outputs: - - carbon: 0.09210503551496703 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.09318003551496702 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.09297100773718923 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.05540635464231354 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.7953820554287163 diff --git a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml deleted file mode 100644 index 3afc34f3e..000000000 --- a/manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml +++ /dev/null @@ -1,1507 +0,0 @@ -name: pipeline-with-mocks -description: a full pipeline seeded with data from mock-observations feature -tags: null -aggregation: - metrics: - - carbon - type: both -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - config: - timestamp-from: 2023-12-12T00:00 - timestamp-to: 2023-12-12T00:10 - duration: 60 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - randint: - cpu/utilization: - min: 1 - max: 99 - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: - time: none - component: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: - time: sum - component: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: - time: none - component: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: - time: none - component: none - interpolate: - path: builtin - method: Interpolation - config: - method: linear - x: - - 0 - - 10 - - 50 - - 100 - 'y': - - 0.12 - - 0.32 - - 0.75 - - 1.02 - input-parameter: cpu/utilization - output-parameter: cpu-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: - time: avg - component: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: - time: avg - component: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: - time: sum - component: sum - wattage-times-duration: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - parameter-metadata: - inputs: - cpu-wattage: - unit: kWh - description: Energy used by the CPU - aggregation-method: - time: sum - component: sum - duration: - unit: seconds - description: Duration of the observation - aggregation-method: - time: sum - component: sum - outputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - wattage-to-energy-kwh: - path: builtin - method: Divide - config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: - time: none - component: none - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: - time: none - component: none - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: none - component: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - parameter-metadata: - inputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: none - component: none - outputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: - time: avg - component: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - sum-carbon: - path: builtin - method: Sum - config: - input-parameters: - - carbon-operational - - embodied-carbon - output-parameter: carbon - parameter-metadata: - inputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - embodied-carbon: - unit: gCO2eq - description: Embodied carbon footprint - aggregation-method: - time: sum - component: sum - outputs: - carbon: - unit: gCO2eq - description: Total carbon footprint - aggregation-method: - time: sum - component: sum - sci: - path: builtin - method: Sci - config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: - time: sum - component: sum - outputs: - sci: - unit: none - description: Scientific Carbon Intensity - aggregation-method: - time: none - component: none - time-sync: - path: builtin - method: TimeSync - config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true - parameter-metadata: - inputs: - time-reserved: - unit: seconds - description: time reserved for a component - aggregation-method: - time: avg - component: avg - outputs: - synced-time: - unit: none - description: Synced time - aggregation-method: - time: none - component: none -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/outputs-if-diff/pipeline-with-mocks.yaml -o - manifests/outputs/pipelines/outputs-if-diff/pipeline-with-mocks.yaml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:13:48.694Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - observe: - - mock-observations - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - aggregated: - carbon: 0.5505472444190767 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 17 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:01:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 17 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:02:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 90 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:03:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 10 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:04:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 59 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:05:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 64 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:06:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 46 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:07:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 28 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:08:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 40 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:09:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 60 - cpu/utilization: 37 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:05.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:10.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:15.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:20.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:25.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:30.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:35.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:40.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:45.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:50.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:00:55.000Z' - cloud/instance-type: null - cloud/region: null - duration: 5 - cpu/utilization: 13.6 - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.3162 - cpu-wattage: 3.2937499999999997 - cpu-wattage-times-duration: 197.625 - cpu-energy-raw: 0.00005489583333333334 - vcpu-ratio: null - cpu-energy-kwh: 0.000006861979166666667 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005489583333333334 - carbon: 0.04512682331303906 - sci: 0.018050729325215627 - - timestamp: '2023-12-12T00:01:00.000Z' - cloud/instance-type: null - cloud/region: null - duration: 1 - cpu/utilization: 17 - requests: 0.5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.39525 - cpu-wattage: 0.65875 - cpu-wattage-times-duration: 39.525 - cpu-energy-raw: 0.000010979166666666668 - vcpu-ratio: null - cpu-energy-kwh: 0.0000013723958333333335 - embodied-carbon: 0.007927447995941146 - carbon-operational: 0.0010979166666666667 - carbon: 0.009025364662607813 - sci: 0.018050729325215627 - aggregated: - carbon: 0.5505472444190767 - outputs: - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0.009025364662607813 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - aggregated: - carbon: 0.5505472444190767 - outputs: - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0.04512682331303906 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0.009025364662607813 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - child-2: - pipeline: - observe: - - mock-observations - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - aggregated: - carbon: 0.6495376610857433 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 60 - cpu/utilization: 93 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:01:00.000Z' - duration: 60 - cpu/utilization: 62 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:02:00.000Z' - duration: 60 - cpu/utilization: 66 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:03:00.000Z' - duration: 60 - cpu/utilization: 46 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:04:00.000Z' - duration: 60 - cpu/utilization: 60 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:05:00.000Z' - duration: 60 - cpu/utilization: 10 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:06:00.000Z' - duration: 60 - cpu/utilization: 62 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:07:00.000Z' - duration: 60 - cpu/utilization: 71 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:08:00.000Z' - duration: 60 - cpu/utilization: 21 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:09:00.000Z' - duration: 60 - cpu/utilization: 53 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cpu/utilization: 74.4 - cloud/instance-type: null - cloud/region: null - requests: 2.5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 2880 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.78576 - cpu-wattage: 8.185 - cpu-wattage-times-duration: 491.1 - cpu-energy-raw: 0.00013641666666666666 - vcpu-ratio: null - cpu-energy-kwh: 0.000017052083333333332 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013641666666666667 - carbon: 0.053278906646372394 - sci: 0.021311562658548958 - - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - cpu/utilization: 62 - cloud/instance-type: null - cloud/region: null - requests: 0.5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - cpu-factor: 0.8148 - cpu-wattage: 1.3579999999999999 - cpu-wattage-times-duration: 81.47999999999999 - cpu-energy-raw: 0.00002263333333333333 - vcpu-ratio: null - cpu-energy-kwh: 0.000002829166666666666 - embodied-carbon: 0.007927447995941146 - carbon-operational: 0.002263333333333333 - carbon: 0.010190781329274479 - sci: 0.020381562658548957 - aggregated: - carbon: 0.6495376610857433 - outputs: - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0.010190781329274479 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - aggregated: - carbon: 0.6495376610857433 - outputs: - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0.053278906646372394 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0.010190781329274479 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - outputs: - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0.09840572995941146 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - - carbon: 0.019216145991882292 - timestamp: '2023-12-12T00:01:00.000Z' - duration: 1 - aggregated: - carbon: 1.2000849055048197 diff --git a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml b/manifests/outputs/pipelines/pipeline-with-aggregate.yaml deleted file mode 100644 index 582e8351d..000000000 --- a/manifests/outputs/pipelines/pipeline-with-aggregate.yaml +++ /dev/null @@ -1,1167 +0,0 @@ -name: pipeline-with-aggregate -description: a full pipeline with the aggregate feature enabled -tags: null -aggregation: - metrics: - - carbon - type: both -initialize: - plugins: - interpolate: - path: builtin - method: Interpolation - config: - method: linear - x: - - 0 - - 10 - - 50 - - 100 - 'y': - - 0.12 - - 0.32 - - 0.75 - - 1.02 - input-parameter: cpu/utilization - output-parameter: cpu-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: - time: avg - component: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: - time: avg - component: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: - time: sum - component: sum - wattage-times-duration: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - wattage-to-energy-kwh: - path: builtin - method: Divide - config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: - time: copy - component: copy - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: - time: copy - component: copy - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: copy - component: copy - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: - time: avg - component: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - sci: - path: builtin - method: Sci - config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: - time: sum - component: sum - sum-carbon: - path: builtin - method: Sum - config: - input-parameters: - - carbon-operational - - embodied-carbon - output-parameter: carbon - parameter-metadata: - outputs: - carbon: - unit: gCO2eq - description: product of carbon - aggregation-method: - time: sum - component: sum - time-sync: - path: builtin - method: TimeSync - config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/pipeline-with-aggregate.yml -o - manifests/outputs/pipelines/pipeline-with-aggregate.yaml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T11:54:19.467Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 1 - cpu/utilization: 10 - requests: 10 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 20 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 5 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 15 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 15 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - requests: 30 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - cloud/instance-type: A1 - cloud/region: uk-west - duration: 5 - cpu/utilization: 14 - requests: 14 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.3205 - cpu-wattage: 66.19999999999999 - cpu-wattage-times-duration: 203 - cpu-energy-raw: 0.0000563888888888889 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000007048611111111113 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.0056388888888888895 - carbon: 0.045276128868594626 - sci: 0.0032340092048996163 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 13 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 9.571428571428571 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.30975 - cpu-wattage: 29.907142857142862 - cpu-wattage-times-duration: 192.25 - cpu-energy-raw: 0.00005340277777777778 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006675347222222222 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.005340277777777777 - carbon: 0.044977517757483515 - sci: 0.004699143646304248 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 12 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 8.428571428571429 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 18.50952380952381 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.0000064887152777777775 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005318601447686367 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - requests: 5 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 9 - requests: 3 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.22425 - cpu-wattage: 3.7375 - cpu-wattage-times-duration: 112.125 - cpu-energy-raw: 0.000031145833333333336 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000003893229166666667 - embodied-carbon: 0.02378234398782344 - carbon-operational: 0.0031145833333333334 - carbon: 0.02689692732115677 - sci: 0.00896564244038559 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 0 - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.38611984715880265 - outputs: - - carbon: 0.045276128868594626 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.044977517757483515 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02689692732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.38611984715880265 - outputs: - - carbon: 0.045276128868594626 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.044977517757483515 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02689692732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.38611984715880265 - child-2: - pipeline: - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - children: - uk-west: - children: - A1: - inputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 1 - cpu/utilization: 30 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 100 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:01.000Z' - duration: 5 - cpu/utilization: 28 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 150 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:06.000Z' - duration: 7 - cpu/utilization: 40 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 110 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - - timestamp: '2023-12-12T00:00:13.000Z' - duration: 30 - cpu/utilization: 33 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 180 - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - outputs: - - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cpu/utilization: 22.8 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 220 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.41509999999999997 - cpu-wattage: 94.57999999999998 - cpu-wattage-times-duration: 258.9 - cpu-energy-raw: 0.00007191666666666668 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000008989583333333334 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007191666666666666 - carbon: 0.046828906646372404 - sci: 0.00021285866657442002 - - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cpu/utilization: 29.6 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 92.85714285714285 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.48819999999999997 - cpu-wattage: 46.98428571428572 - cpu-wattage-times-duration: 308.35 - cpu-energy-raw: 0.00008565277777777778 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000010706597222222223 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.008565277777777778 - carbon: 0.04820251775748351 - sci: 0.0005191040373882839 - - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cpu/utilization: 30.6 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 59.14285714285714 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.49894999999999995 - cpu-wattage: 31.31738095238095 - cpu-wattage-times-duration: 306.2 - cpu-energy-raw: 0.00008505555555555556 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000010631944444444445 - embodied-carbon: 0.03963723997970574 - carbon-operational: 0.008505555555555556 - carbon: 0.04814279553526128 - sci: 0.0008140086201614227 - - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cpu/utilization: 26.4 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 30 - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.45380000000000004 - cpu-wattage: 9.454166666666667 - cpu-wattage-times-duration: 283.625 - cpu-energy-raw: 0.00007878472222222222 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000009848090277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.007878472222222222 - carbon: 0.04751571220192795 - sci: 0.0015838570733975983 - - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cpu/utilization: 19.8 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 18 - cpu/thermal-design-power: 60 - grid/carbon-intensity: 480 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0.34035000000000004 - cpu-wattage: 5.6725 - cpu-wattage-times-duration: 170.175 - cpu-energy-raw: 0.00004727083333333333 - vcpu-ratio: 8 - cpu-energy-kwh: 0.000005908854166666666 - embodied-carbon: 0.02378234398782344 - carbon-operational: 0.004727083333333333 - carbon: 0.02850942732115677 - sci: 0.0015838570733975985 - - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cpu/utilization: 0 - cloud/instance-type: A1 - cloud/region: uk-west - requests: 0 - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - time-reserved: 1 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: 8 - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.4092622082699138 - outputs: - - carbon: 0.046828906646372404 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04820251775748351 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04814279553526128 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02850942732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.4092622082699138 - outputs: - - carbon: 0.046828906646372404 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04820251775748351 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04814279553526128 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.04751571220192795 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.02850942732115677 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.4092622082699138 - outputs: - - carbon: 0.09210503551496703 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.09318003551496702 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.09297100773718923 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0.0923439244038559 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0.05540635464231354 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.7953820554287163 diff --git a/manifests/outputs/pipelines/pipeline-with-mocks.yaml b/manifests/outputs/pipelines/pipeline-with-mocks.yaml deleted file mode 100644 index bd27a179a..000000000 --- a/manifests/outputs/pipelines/pipeline-with-mocks.yaml +++ /dev/null @@ -1,1187 +0,0 @@ -name: pipeline-with-mocks -description: a full pipeline seeded with data from mock-observations feature -tags: null -aggregation: - metrics: - - carbon - type: both -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - config: - timestamp-from: '2023-12-12T00:00:00.000Z' - timestamp-to: '2023-12-12T00:00:13.000Z' - duration: 30 - components: - - cloud/instance-type: A1 - generators: - common: - cloud/region: uk-west - randint: - cpu/utilization: - min: 1 - max: 99 - parameter-metadata: - inputs: - timestamp: - unit: RFC3339 - description: refers to the time of occurrence of the input - aggregation-method: - time: none - component: none - duration: - unit: seconds - description: refers to the duration of the input - aggregation-method: - time: sum - component: sum - cloud/instance-type: - unit: none - description: type of Cloud Instance name used in the cloud provider APIs - aggregation-method: - time: none - component: none - cloud/region: - unit: none - description: region cloud instance - aggregation-method: - time: none - component: none - interpolate: - path: builtin - method: Interpolation - config: - method: linear - x: - - 0 - - 10 - - 50 - - 100 - 'y': - - 0.12 - - 0.32 - - 0.75 - - 1.02 - input-parameter: cpu/utilization - output-parameter: cpu-factor - parameter-metadata: - inputs: - cpu/utilization: - unit: percentage - description: refers to CPU utilization. - aggregation-method: - time: avg - component: avg - outputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu-factor-to-wattage: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-factor - - cpu/thermal-design-power - output-parameter: cpu-wattage - parameter-metadata: - inputs: - cpu-factor: - unit: kWh - description: result of interpolate - aggregation-method: - time: avg - component: avg - cpu/thermal-design-power: - unit: kWh - description: thermal design power for a processor - aggregation-method: - time: avg - component: avg - outputs: - cpu-wattage: - unit: kWh - description: the energy used by the CPU - aggregation-method: - time: sum - component: sum - wattage-times-duration: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-wattage - - duration - output-parameter: cpu-wattage-times-duration - parameter-metadata: - inputs: - cpu-wattage: - unit: kWh - description: Energy used by the CPU - aggregation-method: - time: sum - component: sum - duration: - unit: seconds - description: Duration of the observation - aggregation-method: - time: sum - component: sum - outputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - wattage-to-energy-kwh: - path: builtin - method: Divide - config: - numerator: cpu-wattage-times-duration - denominator: 3600000 - output: cpu-energy-raw - parameter-metadata: - inputs: - cpu-wattage-times-duration: - unit: kWh - description: CPU wattage multiplied by duration - aggregation-method: - time: sum - component: sum - outputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - calculate-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: vcpus-total - denominator: vcpus-allocated - output: vcpu-ratio - parameter-metadata: - inputs: - vcpus-total: - unit: count - description: total number of vcpus available on a particular resource - aggregation-method: - time: none - component: none - vcpus-allocated: - unit: count - description: number of vcpus allocated to particular resource - aggregation-method: - time: none - component: none - outputs: - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: none - component: none - correct-cpu-energy-for-vcpu-ratio: - path: builtin - method: Divide - config: - numerator: cpu-energy-raw - denominator: vcpu-ratio - output: cpu-energy-kwh - parameter-metadata: - inputs: - cpu-energy-raw: - unit: kWh - description: Raw energy used by CPU in kWh - aggregation-method: - time: sum - component: sum - vcpu-ratio: - unit: none - description: Ratio of vCPUs - aggregation-method: - time: none - component: none - outputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - sci-embodied: - path: builtin - method: SciEmbodied - operational-carbon: - path: builtin - method: Multiply - config: - input-parameters: - - cpu-energy-kwh - - grid/carbon-intensity - output-parameter: carbon-operational - parameter-metadata: - inputs: - cpu-energy-kwh: - unit: kWh - description: Corrected CPU energy in kWh - aggregation-method: - time: sum - component: sum - grid/carbon-intensity: - unit: gCO2eq/kWh - description: Carbon intensity for the grid - aggregation-method: - time: avg - component: avg - outputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - sum-carbon: - path: builtin - method: Sum - config: - input-parameters: - - carbon-operational - - embodied-carbon - output-parameter: carbon - parameter-metadata: - inputs: - carbon-operational: - unit: gCO2eq - description: Operational carbon footprint - aggregation-method: - time: sum - component: sum - embodied-carbon: - unit: gCO2eq - description: Embodied carbon footprint - aggregation-method: - time: sum - component: sum - outputs: - carbon: - unit: gCO2eq - description: Total carbon footprint - aggregation-method: - time: sum - component: sum - sci: - path: builtin - method: Sci - config: - functional-unit: requests - parameter-metadata: - inputs: - requests: - unit: none - description: expressed the final SCI value - aggregation-method: - time: sum - component: sum - outputs: - sci: - unit: none - description: Scientific Carbon Intensity - aggregation-method: - time: none - component: none - time-sync: - path: builtin - method: TimeSync - config: - start-time: '2023-12-12T00:00:00.000Z' - end-time: '2023-12-12T00:01:00.000Z' - interval: 5 - allow-padding: true -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/pipeline-with-mocks.yml -o - manifests/outputs/pipelines/pipeline-with-mocks.yml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:14:02.702Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child-1: - pipeline: - observe: - - mock-observations - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - requests: 50 - children: - uk-west: - children: - A1: - inputs: - - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - requests: 50 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 89 - outputs: - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 71.2 - cpu-factor: 0.76848 - cpu-wattage: 16.009999999999998 - cpu-wattage-times-duration: 480.3 - cpu-energy-raw: 0.00013341666666666667 - vcpu-ratio: null - cpu-energy-kwh: 0.000016677083333333333 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.013341666666666668 - carbon: 0.0529789066463724 - sci: 0.006357468797564688 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.3178734398782344 - outputs: - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.3178734398782344 - outputs: - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.0529789066463724 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.3178734398782344 - child-2: - pipeline: - observe: - - mock-observations - regroup: - - cloud/region - - cloud/instance-type - compute: - - interpolate - - cpu-factor-to-wattage - - wattage-times-duration - - wattage-to-energy-kwh - - calculate-vcpu-ratio - - correct-cpu-energy-for-vcpu-ratio - - sci-embodied - - operational-carbon - - sum-carbon - - time-sync - - sci - defaults: - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - requests: 50 - children: - uk-west: - children: - A1: - inputs: - - cpu/thermal-design-power: 100 - grid/carbon-intensity: 800 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: 8 - vcpus-allocated: 1 - requests: 50 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 30 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 15 - outputs: - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 80 - grid/carbon-intensity: 640 - device/emissions-embodied: 1533.12 - time-reserved: 3600 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 8.333333333333334 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 12 - cpu-factor: 0.29900000000000004 - cpu-wattage: 6.229166666666667 - cpu-wattage-times-duration: 186.875 - cpu-energy-raw: 0.00005190972222222223 - vcpu-ratio: null - cpu-energy-kwh: 0.000006488715277777778 - embodied-carbon: 0.03963723997970573 - carbon-operational: 0.005190972222222222 - carbon: 0.04482821220192795 - sci: 0.005379385464231354 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - - cpu/thermal-design-power: 0 - grid/carbon-intensity: 0 - device/emissions-embodied: 1533.12 - device/expected-lifespan: 94608000 - vcpus-total: null - vcpus-allocated: null - requests: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - cloud/instance-type: null - cloud/region: null - cpu/utilization: 0 - cpu-factor: 0 - cpu-wattage: 0 - cpu-wattage-times-duration: 0 - cpu-energy-raw: 0 - vcpu-ratio: null - cpu-energy-kwh: 0 - embodied-carbon: 0 - carbon-operational: 0 - carbon: 0 - sci: 0 - aggregated: - carbon: 0.2689692732115677 - outputs: - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.2689692732115677 - outputs: - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.04482821220192795 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.2689692732115677 - outputs: - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:00.000Z' - duration: 5 - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:05.000Z' - duration: 5 - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:10.000Z' - duration: 5 - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:15.000Z' - duration: 5 - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:20.000Z' - duration: 5 - - carbon: 0.09780711884830035 - timestamp: '2023-12-12T00:00:25.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:30.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:35.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:40.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:45.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:50.000Z' - duration: 5 - - carbon: 0 - timestamp: '2023-12-12T00:00:55.000Z' - duration: 5 - aggregated: - carbon: 0.5868427130898021 diff --git a/manifests/outputs/pipelines/scenario-3.yaml b/manifests/outputs/pipelines/scenario-3.yaml deleted file mode 100644 index 1f315baa4..000000000 --- a/manifests/outputs/pipelines/scenario-3.yaml +++ /dev/null @@ -1,146 +0,0 @@ -name: groupby -description: successful path -initialize: - plugins: - sum: - path: builtin - method: Sum - config: - input-parameters: - - cpu/energy - - network/energy - output-parameter: energy -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/scenario-3.yml -o - manifests/outputs/pipelines/scenario-3.yml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:13:43.098Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - my-app: - pipeline: - observe: null - regroup: - - cloud/instance-type - - cloud/region - compute: null - children: - uk-west: - children: - A1: - children: - uk-west: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 99 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-west - cpu/utilization: 12 - B1: - children: - uk-west: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-west - cpu/utilization: 1 - uk-east: - children: - A1: - children: - uk-east: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-east - cpu/utilization: 9 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-east - cpu/utilization: 23 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: A1 - cloud/region: uk-east - cpu/utilization: 12 - B1: - children: - uk-east: - inputs: - - timestamp: 2023-07-06T00:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-east - cpu/utilization: 11 - - timestamp: 2023-07-06T05:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-east - cpu/utilization: 67 - - timestamp: 2023-07-06T10:00 - duration: 300 - cloud/instance-type: B1 - cloud/region: uk-east - cpu/utilization: 1 diff --git a/manifests/outputs/pipelines/scenario-5.yaml b/manifests/outputs/pipelines/scenario-5.yaml deleted file mode 100644 index 4e9e0f011..000000000 --- a/manifests/outputs/pipelines/scenario-5.yaml +++ /dev/null @@ -1,125 +0,0 @@ -name: demo -description: null -tags: null -initialize: - plugins: - mock-observations: - path: builtin - method: MockObservations - config: - timestamp-from: 2023-07-06T00:00 - timestamp-to: 2023-07-06T00:01 - duration: 60 - components: - - cloud/instance-type: A1 - - cloud/instance-type: B1 - generators: - common: - region: uk-west - common-key: common-val - randint: - cpu/utilization: - min: 1 - max: 99 - memory/utilization: - min: 1 - max: 99 - sum: - path: builtin - method: Sum - config: - input-parameters: - - cpu/utilization - - memory/utilization - output-parameter: util-sum -execution: - command: >- - /Users/manushak/.npm/_npx/1bf7c3c15bf47d04/node_modules/.bin/ts-node - /Users/manushak/Documents/Projects/Green-Software/if/src/if-run/index.ts -m - manifests/examples/pipelines/scenario-5.yml -o - manifests/outputs/pipelines/scenario-5.yml - environment: - if-version: 0.6.0 - os: macOS - os-version: 14.6.1 - node-version: 18.20.4 - date-time: 2024-09-12T06:13:37.404Z (UTC) - dependencies: - - '@babel/core@7.22.10' - - '@babel/preset-typescript@7.23.3' - - '@commitlint/cli@18.6.0' - - '@commitlint/config-conventional@18.6.0' - - '@grnsft/if-core@0.0.22' - - '@jest/globals@29.7.0' - - '@types/jest@29.5.8' - - '@types/js-yaml@4.0.9' - - '@types/luxon@3.4.2' - - '@types/node@20.9.0' - - axios-mock-adapter@1.22.0 - - axios@1.7.2 - - cross-env@7.0.3 - - csv-parse@5.5.6 - - csv-stringify@6.4.6 - - fixpack@4.0.0 - - gts@5.2.0 - - husky@8.0.3 - - jest@29.7.0 - - js-yaml@4.1.0 - - lint-staged@15.2.2 - - luxon@3.4.4 - - release-it@16.3.0 - - rimraf@5.0.5 - - ts-command-line-args@2.5.1 - - ts-jest@29.1.1 - - typescript-cubic-spline@1.0.1 - - typescript@5.2.2 - - winston@3.11.0 - - zod@3.23.8 - status: success -tree: - children: - child: - pipeline: - observe: - - mock-observations - regroup: - - cloud/instance-type - compute: - - sum - children: - A1: - inputs: - - timestamp: '2023-07-06T00:00:00.000Z' - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: 65 - memory/utilization: 84 - outputs: - - timestamp: '2023-07-06T00:00:00.000Z' - duration: 60 - cloud/instance-type: A1 - region: uk-west - common-key: common-val - cpu/utilization: 65 - memory/utilization: 84 - util-sum: 149 - B1: - inputs: - - timestamp: '2023-07-06T00:00:00.000Z' - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: 70 - memory/utilization: 82 - outputs: - - timestamp: '2023-07-06T00:00:00.000Z' - duration: 60 - cloud/instance-type: B1 - region: uk-west - common-key: common-val - cpu/utilization: 70 - memory/utilization: 82 - util-sum: 152 From 6717f878109877a165e44f14b60aabd2a9305b74 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 10 Oct 2024 17:21:43 +0400 Subject: [PATCH 839/863] fix(.github): add npm build to github workflow --- .github/workflows/release-commit.yml | 5 ++++- .github/workflows/release-publish.yml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-commit.yml b/.github/workflows/release-commit.yml index 8ffa665f7..b70b151ae 100644 --- a/.github/workflows/release-commit.yml +++ b/.github/workflows/release-commit.yml @@ -67,6 +67,9 @@ jobs: - name: Install dependencies run: npm ci + - name: Build project + run: npm run build + - name: Initialize git user email run: git config --global user.email "${{ vars.RELEASE_USER_EMAIL }}" @@ -94,4 +97,4 @@ jobs: - name: Create pull request run: gh pr create -B ${{ vars.RELEASE_BRANCH_NAME }} -H $PR_BRANCH_NAME --title "Release ${{github.event.release.tag_name}}" --body "${{github.event.release.body}}" env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 3261fa840..c014a176e 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -26,6 +26,9 @@ jobs: - name: Run integration tests run: npm run if-check -- -d manifests/outputs + - name: Build project + run: npm run build + - name: Initialize git user email run: git config --global user.email "${{ env.RELEASE_USER_EMAIL }}" @@ -70,4 +73,4 @@ jobs: run: npm publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} From 12bf620bf7b83ccba4288fe8447cd22bf4fc312e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 10 Oct 2024 17:22:44 +0400 Subject: [PATCH 840/863] =?UTF-8?q?chore(release):=20v0.7.1=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 265 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 172 insertions(+), 95 deletions(-) diff --git a/package-lock.json b/package-lock.json index 43766c712..177c80514 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@grnsft/if", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@grnsft/if", - "version": "0.7.0", + "version": "0.7.1", "license": "MIT", "dependencies": { "@commitlint/cli": "^18.6.0", @@ -2703,9 +2703,9 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -3329,9 +3329,9 @@ } }, "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -3341,15 +3341,15 @@ } }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -3583,12 +3583,12 @@ } }, "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/compare-func": { @@ -3913,11 +3913,12 @@ } }, "node_modules/debug": { - "version": "4.3.4", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -4338,6 +4339,18 @@ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.2", "license": "MIT", @@ -5248,6 +5261,20 @@ "dev": true, "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "license": "MIT", @@ -7864,12 +7891,15 @@ } }, "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -7877,21 +7907,21 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -8050,16 +8080,16 @@ } }, "node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", - "rfdc": "^1.3.0", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -8067,9 +8097,9 @@ } }, "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -8091,15 +8121,15 @@ } }, "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, "node_modules/listr2/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -8266,14 +8296,14 @@ } }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -8285,21 +8315,24 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -8321,24 +8354,24 @@ } }, "node_modules/log-update/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, "node_modules/log-update/node_modules/is-fullwidth-code-point": { @@ -8356,22 +8389,49 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", @@ -8389,9 +8449,9 @@ } }, "node_modules/log-update/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", @@ -8586,11 +8646,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8623,6 +8684,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", @@ -8682,8 +8755,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "license": "MIT" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mute-stream": { "version": "0.0.8", @@ -10305,9 +10379,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, "node_modules/rimraf": { @@ -11830,10 +11904,13 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index 6aaed3cf1..cd8d79fc8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@grnsft/if", "description": "Impact Framework", - "version": "0.7.0", + "version": "0.7.1", "author": { "name": "Green Software Foundation", "email": "info@gsf.com" From aa4498775cf36d20d9d504bfc9f5dc9985b654ae Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 10 Oct 2024 17:30:46 +0400 Subject: [PATCH 841/863] fix(package): add prepublish script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index cd8d79fc8..558415eee 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", + "prepublish": "npm run build", "release": "release-it", "test": "jest --verbose --testPathPattern=src/__tests__/" }, From a8d783fd505f033a1dd5142ba86a6e27aaea0236 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 10 Oct 2024 17:32:53 +0400 Subject: [PATCH 842/863] revert(.github): build step from workflows --- .github/workflows/release-commit.yml | 3 --- .github/workflows/release-publish.yml | 3 --- 2 files changed, 6 deletions(-) diff --git a/.github/workflows/release-commit.yml b/.github/workflows/release-commit.yml index b70b151ae..7172083c1 100644 --- a/.github/workflows/release-commit.yml +++ b/.github/workflows/release-commit.yml @@ -67,9 +67,6 @@ jobs: - name: Install dependencies run: npm ci - - name: Build project - run: npm run build - - name: Initialize git user email run: git config --global user.email "${{ vars.RELEASE_USER_EMAIL }}" diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index c014a176e..a71a694aa 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -26,9 +26,6 @@ jobs: - name: Run integration tests run: npm run if-check -- -d manifests/outputs - - name: Build project - run: npm run build - - name: Initialize git user email run: git config --global user.email "${{ env.RELEASE_USER_EMAIL }}" From a8a5f9e048748b8191728a6ed7d9a6464cee6b85 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Thu, 10 Oct 2024 21:42:09 +0400 Subject: [PATCH 843/863] feat(package): tune configuration --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 558415eee..343382e78 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,12 @@ "email": "info@gsf.com" }, "bin": { - "if-diff": "./build/if-diff/index.js", - "if-run": "./build/if-run/index.js", - "if-env": "./build/if-env/index.js", - "if-check": "./build/if-check/index.js", - "if-csv": "./build/if-csv/index.js", - "if-merge": "./build/if-merge/index.js" + "if-diff": "build/if-diff/index.js", + "if-run": "build/if-run/index.js", + "if-env": "build/if-env/index.js", + "if-check": "build/if-check/index.js", + "if-csv": "build/if-csv/index.js", + "if-merge": "build/if-merge/index.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -70,7 +70,7 @@ "access": "public" }, "repository": { - "url": "https://github.com/Green-Software-Foundation/if" + "url": "git+https://github.com/Green-Software-Foundation/if.git" }, "scripts": { "build": "npm run clean && tsc --project tsconfig.build.json", @@ -87,7 +87,7 @@ "lint": "gts lint", "pre-commit": "lint-staged", "prepare": "husky install", - "prepublish": "npm run build", + "prepublishOnly": "npm run build", "release": "release-it", "test": "jest --verbose --testPathPattern=src/__tests__/" }, From 756fc1e250a831ccddaeb8b6adbccac861479c63 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Fri, 11 Oct 2024 20:12:04 +0400 Subject: [PATCH 844/863] refactor(lib): prettify the regroup code --- src/if-run/lib/regroup.ts | 127 +++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 69 deletions(-) diff --git a/src/if-run/lib/regroup.ts b/src/if-run/lib/regroup.ts index 7e39b1c89..55d8f8221 100644 --- a/src/if-run/lib/regroup.ts +++ b/src/if-run/lib/regroup.ts @@ -7,93 +7,82 @@ import {validate} from '../../common/util/validations'; import {STRINGS} from '../config'; const {InvalidGroupingError} = ERRORS; - const {INVALID_GROUP_KEY, REGROUP_ERROR} = STRINGS; /** - * Grouping strategy. + * Creates structure to insert inputs by groups. */ -export const Regroup = ( - inputs: PluginParams[], - outputs: PluginParams[], +const appendGroup = ( + value: PluginParams, + object: any, + target: string, groups: string[] -) => { - /** - * Creates structure to insert inputs by groups. - */ - const appendGroup = ( - value: PluginParams, - object: any, - target: string, - groups: string[] - ) => { - if (groups.length > 0) { - const group = groups.shift() as string; - - object.children = object.children ?? {}; - object.children[group] = object.children[group] ?? {}; +): any => { + if (groups.length === 0) { + object[target] = object[target] || []; + object[target].push(value); + return object; + } - if (groups.length === 0) { - if ( - object.children[group][target] && - object.children[group][target].length > 0 - ) { - object.children[group][target].push(value); - } else { - object.children[group][target] = [value]; - } - } + const group = groups.shift()!; + object.children = object.children || {}; + object.children[group] = object.children[group] || {}; - appendGroup(value, object.children[group], target, groups); - } + return appendGroup(value, object.children[group], target, groups); +}; - return object; - }; +/** + * Validates the groups array. + */ +const validateGroups = (groups: string[]): string[] => { + const inputData = {regroup: groups}; + const validationSchema = z.record( + z.string(), + z.array(z.string(), {message: REGROUP_ERROR}).min(1) + ); - /** - * Validates groups array. - */ - const validateGroups = (regroup: string[]) => { - const inputData = {regroup}; - const validationSchema = z.record( - z.string(), - z.array(z.string(), {message: REGROUP_ERROR}).min(1) - ); + validate(validationSchema, inputData); - validate(validationSchema, inputData); + return groups; +}; - return groups; - }; +/** + * Looks up a group key value in the input. + */ +const lookupGroupKey = (input: PluginParams, groupKey: string): string => { + if (!input[groupKey]) { + throw new InvalidGroupingError(INVALID_GROUP_KEY(groupKey)); + } - /** - * Interates over inputs, grabs group values for each one. - * Based on grouping, initializes the structure. - */ + return input[groupKey]; +}; +/** + * Regroups inputs and outputs based on the given group keys. + */ +export const Regroup = ( + inputs: PluginParams[], + outputs: PluginParams[], + groups: string[] +): any => { const validatedGroups = validateGroups(groups); - const lookupGroupKey = (input: PluginParams, groupKey: string) => { - if (!input[groupKey]) { - throw new InvalidGroupingError(INVALID_GROUP_KEY(groupKey)); + const appendToAccumulator = ( + items: PluginParams[], + acc: any, + target: string + ) => { + for (const item of items) { + const groupsWithData = validatedGroups.map(groupKey => + lookupGroupKey(item, groupKey) + ); + appendGroup(item, acc, target, groupsWithData); } - - return input[groupKey]; }; - let acc = {} as any; - for (const input of inputs) { - const groupsWithData = validatedGroups.map(groupKey => - lookupGroupKey(input, groupKey) - ); - acc = appendGroup(input, acc, 'inputs', groupsWithData); - } - - for (const output of outputs) { - const groupsWithData = validatedGroups.map(groupKey => - lookupGroupKey(output, groupKey) - ); - acc = appendGroup(output, acc, 'outputs', groupsWithData); - } + const acc = {} as any; + appendToAccumulator(inputs, acc, 'inputs'); + appendToAccumulator(outputs, acc, 'outputs'); return acc.children; }; From 45dde859eb86ebff02acf2acc9835854b41c5fa5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 16:46:20 +0400 Subject: [PATCH 845/863] feat(builtins): enable interpolation to accept 0 or off values --- src/if-run/builtins/interpolation/index.ts | 28 +++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index 30226e5a6..d980ba521 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -54,12 +54,13 @@ export const Interpolation = PluginFactory({ .object({ timestamp: z.string().or(z.date()), duration: z.number(), - [inputParameter]: z.number().gt(0), + [inputParameter]: z.number().gte(0).or(z.literal('off')), }) .refine( data => - data[inputParameter] >= config.x[0] && - data[inputParameter] <= config.x[config.x.length - 1], + (data[inputParameter] >= config.x[0] && + data[inputParameter] <= config.x[config.x.length - 1]) || + data[inputParameter] === 'off', { message: WITHIN_THE_RANGE, } @@ -68,14 +69,22 @@ export const Interpolation = PluginFactory({ return validate>(schema, input, index); }, implementation: async (inputs: PluginParams[], config: ConfigParams) => { - const {'output-parameter': outputParameter} = config; + const { + 'input-parameter': inputParameter, + 'output-parameter': outputParameter, + } = config; return inputs.map(input => { - const calculatedResult = calculateResult(config, input); + if (input[inputParameter] === 'off') { + return { + ...input, + [inputParameter]: 0, + }; + } return { ...input, - [outputParameter]: calculatedResult, + [outputParameter]: calculateResult(config, input), }; }); }, @@ -169,7 +178,8 @@ const getPolynomialInterpolation = ( return result; }; +/** + * Sorts given point items in ascending order. + */ const sortPoints = (items: number[]) => - items.sort((a: number, b: number) => { - return a - b; - }); + items.sort((a: number, b: number) => a - b); From a9de9d341a8b1170b8118cdb247bfef45b83b35e Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 16:48:06 +0400 Subject: [PATCH 846/863] fix(lib): in compute rename inputsStorage to outputsStorage --- src/if-run/lib/compute.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 5e73cbbb4..577790caf 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -99,8 +99,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { }); } - let inputStorage = structuredClone(node.inputs) as PluginParams[]; - inputStorage = mergeDefaults(inputStorage, defaults); + let outputStorage = structuredClone(node.inputs) as PluginParams[]; + outputStorage = mergeDefaults(outputStorage, defaults); const pipelineCopy = structuredClone(pipeline) || {}; /** Checks if pipeline is not an array or empty object. */ @@ -125,8 +125,8 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { const plugin = params.pluginStorage.get(pluginName); const nodeConfig = config && config[pluginName]; - inputStorage = await plugin.execute(inputStorage, nodeConfig); - node.inputs = inputStorage; + outputStorage = await plugin.execute(outputStorage, nodeConfig); + node.inputs = outputStorage; if (params.context.explainer) { addExplainData({ @@ -145,7 +145,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { const originalOutputs = params.append ? node.outputs || [] : []; node.children = Regroup( - inputStorage, + outputStorage, originalOutputs, pipelineCopy.regroup ); @@ -183,10 +183,12 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); debugLogger.setExecutingPluginName(pluginName); - inputStorage = await plugin.execute(inputStorage, nodeConfig); + console.log(outputStorage); + outputStorage = await plugin.execute(outputStorage, nodeConfig); + console.log(outputStorage); debugLogger.setExecutingPluginName(); - node.outputs = inputStorage; + node.outputs = outputStorage; if (params.context.explainer) { addExplainData({ From addb108f781193106b499d73bdaa3479ad352ca0 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 16:48:34 +0400 Subject: [PATCH 847/863] chore(package): update if-core version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 177c80514..40ce27219 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.25", + "@grnsft/if-core": "^0.0.26", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.25", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.25.tgz", - "integrity": "sha512-1W4SXsXhXos06q4SBPc8QpgQPDhHEc03njrGcd/X2UiJyh0ycBKTqGCjuRPRipEayGgUxO0DwRNOgNcgzzcDkA==", + "version": "0.0.26", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.26.tgz", + "integrity": "sha512-j8oO4/2y+229ei2LObZtwZJYey/3vqZVErsad0tCQp++aVAoP6y8/0iVRGbOUw7Mg7UITRXFcbnbN6Kgy0Ix4A==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index 343382e78..af1d81624 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.25", + "@grnsft/if-core": "^0.0.26", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 7039956a6970d703bcfb4b0e6e772d3febeb6352 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 16:51:19 +0400 Subject: [PATCH 848/863] feat(manifests): add success with off to interpolation --- .../interpolation/success-with-off.yml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 manifests/examples/builtins/interpolation/success-with-off.yml diff --git a/manifests/examples/builtins/interpolation/success-with-off.yml b/manifests/examples/builtins/interpolation/success-with-off.yml new file mode 100644 index 000000000..0aebabbf4 --- /dev/null +++ b/manifests/examples/builtins/interpolation/success-with-off.yml @@ -0,0 +1,24 @@ +name: interpolation-demo +description: simple demo of interpolation plugin +tags: +initialize: + plugins: + interpolation: + method: Interpolation + path: "builtin" + 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: off From a379f158095a34857c86425b57922cc66ed10e03 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 16:59:55 +0400 Subject: [PATCH 849/863] feat(doc): update interpolation README --- src/if-run/builtins/interpolation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/if-run/builtins/interpolation/README.md b/src/if-run/builtins/interpolation/README.md index d328dc9aa..9b62e7000 100644 --- a/src/if-run/builtins/interpolation/README.md +++ b/src/if-run/builtins/interpolation/README.md @@ -62,7 +62,7 @@ The plugin expects the following input parameters: - `timestamp`: a timestamp for the input (required) - `duration`: the amount of time, in seconds, that the input covers. (required) -- `[input-parameter]` - a field whose name matches the string provided to input-parameter in config (i.e. if the input-parameter in config is cpu/utilisation then cpu-utilisation must exist in the input data) +- `[input-parameter]` - a field whose name matches the string provided to input-parameter in config (i.e. if the input-parameter in config is cpu/utilisation then cpu-utilisation must exist in the input data). Value can be greater or equal to 0. For modeling server which totally turned off, `off` value can be used. ## Output From 702b96146e9d1a40c20eab6dd0d8a48a84176818 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 18:55:12 +0400 Subject: [PATCH 850/863] test(builtins): add cases to cover interpolation input 0 and off --- .../if-run/builtins/interpolation.test.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index be379b3d3..268d9ebf8 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -55,6 +55,49 @@ describe('builtins/interpolation: ', () => { expect(result).toEqual(outputs); }); + it('returns valid output parameter if input parameter is 0.', async () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 0, + }, + ]; + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 0, + 'interpolation-result': 0.12, + }, + ]; + + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); + }); + + it('returns no output parameter if input parameter is `off`.', async () => { + const inputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 'off', + }, + ]; + const outputs = [ + { + timestamp: '2023-07-06T00:00', + duration: 3600, + 'cpu/utilization': 0, + }, + ]; + + const result = await plugin.execute(inputs); + + expect(result).toEqual(outputs); + }); + it('returns result when `mapping` has valid data.', async () => { const mapping = { 'cpu/utilization': 'cpu/util', From a00faca6f14ac0141ec03be3e3a1789b45429060 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Tue, 15 Oct 2024 18:57:59 +0400 Subject: [PATCH 851/863] fix(.github): update pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 50c9aabaf..9254fe1fd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,11 +4,8 @@ - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) -- [ ] My code follows the code style of this project. -- [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. -- [ ] All new and existing tests passed. ### A description of the changes proposed in the Pull Request From 004a73f835139a44171b28f324c4788b4f9e95c4 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 16 Oct 2024 11:52:05 +0400 Subject: [PATCH 852/863] fix(lib): remove console.log Co-authored-by: Manushak Keramyan Signed-off-by: Narek Hovhannisyan --- src/if-run/lib/compute.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 577790caf..81bc768e1 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -183,7 +183,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { console.debug(COMPUTING_PIPELINE_FOR_NODE(pluginName)); debugLogger.setExecutingPluginName(pluginName); - console.log(outputStorage); outputStorage = await plugin.execute(outputStorage, nodeConfig); console.log(outputStorage); debugLogger.setExecutingPluginName(); From 6200ad4b75b241ca2bf7d097f9def0b97cb0e70c Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 21 Oct 2024 12:57:25 +0400 Subject: [PATCH 853/863] chore(package): update if core version to 0.0.28 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40ce27219..ded744c52 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.26", + "@grnsft/if-core": "^0.0.28", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", @@ -1186,9 +1186,9 @@ } }, "node_modules/@grnsft/if-core": { - "version": "0.0.26", - "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.26.tgz", - "integrity": "sha512-j8oO4/2y+229ei2LObZtwZJYey/3vqZVErsad0tCQp++aVAoP6y8/0iVRGbOUw7Mg7UITRXFcbnbN6Kgy0Ix4A==", + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@grnsft/if-core/-/if-core-0.0.28.tgz", + "integrity": "sha512-DM88HFeBbR1yl3bU0vFRgy6FnmUiyP4KhmtXp7HK1tMQHtnuKxzdPSxbfdpHsnUuHlvgDG7R/dI67/PmQD4U5w==", "dependencies": { "typescript": "^5.1.6", "zod": "^3.23.8" diff --git a/package.json b/package.json index af1d81624..7a05f5742 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", - "@grnsft/if-core": "^0.0.26", + "@grnsft/if-core": "^0.0.28", "axios": "^1.7.2", "csv-parse": "^5.5.6", "csv-stringify": "^6.4.6", From 47731dd8415180d20f813629cceca9a652586f07 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 21 Oct 2024 12:57:39 +0400 Subject: [PATCH 854/863] feat(builtins): return zero output param if input `is off` --- src/if-run/builtins/interpolation/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-run/builtins/interpolation/index.ts b/src/if-run/builtins/interpolation/index.ts index d980ba521..bfc39e3c8 100644 --- a/src/if-run/builtins/interpolation/index.ts +++ b/src/if-run/builtins/interpolation/index.ts @@ -79,6 +79,7 @@ export const Interpolation = PluginFactory({ return { ...input, [inputParameter]: 0, + [outputParameter]: 0, }; } From c4e47651f786850b3fecb3b34f06bf1d39d21248 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Mon, 21 Oct 2024 12:59:17 +0400 Subject: [PATCH 855/863] test(builtins): update interpolation units --- src/__tests__/if-run/builtins/interpolation.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/__tests__/if-run/builtins/interpolation.test.ts b/src/__tests__/if-run/builtins/interpolation.test.ts index 268d9ebf8..dd5381529 100644 --- a/src/__tests__/if-run/builtins/interpolation.test.ts +++ b/src/__tests__/if-run/builtins/interpolation.test.ts @@ -90,6 +90,7 @@ describe('builtins/interpolation: ', () => { timestamp: '2023-07-06T00:00', duration: 3600, 'cpu/utilization': 0, + 'interpolation-result': 0, }, ]; From dc06a78fa91220d4178f00d987bede503721e946 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 29 Oct 2024 20:28:33 +0400 Subject: [PATCH 856/863] feat(config): add strings for explain --- src/common/config/strings.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/common/config/strings.ts b/src/common/config/strings.ts index e5884852b..62cb0baa2 100644 --- a/src/common/config/strings.ts +++ b/src/common/config/strings.ts @@ -11,7 +11,11 @@ Incubation projects are experimental, offer no support guarantee, have minimal g MANIFEST_IS_MISSING: 'Manifest is missing.', DIRECTORY_NOT_FOUND: 'Directory not found.', AGGREGATION_UNITS_NOT_MATCH: (param: string) => - `Your manifest uses two instances of ${param} with different units. Please check that you are using consistent units for ${param} throughout your manifest.`, + `Your manifest uses two instances of \`${param}\` with different units. Please check that you are using consistent units for \`${param}\` throughout your manifest.`, AGGREGATION_METHODS_NOT_MATCH: (param: string) => - `Your manifest uses two instances of ${param} with different 'aggregation-method'. Please check that you are using right 'aggregation-method' for ${param} throughout your manifest.`, + `Your manifest uses two instances of \`${param}\` with different 'aggregation-method'. Please check that you are using right 'aggregation-method' for \`${param}\` throughout your manifest.`, + MISSING_INPUTS_PARAMETER: (pluginName: string) => + `The inputs parameter metadata of the \`${pluginName}\` plugin is missing.`, + MISSING_OUTPUTS_PARAMETER: (pluginName: string) => + `The outputs parameter metadata of the \`${pluginName}\` plugin is missing.`, }; From d1e3e8287315ae2c8011abe406b5579e3a8ba8f7 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 29 Oct 2024 20:30:47 +0400 Subject: [PATCH 857/863] feat(types): update ExplainStorageType and ExplainParams types --- src/if-run/types/explain.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/if-run/types/explain.ts b/src/if-run/types/explain.ts index caedd3992..8fc51ac10 100644 --- a/src/if-run/types/explain.ts +++ b/src/if-run/types/explain.ts @@ -1,19 +1,14 @@ -import {AggregationOptions, ParameterMetadata} from '@grnsft/if-core/types'; - -import {PluginOptions} from '../../common/types/manifest'; +import {ParameterMetadata} from '@grnsft/if-core/types'; export type ExplainParams = { pluginName: string; - pluginData: PluginOptions; metadata: {inputs?: ParameterMetadata; outputs?: ParameterMetadata}; }; export type ExplainStorageType = Record< string, { - plugins: string[]; - unit: string; - description: string; - 'aggregation-method': AggregationOptions; + inputs?: ParameterMetadata; + outputs?: ParameterMetadata; } >; From 890a9c5b652394976b05f1eb287d7b7b2c3753f5 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 29 Oct 2024 20:32:15 +0400 Subject: [PATCH 858/863] feat(lib): update explain feature --- src/if-run/lib/compute.ts | 4 +- src/if-run/lib/explain.ts | 147 +++++++++++++++++++++++++------------- 2 files changed, 100 insertions(+), 51 deletions(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 81bc768e1..0381fee10 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -132,7 +132,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { addExplainData({ pluginName, metadata: plugin.metadata, - pluginData: params.context.initialize!.plugins[pluginName], }); } } @@ -184,7 +183,7 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { debugLogger.setExecutingPluginName(pluginName); outputStorage = await plugin.execute(outputStorage, nodeConfig); - console.log(outputStorage); + debugLogger.setExecutingPluginName(); node.outputs = outputStorage; @@ -193,7 +192,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { addExplainData({ pluginName, metadata: plugin.metadata, - pluginData: params.context.initialize!.plugins[pluginName], }); } } diff --git a/src/if-run/lib/explain.ts b/src/if-run/lib/explain.ts index 470eed2e7..017d20f5d 100644 --- a/src/if-run/lib/explain.ts +++ b/src/if-run/lib/explain.ts @@ -1,82 +1,133 @@ +import {ParameterMetadata} from '@grnsft/if-core/types'; import {ERRORS} from '@grnsft/if-core/utils'; import {STRINGS} from '../../common/config'; +import {logger} from '../../common/util/logger'; + import {ExplainParams, ExplainStorageType} from '../types/explain'; const {ManifestValidationError} = ERRORS; -const {AGGREGATION_UNITS_NOT_MATCH, AGGREGATION_METHODS_NOT_MATCH} = STRINGS; +const { + AGGREGATION_UNITS_NOT_MATCH, + AGGREGATION_METHODS_NOT_MATCH, + MISSING_INPUTS_PARAMETER, + MISSING_OUTPUTS_PARAMETER, +} = STRINGS; /** * Retrieves stored explain data. */ -export const explain = () => storeExplainData.parameters; +export const explain = () => storeExplainData.plugins; /** * Manages the storage of explain data. */ const storeExplainData = (() => { - let parameter: ExplainStorageType = {}; + let plugins: ExplainStorageType = {}; - const parameterManager = { - get parameters() { - return parameter; + const pluginManager = { + get plugins() { + return plugins; }, - set parameters(value: ExplainStorageType) { - parameter = value; + set plugins(value: ExplainStorageType) { + plugins = value; }, }; - return parameterManager; + return pluginManager; })(); /** * Adds new explain data to the stored explain data. */ export const addExplainData = (params: ExplainParams) => { - const {pluginName, pluginData, metadata} = params; - const parameterMetadata = pluginData?.['parameter-metadata'] || metadata; - const parameters = storeExplainData.parameters; - const allParameters = { - ...parameterMetadata?.inputs, - ...parameterMetadata?.outputs, - } as ExplainStorageType; - - Object.entries(allParameters).forEach(([name, meta]) => { - const existingParameter = parameters[name]; - - if (parameters[name]?.plugins?.includes(pluginName)) { - return; - } + const {pluginName, metadata} = params; + const plugin: ExplainStorageType = { + [pluginName]: { + inputs: metadata?.inputs ?? {}, + outputs: metadata?.outputs ?? {}, + }, + }; - if (existingParameter) { - if (meta.unit !== existingParameter.unit) { - throw new ManifestValidationError(AGGREGATION_UNITS_NOT_MATCH(name)); - } + const isInputsMissing = !Object.keys(plugin[pluginName].inputs || {}).length; + const isOutputsMissing = !Object.keys(plugin[pluginName].outputs || {}) + .length; + + if (isInputsMissing) { + delete plugin[pluginName].inputs; + + logger.warn(MISSING_INPUTS_PARAMETER(pluginName)); + } + + if (isOutputsMissing) { + delete plugin[pluginName].outputs; + + logger.warn(MISSING_OUTPUTS_PARAMETER(pluginName)); + } + + checkMetadatas(metadata); + + if (!isInputsMissing || !isOutputsMissing) { + storeExplainData.plugins = { + ...storeExplainData.plugins, + ...plugin, + }; + } +}; - if ( - meta['aggregation-method'].component !== - existingParameter['aggregation-method'].component || - meta['aggregation-method'].time !== - existingParameter['aggregation-method'].time - ) { - throw new ManifestValidationError(AGGREGATION_METHODS_NOT_MATCH(name)); +/** + * Checks if the 'unit' and 'aggregation-method' of the parameter are the same throughout the manifest + */ +const checkMetadatas = (metadata: { + inputs?: ParameterMetadata; + outputs?: ParameterMetadata; +}) => { + const inputsOutputsMetadata = {...metadata?.inputs, ...metadata?.outputs}; + const storedParameters: any = {}; + + // Populate stored parameters with metadata from each plugin + Object.values(storeExplainData.plugins).forEach(plugin => { + const storedInputOutputMetadata = {...plugin.inputs, ...plugin.outputs}; + + Object.keys(storedInputOutputMetadata).forEach(parameter => { + if (!storedParameters[parameter]) { + storedParameters[parameter] = { + unit: storedInputOutputMetadata[parameter].unit, + 'aggregation-method': + storedInputOutputMetadata[parameter]['aggregation-method'], + }; } + }); + }); + + // Validate input-output metadata against stored parameters + Object.keys(inputsOutputsMetadata).forEach(parameterName => { + const parameter = inputsOutputsMetadata[parameterName]; + const storedParameter = storedParameters[parameterName]; - existingParameter.plugins.push(pluginName); - existingParameter.description = - meta.description || existingParameter.description; - } else { - parameters[name] = { - plugins: [pluginName], - unit: meta.unit, - description: meta.description, - 'aggregation-method': meta['aggregation-method'], - }; + if ( + parameter && + Object.keys(storedParameters).includes(parameterName) && + storedParameter.unit !== parameter.unit + ) { + throw new ManifestValidationError( + AGGREGATION_UNITS_NOT_MATCH(parameterName) + ); } - }); - storeExplainData.parameters = { - ...parameters, - }; + // Check for aggregation-method mismatch + const inputAggregation = parameter['aggregation-method']; + + if ( + storedParameter && + (storedParameter['aggregation-method']?.component !== + inputAggregation?.component || + storedParameter['aggregation-method']?.time !== inputAggregation?.time) + ) { + throw new ManifestValidationError( + AGGREGATION_METHODS_NOT_MATCH(parameterName) + ); + } + }); }; From 50fe84e02bcd2a8b39486263a2bff5b0e1e5c0f2 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 29 Oct 2024 20:33:14 +0400 Subject: [PATCH 859/863] test(lib): update explain feature's tests --- src/__tests__/if-run/lib/explain.test.ts | 125 +++++++++++------------ 1 file changed, 60 insertions(+), 65 deletions(-) diff --git a/src/__tests__/if-run/lib/explain.test.ts b/src/__tests__/if-run/lib/explain.test.ts index df86448ac..a6049f500 100644 --- a/src/__tests__/if-run/lib/explain.test.ts +++ b/src/__tests__/if-run/lib/explain.test.ts @@ -13,10 +13,6 @@ describe('lib/explain: ', () => { const mockData = { pluginName: 'divide', metadata: {kind: 'execute', inputs: undefined, outputs: undefined}, - pluginData: { - path: 'builtin', - method: 'Divide', - }, }; addExplainData(mockData); @@ -50,30 +46,29 @@ describe('lib/explain: ', () => { }, }, }, - pluginData: { - path: 'builtin', - method: 'Sum', - }, }; const expectedResult = { - 'cpu/energy': { - plugins: ['sum'], - unit: 'kWh', - description: 'energy consumed by the cpu', - 'aggregation-method': 'sum', - }, - 'network/energy': { - plugins: ['sum'], - unit: 'kWh', - description: 'energy consumed by data ingress and egress', - 'aggregation-method': 'sum', - }, - 'energy-sum': { - plugins: ['sum'], - unit: 'kWh', - description: 'sum of energy components', - 'aggregation-method': 'sum', + sum: { + inputs: { + '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', + }, + }, }, }; @@ -111,42 +106,50 @@ describe('lib/explain: ', () => { }, }, }, - pluginData: { - path: 'builtin', - method: 'Sum', - }, }; const expectedResult = { - 'cpu/energy': { - plugins: ['sum', 'sum-energy'], - unit: 'kWh', - description: 'energy consumed by the cpu', - 'aggregation-method': 'sum', - }, - 'network/energy': { - plugins: ['sum'], - unit: 'kWh', - description: 'energy consumed by data ingress and egress', - 'aggregation-method': 'sum', - }, - 'energy-sum': { - plugins: ['sum'], - unit: 'kWh', - description: 'sum of energy components', - 'aggregation-method': 'sum', - }, - 'memory/energy': { - plugins: ['sum-energy'], - unit: 'kWh', - description: 'energy consumed by data from memory', - 'aggregation-method': 'sum', + sum: { + inputs: { + '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', + }, + }, }, - 'total/energy': { - plugins: ['sum-energy'], - unit: 'kWh', - description: 'sum of energy components', - 'aggregation-method': 'sum', + 'sum-energy': { + inputs: { + 'cpu/energy': { + unit: 'kWh', + description: 'energy consumed by the cpu', + 'aggregation-method': 'sum', + }, + 'memory/energy': { + unit: 'kWh', + description: 'energy consumed by data from memory', + 'aggregation-method': 'sum', + }, + }, + outputs: { + 'total/energy': { + unit: 'kWh', + description: 'sum of energy components', + 'aggregation-method': 'sum', + }, + }, }, }; @@ -184,10 +187,6 @@ describe('lib/explain: ', () => { }, }, }, - pluginData: { - path: 'builtin', - method: 'Sum', - }, }; expect.assertions(2); @@ -239,10 +238,6 @@ describe('lib/explain: ', () => { }, }, }, - pluginData: { - path: 'builtin', - method: 'Sum', - }, }; expect.assertions(2); From d9a58ebad4893d470aa40be7ceb20626d8803de6 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 30 Oct 2024 20:45:08 +0400 Subject: [PATCH 860/863] fix(util): tune aggregate outputs into one logic to not stop executionon none and copy --- src/if-run/util/aggregation-helper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/if-run/util/aggregation-helper.ts b/src/if-run/util/aggregation-helper.ts index defa71726..6e9f4e071 100644 --- a/src/if-run/util/aggregation-helper.ts +++ b/src/if-run/util/aggregation-helper.ts @@ -39,12 +39,12 @@ export const aggregateOutputsIntoOne = ( const aggregationType = isTemporal ? 'component' : 'time'; if (aggregationParams[aggregationType] === 'none') { - return acc; + continue; } if (aggregationParams[aggregationType] === 'copy') { acc[metric] = output[metric]; - return acc; + continue; } acc[metric] = acc[metric] ?? 0; From 88ff03711ccdaa0d9c7d94ed689d3c1d451d7386 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 30 Oct 2024 20:51:40 +0400 Subject: [PATCH 861/863] fix(util): fix imports order in initialize --- src/if-run/lib/initialize.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/if-run/lib/initialize.ts b/src/if-run/lib/initialize.ts index 554b4f9c0..5ae3787f1 100644 --- a/src/if-run/lib/initialize.ts +++ b/src/if-run/lib/initialize.ts @@ -3,6 +3,8 @@ import * as path from 'node:path'; import {ERRORS} from '@grnsft/if-core/utils'; import {PluginInterface} from '@grnsft/if-core/types'; +import {storeAggregationMetrics} from './aggregate'; + import {logger} from '../../common/util/logger'; import {memoizedLog} from '../util/log-memoize'; import {pluginStorage} from '../util/plugin-storage'; @@ -11,7 +13,6 @@ import {CONFIG, STRINGS} from '../config'; import {Context, PluginOptions} from '../../common/types/manifest'; import {PluginStorageInterface} from '../types/plugin-storage'; -import {storeAggregationMetrics} from './aggregate'; const { PluginInitializationError, From 4b9d14ed6c518f071394125152ce73af584504f5 Mon Sep 17 00:00:00 2001 From: Narek Hovhannisyan Date: Wed, 30 Oct 2024 20:52:09 +0400 Subject: [PATCH 862/863] revert(lib): drop console.log from compute --- src/if-run/lib/compute.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/if-run/lib/compute.ts b/src/if-run/lib/compute.ts index 81bc768e1..497d0b5e6 100644 --- a/src/if-run/lib/compute.ts +++ b/src/if-run/lib/compute.ts @@ -184,7 +184,6 @@ const computeNode = async (node: Node, params: ComputeParams): Promise => { debugLogger.setExecutingPluginName(pluginName); outputStorage = await plugin.execute(outputStorage, nodeConfig); - console.log(outputStorage); debugLogger.setExecutingPluginName(); node.outputs = outputStorage; From f6a8a543f6f7d2fd32302349e63f30ffef98ceb9 Mon Sep 17 00:00:00 2001 From: Release commit workflow Date: Thu, 31 Oct 2024 14:46:25 +0000 Subject: [PATCH 863/863] =?UTF-8?q?chore(release):=20v0.7.2=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ded744c52..551696574 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@grnsft/if", - "version": "0.7.1", + "version": "0.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@grnsft/if", - "version": "0.7.1", + "version": "0.7.2", "license": "MIT", "dependencies": { "@commitlint/cli": "^18.6.0", diff --git a/package.json b/package.json index 7a05f5742..c0d92fffc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@grnsft/if", "description": "Impact Framework", - "version": "0.7.1", + "version": "0.7.2", "author": { "name": "Green Software Foundation", "email": "info@gsf.com"