diff --git a/packages/backend/src/plugins/sanitize.ts b/packages/backend/src/plugins/sanitize.ts new file mode 100644 index 0000000..94d7037 --- /dev/null +++ b/packages/backend/src/plugins/sanitize.ts @@ -0,0 +1,59 @@ +import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import yaml from 'js-yaml'; + +// Add type annotations to fix TS2742 +type SanitizeResourceInput = { + document: string; +}; + +type SanitizeResourceOutput = { + sanitized: string; +}; + +export const createSanitizeResource = () => { + return createTemplateAction({ + id: 'cnoe:utils:sanitize', + schema: { + input: { + type: 'object', + required: ['document'], + properties: { + document: { + type: 'string', + title: 'Document', + description: 'The document to be sanitized', + }, + }, + }, + }, + async handler(ctx) { + const obj = yaml.load(ctx.input.document); + ctx.output('sanitized', yaml.dump(removeEmptyObjects(obj))); + }, + }); +}; + +// Remove empty elements from an object +function removeEmptyObjects(obj: any): any { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + + const newObj: any = Array.isArray(obj) ? [] : {}; + + for (const key in obj) { + const value = obj[key]; + const newValue = removeEmptyObjects(value); + if ( + !( + newValue === null || + newValue === undefined || + (typeof newValue === 'object' && Object.keys(newValue).length === 0) + ) + ) { + newObj[key] = newValue; + } + } + + return newObj; +} diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index b0a31b3..87738e5 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -22,6 +22,8 @@ import { createReplaceInFileAction } from '@roadiehq/scaffolder-backend-module-utils'; import {createKubernetesApply} from "./k8s-apply"; +import {createSanitizeResource} from "./sanitize"; +import {createVerifyDependency} from "./verify"; export default async function createPlugin( env: PluginEnvironment, @@ -50,7 +52,9 @@ export default async function createPlugin( const cnoeActions = [ createPublishGiteaAction(options), createArgoCDApp(argocdOptions), - createKubernetesApply(env.config) + createKubernetesApply(env.config), + createSanitizeResource(), + createVerifyDependency() ] const roadieUtilActions = [ diff --git a/packages/backend/src/plugins/verify.ts b/packages/backend/src/plugins/verify.ts new file mode 100644 index 0000000..32e9737 --- /dev/null +++ b/packages/backend/src/plugins/verify.ts @@ -0,0 +1,67 @@ +import { executeShellCommand } from '@backstage/plugin-scaffolder-node'; +import { createTemplateAction }from '@backstage/plugin-scaffolder-node'; +import {Writable} from 'stream'; + +class ConsoleLogStream extends Writable { + data: string; + + constructor(options: any) { + super(options); + this.data = ''; + } + + _write(chunk: any, _: any, callback: any) { + this.data += chunk.toString(); // Convert the chunk to a string and append it to this.data + console.log(this.data) + callback(); + } +} + +export const createVerifyDependency = () => { + return createTemplateAction<{ + verifiers: string[]; + }>({ + id: 'cnoe:verify:dependency', + schema: { + input: { + type: 'object', + required: ['verifiers'], + properties: { + verifiers: { + type: 'array', + items: { + type: 'string', + }, + title: 'verifiers', + description: 'The list of verifiers', + }, + }, + }, + }, + async handler(ctx) { + const verifiers = ctx.input.verifiers + + if (verifiers === null || verifiers.length === 0) { + ctx.logger.error('no verifier was supplied for the object') + return + } + + const baseCommand = 'cnoe' + const baseArguments = ['k8s', 'verify'] + + verifiers.forEach((verifier: string) => baseArguments.push("--config", verifier)) + + const logStream = new ConsoleLogStream({}); + await executeShellCommand({ + command: baseCommand, + args: baseArguments, + logStream: logStream, + }).then(() => + ctx.logger.info("verification succeeded") + ).catch((error) => { + ctx.logger.error(error) + throw new Error(logStream.data) + }); + }, + }); +};