Merge pull request #9580 from backstage/blam/deprecations/more

chore: removing `CatalogEntityClient` export from `scaffolder-backend`
This commit is contained in:
Ben Lambert
2022-02-16 20:30:43 +01:00
committed by GitHub
7 changed files with 71 additions and 96 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-scaffolder-backend': minor
---
**BREAKING** - Removed the `CatalogEntityClient` export. This is no longer provider by this package,
but you can implement one pretty simply yourself using the `CatalogApi` and applying filters to fetch templates.
-14
View File
@@ -29,7 +29,6 @@ import { SpawnOptionsWithoutStdio } from 'child_process';
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
import { TaskSpecV1beta2 } from '@backstage/plugin-scaffolder-common';
import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common';
import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common';
import { TemplateMetadata } from '@backstage/plugin-scaffolder-common';
import { UrlReader } from '@backstage/backend-common';
import { Writable } from 'stream';
@@ -49,19 +48,6 @@ export type ActionContext<Input extends JsonObject> = {
metadata?: TemplateMetadata;
};
// Warning: (ae-missing-release-tag) "CatalogEntityClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export class CatalogEntityClient {
constructor(catalogClient: CatalogApi);
findTemplate(
templateName: string,
options?: {
token?: string;
},
): Promise<TemplateEntityV1beta2>;
}
// @public
export type CompletedTaskState = 'failed' | 'completed';
@@ -1,58 +0,0 @@
/*
* Copyright 2020 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.
* 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 { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common';
import { CatalogApi } from '@backstage/catalog-client';
import { ConflictError, NotFoundError } from '@backstage/errors';
/**
* A catalog client tailored for reading out entity data from the catalog.
*/
export class CatalogEntityClient {
constructor(private readonly catalogClient: CatalogApi) {}
/**
* Looks up a single template using a template name.
*
* Throws a NotFoundError or ConflictError if 0 or multiple templates are found.
*/
async findTemplate(
templateName: string,
options?: { token?: string },
): Promise<TemplateEntityV1beta2> {
const { items: templates } = (await this.catalogClient.getEntities(
{
filter: {
kind: 'template',
'metadata.name': templateName,
},
},
options,
)) as { items: TemplateEntityV1beta2[] };
if (templates.length !== 1) {
if (templates.length > 1) {
throw new ConflictError(
'Templates lookup resulted in multiple matches',
);
} else {
throw new NotFoundError('Template not found');
}
}
return templates[0];
}
}
@@ -1,16 +0,0 @@
/*
* Copyright 2020 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.
* 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.
*/
export { CatalogEntityClient } from './CatalogEntityClient';
@@ -14,5 +14,4 @@
* limitations under the License.
*/
export * from './catalog';
export * from './templating';
@@ -14,14 +14,21 @@
* limitations under the License.
*/
import { CatalogApi } from '@backstage/catalog-client';
import {
Entity,
ANNOTATION_LOCATION,
parseLocationRef,
ANNOTATION_SOURCE_LOCATION,
EntityRef,
parseEntityRef,
} from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { assertError } from '@backstage/errors';
import { assertError, ConflictError, NotFoundError } from '@backstage/errors';
import {
TemplateEntityV1beta2,
TemplateEntityV1beta3,
} from '@backstage/plugin-scaffolder-common';
import fs from 'fs-extra';
import os from 'os';
import { Logger } from 'winston';
@@ -78,3 +85,49 @@ export function getEntityBaseUrl(entity: Entity): string | undefined {
// what the url is pointing to makes sense to use as a baseUrl
return undefined;
}
/**
* Will use the provided CatalogApi to go find the template entity ref that is provided with and additional token
* Returns the first matching template, throws a NotFoundError or ConflictError if 0 or multiple templates are found.
*/
export async function findTemplate({
entityRef,
token,
catalogApi,
}: {
entityRef: EntityRef;
token?: string;
catalogApi: CatalogApi;
}): Promise<TemplateEntityV1beta3 | TemplateEntityV1beta2> {
const parsedEntityRef = parseEntityRef(entityRef, {
defaultKind: 'template',
defaultNamespace: 'default',
});
const { items } = await catalogApi.getEntities(
{
filter: {
kind: 'template',
'metadata.name': parsedEntityRef.name,
'metadata.namespace': parsedEntityRef.namespace,
},
},
{
token,
},
);
const templates = items.filter(
(entity): entity is TemplateEntityV1beta3 | TemplateEntityV1beta2 =>
entity.kind === 'Template',
);
if (templates.length !== 1) {
if (templates.length > 1) {
throw new ConflictError('Templates lookup resulted in multiple matches');
} else {
throw new NotFoundError('Template not found');
}
}
return templates[0];
}
@@ -33,7 +33,7 @@ import express from 'express';
import Router from 'express-promise-router';
import { validate } from 'jsonschema';
import { Logger } from 'winston';
import { CatalogEntityClient, TemplateFilter } from '../lib';
import { TemplateFilter } from '../lib';
import {
createBuiltinActions,
DatabaseTaskStore,
@@ -44,7 +44,7 @@ import {
TemplateActionRegistry,
} from '../scaffolder';
import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';
import { getEntityBaseUrl, getWorkingDirectory } from './helpers';
import { getEntityBaseUrl, getWorkingDirectory, findTemplate } from './helpers';
/**
* RouterOptions
@@ -93,7 +93,6 @@ export async function createRouter(
const logger = parentLogger.child({ plugin: 'scaffolder' });
const workingDirectory = await getWorkingDirectory(config, logger);
const entityClient = new CatalogEntityClient(catalogClient);
const integrations = ScmIntegrations.fromConfig(config);
let taskBroker: TaskBroker;
@@ -152,7 +151,9 @@ export async function createRouter(
);
}
const template = await entityClient.findTemplate(name, {
const template = await findTemplate({
catalogApi: catalogClient,
entityRef: { kind, namespace, name },
token: getBearerToken(req.headers.authorization),
});
if (isSupportedTemplate(template)) {
@@ -187,8 +188,12 @@ export async function createRouter(
const templateName: string = req.body.templateName;
const values = req.body.values;
const token = getBearerToken(req.headers.authorization);
const template = await entityClient.findTemplate(templateName, {
token,
const template = await findTemplate({
catalogApi: catalogClient,
entityRef: {
name: templateName,
},
token: getBearerToken(req.headers.authorization),
});
let taskSpec: TaskSpec;