Added /validate-entity to the catalog client

Signed-off-by: Taras <tarasm@gmail.com>
This commit is contained in:
Taras
2022-09-07 17:32:06 -04:00
parent cc16950bca
commit 54f14d5b88
3 changed files with 123 additions and 1 deletions
@@ -295,4 +295,67 @@ describe('CatalogClient', () => {
await client.getLocationById('42');
});
});
describe('validateEntity', () => {
it('returns valid false when validation fails', async () => {
server.use(
rest.post(`${mockBaseUrl}/validate-entity`, (req, res, ctx) => {
return res(
ctx.status(400),
ctx.json({
errors: [
{
message: 'Missing name',
},
],
}),
);
}),
);
expect(
await client.validateEntity(
{
apiVersion: '1',
kind: 'Component',
metadata: {
name: '',
},
},
'http://example.com',
),
).toMatchObject({
valid: false,
errors: [
{
message: 'Missing name',
},
],
});
});
it('returns valid true when validation fails', async () => {
server.use(
rest.post(`${mockBaseUrl}/validate-entity`, (req, res, ctx) => {
return res(ctx.status(200), ctx.text(''));
}),
);
expect(
await client.validateEntity(
{
apiVersion: '1',
kind: 'Component',
metadata: {
name: 'good',
},
},
'http://example.com',
),
).toMatchObject({
valid: true,
errors: undefined,
});
});
});
});
+37 -1
View File
@@ -21,7 +21,7 @@ import {
stringifyEntityRef,
stringifyLocationRef,
} from '@backstage/catalog-model';
import { ResponseError } from '@backstage/errors';
import { ResponseError, SerializedError } from '@backstage/errors';
import crossFetch from 'cross-fetch';
import {
CATALOG_FILTER_EXISTS,
@@ -36,6 +36,7 @@ import {
Location,
GetEntityFacetsRequest,
GetEntityFacetsResponse,
ValidateEntityResponse,
} from './types/api';
import { DiscoveryApi } from './types/discovery';
import { FetchApi } from './types/fetch';
@@ -353,6 +354,41 @@ export class CatalogClient implements CatalogApi {
);
}
/**
* {@inheritdoc CatalogApi.validateEntity}
*/
async validateEntity(
entity: Entity,
location: string,
options?: CatalogRequestOptions,
): Promise<ValidateEntityResponse> {
const response = await this.fetchApi.fetch(
`${await this.discoveryApi.getBaseUrl('catalog')}/validate-entity`,
{
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify({ entity, location }),
},
);
if (response.ok) {
return {
valid: true,
errors: undefined,
};
}
const { errors } = (await response.json()) as { errors: SerializedError[] };
return {
valid: false,
errors,
};
}
//
// Private methods
//
+23
View File
@@ -15,6 +15,7 @@
*/
import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
import { SerializedError } from '@backstage/errors';
/**
* This symbol can be used in place of a value when passed to filters in e.g.
@@ -269,6 +270,16 @@ export type AddLocationResponse = {
exists?: boolean;
};
/**
* The response type for {@link CatalogClient.validateEntity}
*
* @public
*/
export type ValidateEntityResponse = {
valid: boolean;
errors?: SerializedError[];
};
/**
* A client for interacting with the Backstage software catalog through its API.
*
@@ -390,4 +401,16 @@ export interface CatalogApi {
id: string,
options?: CatalogRequestOptions,
): Promise<void>;
/**
* Validate entity and its location.
*
* @param entity - Entity to validate
* @param location - URL location of the entity
*/
validateEntity(
entity: Entity,
location: string,
options?: CatalogRequestOptions,
): Promise<ValidateEntityResponse>;
}