This commit is contained in:
Johan Haals
2021-01-26 12:00:40 +01:00
parent fef53431df
commit 8623025c9b
5 changed files with 226 additions and 5 deletions
@@ -0,0 +1,106 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Config } from '@backstage/config';
import { TemplateActionRegistry } from '../TemplateConverter';
import { FilePreparer } from './prepare';
import Docker from 'dockerode';
type Options = {
logger: Logger;
config: Config;
dockerClient: Docker;
};
export function registerLegacyActions(
registry: TemplateActionRegistry,
options: Options,
) {
registry.register({
id: 'legacy:prepare',
async handler(ctx) {
const { logger } = ctx;
console.log(ctx);
logger.info('Task claimed, waiting ...');
// Give us some time to curl observe
await new Promise(resolve => setTimeout(resolve, 5000));
logger.info('Prepare the skeleton');
const { protocol, pullPath } = ctx.parameters;
const preparer =
protocol === 'file'
? new FilePreparer()
: preparers.get(pullPath as string);
await preparer.prepare(task.spec.template, {
logger,
ctx.workspaceDir,
});
ctx.output('catalogInfoUrl', 'httpderp://asdasd');
},
});
// try {
// const { values, template } = task.spec;
// task.emitLog('Prepare the skeleton');
// const { protocol, location: pullPath } = parseLocationAnnotation(
// task.spec.template,
// );
// const preparer =
// protocol === 'file' ? new FilePreparer() : preparers.get(pullPath);
// const templater = templaters.get(template);
// const publisher = publishers.get(values.storePath);
// const skeletonDir = await preparer.prepare(task.spec.template, {
// logger: taskLogger,
// workingDirectory: workingDirectory,
// });
registry.register({
id: 'legacy:template',
async handler(ctx) {
const { logger } = ctx;
const templater = templaters.get(ctx.parameters.templater as string);
logger.info('Run the templater');
const { resultDir } = await templater.run({
directory: ctx.workspaceDir,
dockerClient,
logStream: ctx.logStream,
values: ctx.parameters.values as TemplaterValues,
});
},
});
// task.emitLog('Publish template');
// logger.info('Will now store the template');
// logger.info('Totally storing the template now');
// await new Promise(resolve => setTimeout(resolve, 5000));
// // const result = await publisher.publish({
// // values: values,
// // directory: resultDir,
// // logger,
// // });
// // task.emitLog(`Result: ${JSON.stringify(result)}`);
// await task.complete('completed');
// } catch (error) {
// await task.complete('failed');
// }
}
@@ -15,7 +15,7 @@
*/
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { TemplaterValues } from '../stages/templater/types';
import { TemplaterValues } from './actions/templater/types';
import { MemoryDatabase } from './MemoryDatabase';
import { MemoryTaskBroker, TaskAgent } from './MemoryTaskBroker';
@@ -0,0 +1,110 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { JsonValue } from '@backstage/config';
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { Logger } from 'winston';
import type { Writable } from 'stream';
import {
getTemplaterKey,
parseLocationAnnotation,
TemplaterValues,
} from '../jobs/actions';
import { TaskSpec } from './types';
import { ConflictError, NotFoundError } from '@backstage/backend-common';
function templateEntityToSpec(
template: TemplateEntityV1alpha1,
values: TemplaterValues,
): TaskSpec {
const steps: TaskSpec['steps'] = [];
const { protocol, location: pullPath } = parseLocationAnnotation(template);
const templater = getTemplaterKey(template);
steps.push({
id: 'prepare',
name: 'Prepare',
action: 'legacy:prepare',
parameters: {
protocol,
pullPath,
},
});
steps.push({
id: 'template',
name: 'Template',
action: 'legacy:template',
parameters: {
templater,
values,
},
});
steps.push({
id: 'publish',
name: 'Publishing',
action: 'publish',
parameters: {
values,
directory,
},
});
return { steps };
}
type ActionContext = {
logger: Logger;
logStream: Writable;
workspaceDir: string;
parameters: { [name: string]: JsonValue };
output(name: string, value: JsonValue): void;
};
type TemplateAction = {
id: string;
handler: (ctx: ActionContext) => Promise<void>;
};
export class TemplateActionRegistry {
private readonly actions = new Map<string, TemplateAction>();
register(action: TemplateAction) {
if (this.actions.has(action.id)) {
throw new ConflictError(
`Template action with id ${action.id} as already been registered`,
);
}
this.actions.set(action.id, action);
}
// validate
// ensure that action exist.
// template variables exist.
get(actionId: string): TemplateAction {
const action = this.actions.get(actionId);
if (!action) {
throw new NotFoundError(
`Template action with id ${actionId} is not registered.`,
);
}
return action;
}
}
@@ -14,8 +14,7 @@
* limitations under the License.
*/
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
import { TemplaterValues } from '..';
import { JsonObject } from '@backstage/config';
export type Status =
| 'open'
@@ -47,8 +46,12 @@ export type DbTaskEventRow = {
};
export type TaskSpec = {
template: TemplateEntityV1alpha1;
values: TemplaterValues;
steps: Array<{
id: string;
name: string;
action: string;
parameters?: JsonObject;
}>;
};
export type DispatchResult = {
@@ -38,6 +38,8 @@ import {
MemoryDatabase,
TaskWorker,
} from '../scaffolder/tasks';
import { TemplateActionRegistry } from '../scaffolder/tasks/TemplateConverter';
import { LOCATION_ANNOTATION } from '@backstage/catalog-model';
export interface RouterOptions {
preparers: PreparerBuilder;