Merge pull request #23084 from aramissennyeydd/openapi-tooling/schemathesis
feat(openapi-tooling): add support for fuzzing with schemathesis
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build",
|
||||
"clean": "backstage-cli package clean",
|
||||
"fuzz": "backstage-repo-tools package schema openapi fuzz --exclude-checks response_schema_conformance",
|
||||
"generate": "backstage-repo-tools package schema openapi generate --server --client-package packages/catalog-client",
|
||||
"lint": "backstage-cli package lint",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1540,7 +1540,7 @@ export const spec = {
|
||||
'400': {
|
||||
description: 'Validation errors.',
|
||||
content: {
|
||||
'application/json; charset=utf-8': {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
||||
@@ -1135,7 +1135,7 @@ paths:
|
||||
'400':
|
||||
description: Validation errors.
|
||||
content:
|
||||
application/json; charset=utf-8:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -42,6 +42,7 @@ import { decodeCursor, encodeCursor } from './util';
|
||||
import { wrapInOpenApiTestServer } from '@backstage/backend-openapi-utils';
|
||||
import { Server } from 'http';
|
||||
import { mockCredentials, mockServices } from '@backstage/backend-test-utils';
|
||||
import { LocationAnalyzer } from '../ingestion';
|
||||
|
||||
describe('createRouter readonly disabled', () => {
|
||||
let entitiesCatalog: jest.Mocked<EntitiesCatalog>;
|
||||
@@ -49,6 +50,7 @@ describe('createRouter readonly disabled', () => {
|
||||
let orchestrator: jest.Mocked<CatalogProcessingOrchestrator>;
|
||||
let app: express.Express | Server;
|
||||
let refreshService: RefreshService;
|
||||
let locationAnalyzer: jest.Mocked<LocationAnalyzer>;
|
||||
|
||||
beforeAll(async () => {
|
||||
entitiesCatalog = {
|
||||
@@ -66,6 +68,10 @@ describe('createRouter readonly disabled', () => {
|
||||
deleteLocation: jest.fn(),
|
||||
getLocationByEntity: jest.fn(),
|
||||
};
|
||||
|
||||
locationAnalyzer = {
|
||||
analyzeLocation: jest.fn(),
|
||||
};
|
||||
refreshService = { refresh: jest.fn() };
|
||||
orchestrator = { process: jest.fn() };
|
||||
const router = await createRouter({
|
||||
@@ -78,6 +84,7 @@ describe('createRouter readonly disabled', () => {
|
||||
permissionIntegrationRouter: express.Router(),
|
||||
auth: mockServices.auth(),
|
||||
httpAuth: mockServices.httpAuth(),
|
||||
locationAnalyzer,
|
||||
});
|
||||
app = wrapInOpenApiTestServer(express().use(router));
|
||||
});
|
||||
@@ -821,6 +828,21 @@ describe('createRouter readonly disabled', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /analyze-location', () => {
|
||||
it('handles invalid URLs', async () => {
|
||||
const parseUrlError = new Error();
|
||||
(parseUrlError as any).subject_url = 'not a url';
|
||||
locationAnalyzer.analyzeLocation.mockRejectedValue(parseUrlError);
|
||||
const response = await request(app)
|
||||
.post('/analyze-location')
|
||||
.send({ location: { type: 'url', target: 'not a url' } });
|
||||
expect(response.status).toEqual(400);
|
||||
expect(response.body.error.message).toMatch(
|
||||
/The given location.target is not a URL/,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createRouter readonly enabled', () => {
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { NotFoundError, serializeError } from '@backstage/errors';
|
||||
import { InputError, NotFoundError, serializeError } from '@backstage/errors';
|
||||
import express from 'express';
|
||||
import { Logger } from 'winston';
|
||||
import yn from 'yn';
|
||||
@@ -298,8 +298,20 @@ export async function createRouter(
|
||||
location: locationInput,
|
||||
catalogFilename: z.string().optional(),
|
||||
});
|
||||
const output = await locationAnalyzer.analyzeLocation(schema.parse(body));
|
||||
res.status(200).json(output);
|
||||
const parsedBody = schema.parse(body);
|
||||
try {
|
||||
const output = await locationAnalyzer.analyzeLocation(parsedBody);
|
||||
res.status(200).json(output);
|
||||
} catch (err) {
|
||||
if (
|
||||
// Catch errors from parse-url library.
|
||||
err.name === 'Error' &&
|
||||
'subject_url' in err
|
||||
) {
|
||||
throw new InputError('The given location.target is not a URL');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack",
|
||||
"clean": "backstage-cli package clean",
|
||||
"generate": "backstage-repo-tools package schema openapi generate --server"
|
||||
"generate": "backstage-repo-tools package schema openapi generate --server",
|
||||
"fuzz": "backstage-repo-tools package schema openapi fuzz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "workspace:^",
|
||||
@@ -52,6 +53,7 @@
|
||||
"@backstage/plugin-permission-node": "workspace:^",
|
||||
"@backstage/plugin-search-backend-node": "workspace:^",
|
||||
"@backstage/plugin-search-common": "workspace:^",
|
||||
"@backstage/repo-tools": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/express": "^4.17.6",
|
||||
"dataloader": "^2.0.0",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build",
|
||||
"clean": "backstage-cli package clean",
|
||||
"fuzz": "backstage-repo-tools package schema openapi fuzz",
|
||||
"generate": "backstage-repo-tools package schema openapi generate --server",
|
||||
"lint": "backstage-cli package lint",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
|
||||
Reference in New Issue
Block a user