diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index b884802a1f..57d7971f50 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -39,6 +39,7 @@ export type ScaffolderPluginOptions = { taskWorkers?: number; taskBroker?: TaskBroker; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; }; /** @@ -101,7 +102,12 @@ export const scaffolderPlugin = createBackendPlugin({ httpRouter, catalogClient, }) { - const { additionalTemplateFilters, taskBroker, taskWorkers } = options; + const { + additionalTemplateFilters, + taskBroker, + taskWorkers, + additionalTemplateGlobals, + } = options; const log = loggerToWinstonLogger(logger); const actions = options.actions || [ @@ -112,6 +118,7 @@ export const scaffolderPlugin = createBackendPlugin({ reader, config, additionalTemplateFilters, + additionalTemplateGlobals, }), ]; @@ -130,6 +137,7 @@ export const scaffolderPlugin = createBackendPlugin({ taskBroker, taskWorkers, additionalTemplateFilters, + additionalTemplateGlobals, }); httpRouter.use(router); }, diff --git a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts index e82620a90d..1b8e201845 100644 --- a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts +++ b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts @@ -64,6 +64,12 @@ const { render, renderCompat } = (() => { } } + if (typeof additionalTemplateGlobals !== 'undefined') { + for (const [globalName, globalFn] of Object.entries(additionalTemplateGlobals)) { + env.addGlobal(globalName, (...args) => JSON.parse(globalFn(...args))); + } + } + let uninstallCompat = undefined; function render(str, values) { @@ -107,6 +113,7 @@ export interface SecureTemplaterOptions { /* Extra user-provided nunjucks filters */ additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; } export type SecureTemplateRenderer = ( @@ -116,8 +123,12 @@ export type SecureTemplateRenderer = ( export class SecureTemplater { static async loadRenderer(options: SecureTemplaterOptions = {}) { - const { parseRepoUrl, cookiecutterCompat, additionalTemplateFilters } = - options; + const { + parseRepoUrl, + cookiecutterCompat, + additionalTemplateFilters, + additionalTemplateGlobals, + } = options; const sandbox: Record = {}; if (parseRepoUrl) { @@ -134,7 +145,19 @@ export class SecureTemplater { ]), ); } - + if (additionalTemplateGlobals) { + console.log(additionalTemplateGlobals, '!!!!!!!!!!!'); + sandbox.additionalTemplateGlobals = Object.fromEntries( + Object.entries(additionalTemplateGlobals) + .filter(([_, filterFunction]) => !!filterFunction) + .map(([filterName, filterFunction]) => [ + filterName, + (...args: JsonValue[]) => JSON.stringify(filterFunction(...args)), + ]), + ); + } + console.log(sandbox.additionalTemplateGlobals, 'HUH?'); + console.log(sandbox.additionalTemplateFilters, 'HUH?'); const vm = new VM({ sandbox }); const nunjucksSource = await fs.readFile( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index fcddf127e2..7581189411 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -82,6 +82,7 @@ export interface CreateBuiltInActionsOptions { * Template Manifests and also template skeleton files when using `fetch:template`. */ additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; } /** @@ -100,6 +101,7 @@ export const createBuiltinActions = ( catalogClient, config, additionalTemplateFilters, + additionalTemplateGlobals, } = options; const githubCredentialsProvider: GithubCredentialsProvider = @@ -114,6 +116,7 @@ export const createBuiltinActions = ( integrations, reader, additionalTemplateFilters, + additionalTemplateGlobals, }), createPublishGerritAction({ integrations, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts index 1ead7ebcd6..47a85df9ca 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts @@ -39,8 +39,14 @@ export function createFetchTemplateAction(options: { reader: UrlReader; integrations: ScmIntegrations; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; }) { - const { reader, integrations, additionalTemplateFilters } = options; + const { + reader, + integrations, + additionalTemplateFilters, + additionalTemplateGlobals, + } = options; return createTemplateAction<{ url: string; @@ -218,6 +224,7 @@ export function createFetchTemplateAction(options: { const renderTemplate = await SecureTemplater.loadRenderer({ cookiecutterCompat: ctx.input.cookiecutterCompat, additionalTemplateFilters, + additionalTemplateGlobals, }); for (const location of allEntriesInTemplate) { diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts index f2c3c13509..36a5a3728a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts @@ -52,6 +52,7 @@ export type TemplateTesterCreateOptions = { actionRegistry: TemplateActionRegistry; workingDirectory: string; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; }; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 009ea1357d..eb6683e32b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -45,6 +45,7 @@ type NunjucksWorkflowRunnerOptions = { integrations: ScmIntegrations; logger: winston.Logger; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; }; type TemplateContext = { @@ -188,6 +189,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { ); const { integrations } = this.options; + console.log(this.options.additionalTemplateGlobals, '@@@%%%%%%%%%%@@@'); const renderTemplate = await SecureTemplater.loadRenderer({ // TODO(blam): let's work out how we can deprecate this. // We shouldn't really need to be exposing these now we can deal with @@ -197,6 +199,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { return parseRepoUrl(url, integrations); }, additionalTemplateFilters: this.options.additionalTemplateFilters, + additionalTemplateGlobals: this.options.additionalTemplateGlobals, }); try { diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 9defd71c49..bd0e6a6dd4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -46,6 +46,7 @@ export type CreateWorkerOptions = { workingDirectory: string; logger: Logger; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; }; /** @@ -64,6 +65,7 @@ export class TaskWorker { integrations, workingDirectory, additionalTemplateFilters, + additionalTemplateGlobals, } = options; const workflowRunner = new NunjucksWorkflowRunner({ @@ -72,6 +74,7 @@ export class TaskWorker { logger, workingDirectory, additionalTemplateFilters, + additionalTemplateGlobals, }); return new TaskWorker({ diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 28dd1ca413..592e0be79d 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -70,6 +70,7 @@ export interface RouterOptions { taskWorkers?: number; taskBroker?: TaskBroker; additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; identity?: IdentityApi; } @@ -160,6 +161,7 @@ export async function createRouter( taskWorkers, scheduler, additionalTemplateFilters, + additionalTemplateGlobals, } = options; const logger = parentLogger.child({ plugin: 'scaffolder' }); @@ -207,6 +209,7 @@ export async function createRouter( logger, workingDirectory, additionalTemplateFilters, + additionalTemplateGlobals, }); workers.push(worker); } @@ -219,6 +222,7 @@ export async function createRouter( reader, config, additionalTemplateFilters, + additionalTemplateGlobals, }); actionsToRegister.forEach(action => actionRegistry.register(action)); @@ -230,6 +234,7 @@ export async function createRouter( logger, workingDirectory, additionalTemplateFilters, + additionalTemplateGlobals, }); router