Merge pull request #21975 from backstage/catalog-backend/add-location-by-entity-api
[CatalogBackend] Add API to get location by entity
This commit is contained in:
@@ -50,6 +50,10 @@ export interface CatalogApi {
|
||||
request: GetEntityFacetsRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<GetEntityFacetsResponse>;
|
||||
getLocationByEntity(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Location_2 | undefined>;
|
||||
getLocationById(
|
||||
id: string,
|
||||
options?: CatalogRequestOptions,
|
||||
@@ -120,6 +124,10 @@ export class CatalogClient implements CatalogApi {
|
||||
request: GetEntityFacetsRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<GetEntityFacetsResponse>;
|
||||
getLocationByEntity(
|
||||
entityRef: CompoundEntityRef | string,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Location_2 | undefined>;
|
||||
getLocationById(
|
||||
id: string,
|
||||
options?: CatalogRequestOptions,
|
||||
|
||||
@@ -617,6 +617,71 @@ describe('CatalogClient', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLocationByEntity', () => {
|
||||
const defaultResponse = {
|
||||
data: {
|
||||
kind: 'c',
|
||||
namespace: 'ns',
|
||||
name: 'n',
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.get(`${mockBaseUrl}/locations/by-entity/c/ns/n`, (_, res, ctx) => {
|
||||
return res(ctx.json(defaultResponse));
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should locations from correct endpoint', async () => {
|
||||
const response = await client.getLocationByEntity(
|
||||
{ kind: 'c', namespace: 'ns', name: 'n' },
|
||||
{ token },
|
||||
);
|
||||
expect(response).toEqual(defaultResponse);
|
||||
});
|
||||
|
||||
it('forwards authorization token', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
server.use(
|
||||
rest.get(
|
||||
`${mockBaseUrl}/locations/by-entity/c/ns/n`,
|
||||
(req, res, ctx) => {
|
||||
expect(req.headers.get('authorization')).toBe(`Bearer ${token}`);
|
||||
return res(ctx.json(defaultResponse));
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
await client.getLocationByEntity(
|
||||
{ kind: 'c', namespace: 'ns', name: 'n' },
|
||||
{ token },
|
||||
);
|
||||
});
|
||||
|
||||
it('skips authorization header if token is omitted', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
server.use(
|
||||
rest.get(
|
||||
`${mockBaseUrl}/locations/by-entity/c/ns/n`,
|
||||
(req, res, ctx) => {
|
||||
expect(req.headers.get('authorization')).toBeNull();
|
||||
return res(ctx.json(defaultResponse));
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
await client.getLocationByEntity({
|
||||
kind: 'c',
|
||||
namespace: 'ns',
|
||||
name: 'n',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateEntity', () => {
|
||||
it('returns valid false when validation fails', async () => {
|
||||
server.use(
|
||||
|
||||
@@ -88,6 +88,21 @@ export class CatalogClient implements CatalogApi {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc CatalogApi.getLocationByEntity}
|
||||
*/
|
||||
async getLocationByEntity(
|
||||
entityRef: CompoundEntityRef | string,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Location | undefined> {
|
||||
return await this.requestOptional(
|
||||
await this.apiClient.getLocationByEntity(
|
||||
{ path: parseEntityRef(entityRef) },
|
||||
options,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc CatalogApi.getEntities}
|
||||
*/
|
||||
|
||||
@@ -461,6 +461,42 @@ export class DefaultApiClient {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a location for entity.
|
||||
* @param kind
|
||||
* @param namespace
|
||||
* @param name
|
||||
*/
|
||||
public async getLocationByEntity(
|
||||
// @ts-ignore
|
||||
request: {
|
||||
path: {
|
||||
kind: string;
|
||||
namespace: string;
|
||||
name: string;
|
||||
};
|
||||
},
|
||||
options?: RequestOptions,
|
||||
): Promise<TypedResponse<Location>> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
|
||||
|
||||
const uriTemplate = `/locations/by-entity/{kind}/{namespace}/{name}`;
|
||||
|
||||
const uri = parser.parse(uriTemplate).expand({
|
||||
kind: request.path.kind,
|
||||
namespace: request.path.namespace,
|
||||
name: request.path.name,
|
||||
});
|
||||
|
||||
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
|
||||
},
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all locations
|
||||
*/
|
||||
|
||||
@@ -629,6 +629,17 @@ export interface CatalogApi {
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Gets a location associated with an entity.
|
||||
*
|
||||
* @param entityRef - A complete entity ref, either on string or compound form
|
||||
* @param options - Additional options
|
||||
*/
|
||||
getLocationByEntity(
|
||||
entityRef: string | CompoundEntityRef,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<Location | undefined>;
|
||||
|
||||
/**
|
||||
* Validate entity and its location.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user