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.
diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md
index a28db34c0c..ba16b5d4f0 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';
@@ -49,19 +48,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/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];
- }
-}
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..5cfc58d586 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,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 {
+ 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];
+}
diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts
index 440f74d6f6..b2978441bd 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,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;