Merge pull request #2481 from RoadieHQ/scaffolder-values-validation
Scaffolder values validation
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
"git-url-parse": "^11.1.2",
|
||||
"globby": "^11.0.0",
|
||||
"helmet": "^4.0.0",
|
||||
"jsonschema": "^1.2.6",
|
||||
"morgan": "^1.10.0",
|
||||
"nodegit": "0.26.5",
|
||||
"uuid": "^8.2.0",
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2020 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 { getVoidLogger } from '@backstage/backend-common';
|
||||
import express from 'express';
|
||||
import request from 'supertest';
|
||||
import { createRouter } from './router';
|
||||
import { Templaters, Preparers, PublisherBase } from '../scaffolder';
|
||||
import Docker from 'dockerode';
|
||||
|
||||
jest.mock('dockerode');
|
||||
|
||||
describe('createRouter', () => {
|
||||
let app: express.Express;
|
||||
const publisher: jest.Mocked<PublisherBase> = { publish: jest.fn() };
|
||||
|
||||
beforeAll(async () => {
|
||||
const router = await createRouter({
|
||||
logger: getVoidLogger(),
|
||||
preparers: new Preparers(),
|
||||
templaters: new Templaters(),
|
||||
publisher: publisher,
|
||||
dockerClient: new Docker(),
|
||||
});
|
||||
app = express().use(router);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('POST /v1/jobs', () => {
|
||||
const template = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Template',
|
||||
metadata: {
|
||||
description: 'Create a new CRA website project',
|
||||
name: 'create-react-app-template',
|
||||
tags: ['experimental', 'react', 'cra'],
|
||||
title: 'Create React App Template',
|
||||
},
|
||||
spec: {
|
||||
owner: 'web@example.com',
|
||||
path: '.',
|
||||
schema: {
|
||||
properties: {
|
||||
component_id: {
|
||||
description: 'Unique name of the component',
|
||||
title: 'Name',
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
description: 'Description of the component',
|
||||
title: 'Description',
|
||||
type: 'string',
|
||||
},
|
||||
use_typescript: {
|
||||
default: true,
|
||||
description: 'Include typescript',
|
||||
title: 'Use Typescript',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
required: ['component_id', 'use_typescript'],
|
||||
},
|
||||
templater: 'cra',
|
||||
type: 'website',
|
||||
},
|
||||
};
|
||||
|
||||
it('rejects template values which do not match the template schema definition', async () => {
|
||||
const response = await request(app).post('/v1/jobs').send({
|
||||
template,
|
||||
values: {},
|
||||
});
|
||||
|
||||
expect(response.status).toEqual(400);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
TemplaterBuilder,
|
||||
PublisherBase,
|
||||
} from '../scaffolder';
|
||||
import { validate, ValidatorResult } from 'jsonschema';
|
||||
|
||||
export interface RouterOptions {
|
||||
preparers: PreparerBuilder;
|
||||
@@ -84,6 +85,15 @@ export async function createRouter(
|
||||
const values: RequiredTemplateValues & Record<string, JsonValue> =
|
||||
req.body.values;
|
||||
|
||||
const validationResult: ValidatorResult = validate(
|
||||
values,
|
||||
template.spec.schema,
|
||||
);
|
||||
if (!validationResult.valid) {
|
||||
res.status(400).json({ errors: validationResult.errors });
|
||||
return;
|
||||
}
|
||||
|
||||
const job = jobProcessor.create({
|
||||
entity: template,
|
||||
values,
|
||||
|
||||
@@ -13288,6 +13288,11 @@ jsonpointer@^4.0.1:
|
||||
resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
||||
integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk=
|
||||
|
||||
jsonschema@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.6.tgz#52b0a8e9dc06bbae7295249d03e4b9faee8a0c0b"
|
||||
integrity sha512-SqhURKZG07JyKKeo/ir24QnS4/BV7a6gQy93bUSe4lUdNp0QNpIz2c9elWJQ9dpc5cQYY6cvCzgRwy0MQCLyqA==
|
||||
|
||||
jspdf-autotable@3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-3.5.3.tgz#2f73adb07f340e7dbf22950e3e6c8bf853991479"
|
||||
|
||||
Reference in New Issue
Block a user