From 3f480db96366194de7927ab372c602258337319a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:08:57 +0100 Subject: [PATCH 01/11] stop using EntityRef in scaffolder-backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../scaffolder-backend/src/service/helpers.ts | 60 +++++++------------ .../scaffolder-backend/src/service/router.ts | 26 +++----- 2 files changed, 28 insertions(+), 58 deletions(-) diff --git a/plugins/scaffolder-backend/src/service/helpers.ts b/plugins/scaffolder-backend/src/service/helpers.ts index 5cfc58d586..e49c28cb74 100644 --- a/plugins/scaffolder-backend/src/service/helpers.ts +++ b/plugins/scaffolder-backend/src/service/helpers.ts @@ -20,11 +20,11 @@ import { ANNOTATION_LOCATION, parseLocationRef, ANNOTATION_SOURCE_LOCATION, - EntityRef, - parseEntityRef, + EntityName, + DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { assertError, ConflictError, NotFoundError } from '@backstage/errors'; +import { assertError, InputError, NotFoundError } from '@backstage/errors'; import { TemplateEntityV1beta2, TemplateEntityV1beta3, @@ -87,47 +87,29 @@ 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, throws a NotFoundError or ConflictError if 0 or multiple templates are found. + * Will use the provided CatalogApi to go find the given template entity with an additional token. + * Returns the matching template, or throws a NotFoundError if no such template existed. */ -export async function findTemplate({ - entityRef, - token, - catalogApi, -}: { - entityRef: EntityRef; +export async function findTemplate(options: { + entityRef: EntityName; token?: string; catalogApi: CatalogApi; }): Promise { - 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 { entityRef, token, catalogApi } = options; - 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'); - } + if (entityRef.namespace.toLocaleLowerCase('en-US') !== DEFAULT_NAMESPACE) { + throw new InputError( + `Invalid namespace, only '${DEFAULT_NAMESPACE}' namespace is supported`, + ); + } + if (entityRef.kind.toLocaleLowerCase('en-US') !== 'template') { + throw new InputError(`Invalid kind, only 'Template' kind is supported`); } - return templates[0]; + const template = await catalogApi.getEntityByName(entityRef, { token }); + if (!template) { + throw new NotFoundError(`Template ${entityRef} not found`); + } + + return template as TemplateEntityV1beta3 | TemplateEntityV1beta2; } diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index b36670a340..f768e354de 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -20,7 +20,10 @@ import { UrlReader, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; -import { stringifyEntityRef } from '@backstage/catalog-model'; +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { InputError, NotFoundError } from '@backstage/errors'; @@ -141,18 +144,6 @@ export async function createRouter( '/v2/templates/:namespace/:kind/:name/parameter-schema', async (req, res) => { const { namespace, kind, name } = req.params; - - if (namespace !== 'default') { - throw new InputError( - `Invalid namespace, only 'default' namespace is supported`, - ); - } - if (kind.toLowerCase() !== 'template') { - throw new InputError( - `Invalid kind, only 'Template' kind is supported`, - ); - } - const template = await findTemplate({ catalogApi: catalogClient, entityRef: { kind, namespace, name }, @@ -188,16 +179,13 @@ export async function createRouter( }) .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; - const { kind, namespace } = { kind: 'template', namespace: 'default' }; + const kind = 'Template'; + const namespace = DEFAULT_NAMESPACE; const values = req.body.values; const token = getBearerToken(req.headers.authorization); const template = await findTemplate({ catalogApi: catalogClient, - entityRef: { - name: templateName, - kind, - namespace, - }, + entityRef: { kind, namespace, name: templateName }, token: getBearerToken(req.headers.authorization), }); From 410e592552a46aa439fe81852bb957cd5bc3307b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:14:03 +0100 Subject: [PATCH 02/11] stop using EntityRef in bazaar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx | 3 +-- plugins/bazaar/src/components/SortView/SortView.tsx | 2 +- plugins/bazaar/src/types.ts | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx index 5624f40765..ec29d1429b 100644 --- a/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx +++ b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx @@ -47,7 +47,6 @@ import useAsyncFn from 'react-use/lib/useAsyncFn'; import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; import { - parseEntityName, stringifyEntityRef, Entity, parseEntityRef, @@ -150,7 +149,7 @@ export const HomePageBazaarInfoCard = ({ const getEntityPageLink = () => { if (bazaarProject?.value?.entityRef) { - const { name, kind, namespace } = parseEntityName( + const { name, kind, namespace } = parseEntityRef( bazaarProject.value.entityRef, ); return entityLink({ kind, namespace, name }); diff --git a/plugins/bazaar/src/components/SortView/SortView.tsx b/plugins/bazaar/src/components/SortView/SortView.tsx index fa97ac69ee..f5bb6facd7 100644 --- a/plugins/bazaar/src/components/SortView/SortView.tsx +++ b/plugins/bazaar/src/components/SortView/SortView.tsx @@ -107,7 +107,7 @@ export const SortView = () => { if (catalogEntityRefs) { bazaarProjects.value?.forEach(async (project: BazaarProject) => { if (project.entityRef) { - if (!catalogEntityRefs?.includes(project.entityRef as string)) { + if (!catalogEntityRefs?.includes(project.entityRef)) { await bazaarApi.updateProject({ ...project, entityRef: null, diff --git a/plugins/bazaar/src/types.ts b/plugins/bazaar/src/types.ts index 30c07286ac..ec3996d1e2 100644 --- a/plugins/bazaar/src/types.ts +++ b/plugins/bazaar/src/types.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { EntityRef } from '@backstage/catalog-model'; - export type Member = { itemId: number; userId: string; @@ -30,7 +28,7 @@ export type Size = 'small' | 'medium' | 'large'; export type BazaarProject = { name: string; id: number; - entityRef?: EntityRef; + entityRef?: string; community: string; status: Status; description: string; From 19521af0453c96b182a17fcb4b80e1830c16d7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:17:24 +0100 Subject: [PATCH 03/11] stop using EntityRef in code-coverage-backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/code-coverage-backend/src/service/router.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts index 5f136cc8e9..4922f5c887 100644 --- a/plugins/code-coverage-backend/src/service/router.ts +++ b/plugins/code-coverage-backend/src/service/router.ts @@ -34,9 +34,8 @@ import { Cobertura } from './converter/cobertura'; import { Jacoco } from './converter/jacoco'; import { Converter } from './converter'; import { - EntityRef, getEntitySourceLocation, - parseEntityName, + parseEntityRef, } from '@backstage/catalog-model'; export interface RouterOptions { @@ -78,7 +77,7 @@ export const makeRouter = async ( */ router.get('/report', async (req, res) => { const { entity } = req.query; - const entityName = parseEntityName(entity as EntityRef); + const entityName = parseEntityRef(entity as string); const entityLookup = await catalogApi.getEntityByName(entityName); if (!entityLookup) { throw new NotFoundError(`No entity found matching ${entity}`); @@ -101,7 +100,7 @@ export const makeRouter = async ( */ router.get('/history', async (req, res) => { const { entity } = req.query; - const entityName = parseEntityName(entity as EntityRef); + const entityName = parseEntityRef(entity as string); const entityLookup = await catalogApi.getEntityByName(entityName); if (!entityLookup) { throw new NotFoundError(`No entity found matching ${entity}`); @@ -120,7 +119,7 @@ export const makeRouter = async ( */ router.get('/file-content', async (req, res) => { const { entity, path } = req.query; - const entityName = parseEntityName(entity as EntityRef); + const entityName = parseEntityRef(entity as string); const entityLookup = await catalogApi.getEntityByName(entityName); if (!entityLookup) { throw new NotFoundError(`No entity found matching ${entity}`); @@ -172,7 +171,7 @@ export const makeRouter = async ( */ router.post('/report', async (req, res) => { const { entity, coverageType } = req.query; - const entityName = parseEntityName(entity as EntityRef); + const entityName = parseEntityRef(entity as string); const entityLookup = await catalogApi.getEntityByName(entityName); if (!entityLookup) { throw new NotFoundError(`No entity found matching ${entity}`); From 184366af8b888ef86908b651569f12e5359e0ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:19:03 +0100 Subject: [PATCH 04/11] stop using EntityRef in jenkins-backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/jenkins-backend/src/service/standaloneServer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/jenkins-backend/src/service/standaloneServer.ts b/plugins/jenkins-backend/src/service/standaloneServer.ts index b99bdcfd5a..7f47d57ac3 100644 --- a/plugins/jenkins-backend/src/service/standaloneServer.ts +++ b/plugins/jenkins-backend/src/service/standaloneServer.ts @@ -18,7 +18,7 @@ import { createServiceBuilder } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; -import { EntityRef } from '@backstage/catalog-model'; +import { EntityName } from '@backstage/catalog-model'; import { JenkinsInfo } from './jenkinsInfoProvider'; export interface ServerOptions { @@ -35,7 +35,7 @@ export async function startStandaloneServer( const router = await createRouter({ logger, jenkinsInfoProvider: { - async getInstance(_: { entityRef: EntityRef }): Promise { + async getInstance(_: { entityRef: EntityName }): Promise { return { baseUrl: 'https://example.com/', jobFullName: 'build-foo' }; }, }, From 7d82685c9d79dae88b2d2cf144fd4b85ec5e382e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:25:50 +0100 Subject: [PATCH 05/11] stop using EntityRef in jenkins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/jenkins/api-report.md | 20 ++++---------------- plugins/jenkins/src/api/JenkinsApi.ts | 24 ++++++++---------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/plugins/jenkins/api-report.md b/plugins/jenkins/api-report.md index 05ebd1fd03..5db5fd0dfe 100644 --- a/plugins/jenkins/api-report.md +++ b/plugins/jenkins/api-report.md @@ -10,7 +10,6 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import type { EntityName } from '@backstage/catalog-model'; -import type { EntityRef } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; import { InfoCardVariants } from '@backstage/core-components'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -55,7 +54,7 @@ export interface JenkinsApi { }): Promise; // Warning: (ae-forgotten-export) The symbol "Project" needs to be exported by the entry point index.d.ts getProjects(options: { - entity: EntityRef; + entity: EntityName; filter: { branch?: string; }; @@ -82,31 +81,20 @@ export class JenkinsClient implements JenkinsApi { identityApi: IdentityApi; }); // (undocumented) - getBuild({ - entity, - jobFullName, - buildNumber, - }: { + getBuild(options: { entity: EntityName; jobFullName: string; buildNumber: string; }): Promise; // (undocumented) - getProjects({ - entity, - filter, - }: { + getProjects(options: { entity: EntityName; filter: { branch?: string; }; }): Promise; // (undocumented) - retry({ - entity, - jobFullName, - buildNumber, - }: { + retry(options: { entity: EntityName; jobFullName: string; buildNumber: string; diff --git a/plugins/jenkins/src/api/JenkinsApi.ts b/plugins/jenkins/src/api/JenkinsApi.ts index 65ac79b62b..dd169de78b 100644 --- a/plugins/jenkins/src/api/JenkinsApi.ts +++ b/plugins/jenkins/src/api/JenkinsApi.ts @@ -19,7 +19,7 @@ import { DiscoveryApi, IdentityApi, } from '@backstage/core-plugin-api'; -import type { EntityName, EntityRef } from '@backstage/catalog-model'; +import type { EntityName } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; export const jenkinsApiRef = createApiRef({ @@ -80,7 +80,7 @@ export interface JenkinsApi { */ getProjects(options: { /** the entity whose jobs should be retrieved. */ - entity: EntityRef; + entity: EntityName; /** a filter on jobs. Currently this just takes a branch (and assumes certain structures in jenkins) */ filter: { branch?: string }; }): Promise; @@ -117,13 +117,11 @@ export class JenkinsClient implements JenkinsApi { this.identityApi = options.identityApi; } - async getProjects({ - entity, - filter, - }: { + async getProjects(options: { entity: EntityName; filter: { branch?: string }; }): Promise { + const { entity, filter } = options; const url = new URL( `${await this.discoveryApi.getBaseUrl( 'jenkins', @@ -158,15 +156,12 @@ export class JenkinsClient implements JenkinsApi { ); } - async getBuild({ - entity, - jobFullName, - buildNumber, - }: { + async getBuild(options: { entity: EntityName; jobFullName: string; buildNumber: string; }): Promise { + const { entity, jobFullName, buildNumber } = options; const url = `${await this.discoveryApi.getBaseUrl( 'jenkins', )}/v1/entity/${encodeURIComponent(entity.namespace)}/${encodeURIComponent( @@ -186,15 +181,12 @@ export class JenkinsClient implements JenkinsApi { return (await response.json()).build; } - async retry({ - entity, - jobFullName, - buildNumber, - }: { + async retry(options: { entity: EntityName; jobFullName: string; buildNumber: string; }): Promise { + const { entity, jobFullName, buildNumber } = options; const url = `${await this.discoveryApi.getBaseUrl( 'jenkins', )}/v1/entity/${encodeURIComponent(entity.namespace)}/${encodeURIComponent( From 35280f66b3c3fabfbb338076d010fbb7f5a37481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:27:24 +0100 Subject: [PATCH 06/11] stop using EntityRef in tech-insights-backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/tech-insights-backend/src/service/router.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/tech-insights-backend/src/service/router.ts b/plugins/tech-insights-backend/src/service/router.ts index 22a80c2d79..b13802358f 100644 --- a/plugins/tech-insights-backend/src/service/router.ts +++ b/plugins/tech-insights-backend/src/service/router.ts @@ -28,8 +28,7 @@ import { DateTime } from 'luxon'; import { PersistenceContext } from './persistence/persistenceContext'; import { EntityName, - EntityRef, - parseEntityName, + parseEntityRef, stringifyEntityRef, } from '@backstage/catalog-model'; import { errorHandler } from '@backstage/backend-common'; @@ -130,7 +129,7 @@ export async function createRouter< */ router.get('/facts/latest', async (req, res) => { const { entity } = req.query; - const { namespace, kind, name } = parseEntityName(entity as EntityRef); + const { namespace, kind, name } = parseEntityRef(entity as string); const ids = req.query.ids as string[]; return res.send( await techInsightsStore.getLatestFactsByIds( @@ -145,7 +144,7 @@ export async function createRouter< */ router.get('/facts/range', async (req, res) => { const { entity } = req.query; - const { namespace, kind, name } = parseEntityName(entity as EntityRef); + const { namespace, kind, name } = parseEntityRef(entity as string); const ids = req.query.ids as string[]; const startDatetime = DateTime.fromISO(req.query.startDatetime as string); From bbbd0f0950d72597421528afd3420efee51ba306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:43:03 +0100 Subject: [PATCH 07/11] deprecate parseEntityName MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../src/service/CodeCoverageDatabase.ts | 4 ++-- .../scaffolder/src/components/TaskPage/TaskPageLinks.tsx | 4 ++-- .../src/service/persistence/TechInsightsDatabase.ts | 6 +++--- plugins/todo-backend/src/service/router.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts index 580d560bae..9235f3a8fd 100644 --- a/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts +++ b/plugins/code-coverage-backend/src/service/CodeCoverageDatabase.ts @@ -15,7 +15,7 @@ */ import { resolvePackagePath } from '@backstage/backend-common'; import { NotFoundError } from '@backstage/errors'; -import { parseEntityName, stringifyEntityRef } from '@backstage/catalog-model'; +import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; import { aggregateCoverage } from './CoverageUtils'; @@ -103,7 +103,7 @@ export class CodeCoverageDatabase implements CodeCoverageStore { .map(r => JSON.parse(r.coverage)) .map(c => aggregateCoverage(c)); - const entityName = parseEntityName(entity); + const entityName = parseEntityRef(entity); return { entity: { diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx index 2adec564a1..d53b5d705c 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { parseEntityName } from '@backstage/catalog-model'; +import { parseEntityRef } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { Box } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; @@ -57,7 +57,7 @@ export const TaskPageLinks = ({ output }: TaskPageLinksProps) => { .filter(({ url, entityRef }) => url || entityRef) .map(({ url, entityRef, title, icon }) => { if (entityRef) { - const entityName = parseEntityName(entityRef); + const entityName = parseEntityRef(entityRef); const target = entityRoute(entityName); return { title, icon, url: target }; } diff --git a/plugins/tech-insights-backend/src/service/persistence/TechInsightsDatabase.ts b/plugins/tech-insights-backend/src/service/persistence/TechInsightsDatabase.ts index 0b7013295f..ddb90b75cd 100644 --- a/plugins/tech-insights-backend/src/service/persistence/TechInsightsDatabase.ts +++ b/plugins/tech-insights-backend/src/service/persistence/TechInsightsDatabase.ts @@ -26,7 +26,7 @@ import { rsort } from 'semver'; import { groupBy, omit } from 'lodash'; import { DateTime } from 'luxon'; import { Logger } from 'winston'; -import { parseEntityName, stringifyEntityRef } from '@backstage/catalog-model'; +import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; import { isMaxItems, isTtl } from '../fact/factRetrievers/utils'; type Transaction = Knex.Transaction; @@ -161,7 +161,7 @@ export class TechInsightsDatabase implements TechInsightsStore { return groupBy( results.map(it => { - const { namespace, kind, name } = parseEntityName(it.entity); + const { namespace, kind, name } = parseEntityRef(it.entity); const timestamp = typeof it.timestamp === 'string' ? DateTime.fromISO(it.timestamp) @@ -253,7 +253,7 @@ export class TechInsightsDatabase implements TechInsightsStore { private dbFactRowsToTechInsightFacts(rows: RawDbFactRow[]) { return rows.reduce((acc, it) => { - const { namespace, kind, name } = parseEntityName(it.entity); + const { namespace, kind, name } = parseEntityRef(it.entity); const timestamp = typeof it.timestamp === 'string' ? DateTime.fromISO(it.timestamp) diff --git a/plugins/todo-backend/src/service/router.ts b/plugins/todo-backend/src/service/router.ts index 203e552161..a0e6a6ec94 100644 --- a/plugins/todo-backend/src/service/router.ts +++ b/plugins/todo-backend/src/service/router.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { EntityName, parseEntityName } from '@backstage/catalog-model'; +import { EntityName, parseEntityRef } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; import express from 'express'; import Router from 'express-promise-router'; @@ -55,7 +55,7 @@ export async function createRouter( let entity: EntityName | undefined = undefined; if (entityRef) { try { - entity = parseEntityName(entityRef); + entity = parseEntityRef(entityRef); } catch (error) { throw new InputError(`Invalid entity ref, ${error}`); } From ff3c04041f4e2322a0995cbc0be396b18c044d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 11:50:45 +0100 Subject: [PATCH 08/11] remove all usage of EntityRef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- packages/catalog-model/src/entity/ref.ts | 18 +++++++++++------- packages/catalog-model/src/types.ts | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/catalog-model/src/entity/ref.ts b/packages/catalog-model/src/entity/ref.ts index 769273dc45..850b11686f 100644 --- a/packages/catalog-model/src/entity/ref.ts +++ b/packages/catalog-model/src/entity/ref.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { EntityName, EntityRef } from '../types'; import { DEFAULT_NAMESPACE } from './constants'; +import { EntityName } from '../types'; import { Entity } from './Entity'; function parseRefString(ref: string): { @@ -76,13 +76,14 @@ export type EntityRefContext = { * otherwise specified as part of the options, and will throw an error if no * kind was specified in the input reference and no default kind was given. * + * @deprecated Please use parseEntityRef instead * @public * @param ref - The reference to parse * @param context - The context of defaults that the parsing happens within * @returns A complete entity name */ export function parseEntityName( - ref: EntityRef, + ref: string | { kind?: string; namespace?: string; name: string }, context: { /** The default kind, if none is given in the reference */ defaultKind?: string; @@ -119,7 +120,7 @@ export function parseEntityName( * @returns The compound form of the reference */ export function parseEntityRef( - ref: EntityRef, + ref: string | { kind?: string; namespace?: string; name: string }, context?: { defaultKind: string; defaultNamespace: string }, ): EntityName; /** @@ -128,7 +129,7 @@ export function parseEntityRef( * @public */ export function parseEntityRef( - ref: EntityRef, + ref: string | { kind?: string; namespace?: string; name: string }, context?: { defaultKind: string }, ): { kind: string; @@ -141,7 +142,7 @@ export function parseEntityRef( * @public */ export function parseEntityRef( - ref: EntityRef, + ref: string | { kind?: string; namespace?: string; name: string }, context?: { defaultNamespace: string }, ): { kind?: string; @@ -154,7 +155,7 @@ export function parseEntityRef( * @public */ export function parseEntityRef( - ref: EntityRef, + ref: string | { kind?: string; namespace?: string; name: string }, context: { /** The default kind, if none is given in the reference */ defaultKind?: string; @@ -249,7 +250,10 @@ export function stringifyEntityRef( */ export function compareEntityToRef( entity: Entity, - ref: EntityRef | EntityName, + ref: + | string + | { kind?: string; namespace?: string; name: string } + | EntityName, context?: { /** The default kind, if none is given in the reference */ defaultKind?: string; diff --git a/packages/catalog-model/src/types.ts b/packages/catalog-model/src/types.ts index 0526f8807e..13550968be 100644 --- a/packages/catalog-model/src/types.ts +++ b/packages/catalog-model/src/types.ts @@ -40,6 +40,7 @@ export type EntityName = { * A reference by name to an entity, either as a compact string representation, * or as a compound reference structure. * + * @deprecated Please use string directly, or EntityName (depending on what you actually need) * @remarks * * The string representation is on the form `[:][/]`. From 67a7c02d266b9115fa29eae096077ea117c5581d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 12:01:13 +0100 Subject: [PATCH 09/11] changesets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/happy-balloons-smell.md | 12 ++++++++ .changeset/slow-waves-press.md | 8 +++++ packages/catalog-model/api-report.md | 45 +++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 .changeset/happy-balloons-smell.md create mode 100644 .changeset/slow-waves-press.md diff --git a/.changeset/happy-balloons-smell.md b/.changeset/happy-balloons-smell.md new file mode 100644 index 0000000000..74b1f34230 --- /dev/null +++ b/.changeset/happy-balloons-smell.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-bazaar': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-jenkins-backend': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-tech-insights-backend': patch +'@backstage/plugin-todo-backend': patch +--- + +Remove usages of `EntityRef` and `parseEntityName` from `@backstage/catalog-model` diff --git a/.changeset/slow-waves-press.md b/.changeset/slow-waves-press.md new file mode 100644 index 0000000000..d2a06df58e --- /dev/null +++ b/.changeset/slow-waves-press.md @@ -0,0 +1,8 @@ +--- +'@backstage/catalog-model': patch +--- + +**DEPRECATED**: The `EntityRef` type and `parseEntityName` function are now +deprecated, and will soon be removed. This is part of a larger movement toward +fixing the poorly named `EntityName` type which should instead have been named +`EntityRef`. Please remove any usage of these as soon as possible. diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 0afe87e709..5d8540d3cd 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -69,7 +69,14 @@ export class CommonValidatorFunctions { // @public @deprecated export function compareEntityToRef( entity: Entity, - ref: EntityRef | EntityName, + ref: + | string + | { + kind?: string; + namespace?: string; + name: string; + } + | EntityName, context?: { defaultKind?: string; defaultNamespace?: string; @@ -212,7 +219,7 @@ export type EntityPolicy = { enforce(entity: Entity): Promise; }; -// @public +// @public @deprecated export type EntityRef = | string | { @@ -384,9 +391,15 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { export const ORIGIN_LOCATION_ANNOTATION = 'backstage.io/managed-by-origin-location'; -// @public +// @public @deprecated export function parseEntityName( - ref: EntityRef, + ref: + | string + | { + kind?: string; + namespace?: string; + name: string; + }, context?: { defaultKind?: string; defaultNamespace?: string; @@ -395,7 +408,13 @@ export function parseEntityName( // @public export function parseEntityRef( - ref: EntityRef, + ref: + | string + | { + kind?: string; + namespace?: string; + name: string; + }, context?: { defaultKind: string; defaultNamespace: string; @@ -404,7 +423,13 @@ export function parseEntityRef( // @public export function parseEntityRef( - ref: EntityRef, + ref: + | string + | { + kind?: string; + namespace?: string; + name: string; + }, context?: { defaultKind: string; }, @@ -416,7 +441,13 @@ export function parseEntityRef( // @public export function parseEntityRef( - ref: EntityRef, + ref: + | string + | { + kind?: string; + namespace?: string; + name: string; + }, context?: { defaultNamespace: string; }, From a561569a10b2cd73b039b4546593e72f2409f341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 13:36:46 +0100 Subject: [PATCH 10/11] default namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- packages/catalog-model/src/entity/ref.test.ts | 4 ++-- packages/catalog-model/src/entity/ref.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/catalog-model/src/entity/ref.test.ts b/packages/catalog-model/src/entity/ref.test.ts index 9fc55612fe..ba0402cb71 100644 --- a/packages/catalog-model/src/entity/ref.test.ts +++ b/packages/catalog-model/src/entity/ref.test.ts @@ -194,12 +194,12 @@ describe('ref', () => { }); expect(parseEntityRef('a:c')).toEqual({ kind: 'a', - namespace: undefined, + namespace: 'default', name: 'c', }); expect(parseEntityRef('c')).toEqual({ kind: undefined, - namespace: undefined, + namespace: 'default', name: 'c', }); }); diff --git a/packages/catalog-model/src/entity/ref.ts b/packages/catalog-model/src/entity/ref.ts index 850b11686f..3c77998eb8 100644 --- a/packages/catalog-model/src/entity/ref.ts +++ b/packages/catalog-model/src/entity/ref.ts @@ -171,11 +171,13 @@ export function parseEntityRef( throw new Error(`Entity reference must not be empty`); } + const defaultNamespace = context.defaultNamespace || DEFAULT_NAMESPACE; + if (typeof ref === 'string') { const parsed = parseRefString(ref); return { kind: parsed.kind ?? context.defaultKind, - namespace: parsed.namespace ?? context.defaultNamespace, + namespace: parsed.namespace ?? defaultNamespace, name: parsed.name, }; } @@ -191,7 +193,7 @@ export function parseEntityRef( return { kind: kind ?? context.defaultKind, - namespace: namespace ?? context.defaultNamespace, + namespace: namespace ?? defaultNamespace, name, }; } From 76e3cb1153def4edc9129b8dd7e46a3c58690ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 23 Feb 2022 14:33:35 +0100 Subject: [PATCH 11/11] fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/scaffolder-backend/src/service/router.test.ts | 8 ++++---- plugins/scaffolder-backend/src/service/router.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index f8336179eb..6a66d6df47 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -50,10 +50,10 @@ import request from 'supertest'; import { createRouter, DatabaseTaskStore, TaskBroker } from '../index'; import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker'; -const createCatalogClient = (templates: any[] = []) => +const createCatalogClient = (template: any) => ({ - getEntities: async () => ({ items: templates }), - } as CatalogApi); + getEntityByName: async () => template, + } as unknown as CatalogApi); function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -120,7 +120,7 @@ describe('createRouter', () => { logger: getVoidLogger(), config: new ConfigReader({}), database: createDatabase(), - catalogClient: createCatalogClient([template]), + catalogClient: createCatalogClient(template), containerRunner: new DockerContainerRunner({} as any), reader: mockUrlReader, taskBroker, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index f768e354de..e1cd75dcc2 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -179,7 +179,7 @@ export async function createRouter( }) .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; - const kind = 'Template'; + const kind = 'template'; const namespace = DEFAULT_NAMESPACE; const values = req.body.values; const token = getBearerToken(req.headers.authorization);