From b6925bb66d582329c18f96487ecfc111b0e7e350 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 16 Feb 2022 17:02:01 +0100 Subject: [PATCH 1/4] chore: removing the entityClient and using a helper instead to fetch the matching Templates Signed-off-by: blam --- .../src/lib/catalog/index.ts | 16 ------ plugins/scaffolder-backend/src/lib/index.ts | 1 - .../scaffolder-backend/src/service/helpers.ts | 52 ++++++++++++++++++- .../scaffolder-backend/src/service/router.ts | 19 ++++--- 4 files changed, 64 insertions(+), 24 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/lib/catalog/index.ts diff --git a/plugins/scaffolder-backend/src/lib/catalog/index.ts b/plugins/scaffolder-backend/src/lib/catalog/index.ts deleted file mode 100644 index ea693b00b3..0000000000 --- a/plugins/scaffolder-backend/src/lib/catalog/index.ts +++ /dev/null @@ -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'; diff --git a/plugins/scaffolder-backend/src/lib/index.ts b/plugins/scaffolder-backend/src/lib/index.ts index dbb4348a2c..20096f9c03 100644 --- a/plugins/scaffolder-backend/src/lib/index.ts +++ b/plugins/scaffolder-backend/src/lib/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './catalog'; export * from './templating'; diff --git a/plugins/scaffolder-backend/src/service/helpers.ts b/plugins/scaffolder-backend/src/service/helpers.ts index f86b1663a7..314823d67f 100644 --- a/plugins/scaffolder-backend/src/service/helpers.ts +++ b/plugins/scaffolder-backend/src/service/helpers.ts @@ -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,46 @@ 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 + */ +export async function findTemplate({ + entityRef, + token, + catalogApi, +}: { + entityRef: EntityRef; + token?: string; + catalogApi: CatalogApi; +}): Promise { + const parsedEntityRef = parseEntityRef(entityRef); + 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]; +} diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 440f74d6f6..894a2da000 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -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,14 @@ 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: { + kind: 'template', + namespace: 'default', + name: templateName, + }, + token: getBearerToken(req.headers.authorization), }); let taskSpec: TaskSpec; From d93ac29500f1b448fa5e12e3db68c182f9a37ddb Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 16 Feb 2022 17:05:04 +0100 Subject: [PATCH 2/4] chore: updating some smaller code refactor, and updating api-report Signed-off-by: blam --- plugins/scaffolder-backend/api-report.md | 14 -------------- plugins/scaffolder-backend/src/service/helpers.ts | 7 +++++-- plugins/scaffolder-backend/src/service/router.ts | 2 -- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index d2967bf88a..9694cdffa7 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -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'; @@ -50,19 +49,6 @@ export type ActionContext = { 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; -} - // @public export type CompletedTaskState = 'failed' | 'completed'; diff --git a/plugins/scaffolder-backend/src/service/helpers.ts b/plugins/scaffolder-backend/src/service/helpers.ts index 314823d67f..5cfc58d586 100644 --- a/plugins/scaffolder-backend/src/service/helpers.ts +++ b/plugins/scaffolder-backend/src/service/helpers.ts @@ -88,7 +88,7 @@ export function getEntityBaseUrl(entity: Entity): string | 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 + * Returns the first matching template, throws a NotFoundError or ConflictError if 0 or multiple templates are found. */ export async function findTemplate({ entityRef, @@ -99,7 +99,10 @@ export async function findTemplate({ token?: string; catalogApi: CatalogApi; }): Promise { - const parsedEntityRef = parseEntityRef(entityRef); + const parsedEntityRef = parseEntityRef(entityRef, { + defaultKind: 'template', + defaultNamespace: 'default', + }); const { items } = await catalogApi.getEntities( { filter: { diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 894a2da000..b2978441bd 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -191,8 +191,6 @@ export async function createRouter( const template = await findTemplate({ catalogApi: catalogClient, entityRef: { - kind: 'template', - namespace: 'default', name: templateName, }, token: getBearerToken(req.headers.authorization), From 5a1594330eada1cfb9b3ac9844e01ac544a6ce16 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 16 Feb 2022 17:07:14 +0100 Subject: [PATCH 3/4] chore: added changeset Signed-off-by: blam --- .changeset/swift-dolls-bow.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/swift-dolls-bow.md diff --git a/.changeset/swift-dolls-bow.md b/.changeset/swift-dolls-bow.md new file mode 100644 index 0000000000..0e7a261055 --- /dev/null +++ b/.changeset/swift-dolls-bow.md @@ -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. From ad170e0ac52eccb3e10f83aaa3958e071b884151 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 16 Feb 2022 19:32:48 +0100 Subject: [PATCH 4/4] chore: remove the actual thing Signed-off-by: blam --- .../src/lib/catalog/CatalogEntityClient.ts | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts diff --git a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts deleted file mode 100644 index e9af165b73..0000000000 --- a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts +++ /dev/null @@ -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 { - 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]; - } -}