From 319012e0f983b728b1600705793172218cee6300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 12 Jun 2020 22:53:39 +0200 Subject: [PATCH 1/2] feat(catalog): new kind LocationRef --- packages/catalog-model/src/EntityPolicies.ts | 9 ++- .../src/kinds/ComponentV1beta1.ts | 15 +---- .../src/kinds/LocationRefV1beta1.ts | 56 +++++++++++++++++++ packages/catalog-model/src/kinds/index.ts | 13 +++-- .../catalog-backend/examples/locationref.yaml | 8 +++ .../src/ingestion/LocationReaders.ts | 2 + .../processors/LocationRefProcessor.ts | 46 +++++++++++++++ 7 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 packages/catalog-model/src/kinds/LocationRefV1beta1.ts create mode 100644 plugins/catalog-backend/examples/locationref.yaml create mode 100644 plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts diff --git a/packages/catalog-model/src/EntityPolicies.ts b/packages/catalog-model/src/EntityPolicies.ts index ca189c042e..1e71688c33 100644 --- a/packages/catalog-model/src/EntityPolicies.ts +++ b/packages/catalog-model/src/EntityPolicies.ts @@ -21,9 +21,9 @@ import { ReservedFieldsEntityPolicy, SchemaValidEntityPolicy, } from './entity'; -import { ComponentV1beta1Policy } from './kinds'; -import { EntityPolicy } from './types'; import { DefaultNamespaceEntityPolicy } from './entity/policies/DefaultNamespaceEntityPolicy'; +import { ComponentV1beta1Policy, LocationRefV1beta1Policy } from './kinds'; +import { EntityPolicy } from './types'; // Helper that requires that all of a set of policies can be successfully // applied @@ -68,7 +68,10 @@ export class EntityPolicies implements EntityPolicy { new FieldFormatEntityPolicy(), new ReservedFieldsEntityPolicy(), ]), - EntityPolicies.anyOf([new ComponentV1beta1Policy()]), + EntityPolicies.anyOf([ + new ComponentV1beta1Policy(), + new LocationRefV1beta1Policy(), + ]), ]); } diff --git a/packages/catalog-model/src/kinds/ComponentV1beta1.ts b/packages/catalog-model/src/kinds/ComponentV1beta1.ts index b041bf7967..32e315bb06 100644 --- a/packages/catalog-model/src/kinds/ComponentV1beta1.ts +++ b/packages/catalog-model/src/kinds/ComponentV1beta1.ts @@ -15,7 +15,7 @@ */ import * as yup from 'yup'; -import type { Entity, EntityMeta } from '../entity/Entity'; +import type { Entity } from '../entity/Entity'; import type { EntityPolicy } from '../types'; const API_VERSION = 'backstage.io/v1beta1'; @@ -24,9 +24,6 @@ const KIND = 'Component'; export interface ComponentV1beta1 extends Entity { apiVersion: typeof API_VERSION; kind: typeof KIND; - metadata: EntityMeta & { - name: string; - }; spec: { type: string; }; @@ -37,11 +34,6 @@ export class ComponentV1beta1Policy implements EntityPolicy { constructor() { this.schema = yup.object>({ - metadata: yup - .object({ - name: yup.string().required(), - }) - .required(), spec: yup .object({ type: yup.string().required(), @@ -51,10 +43,7 @@ export class ComponentV1beta1Policy implements EntityPolicy { } async enforce(envelope: Entity): Promise { - if ( - envelope.apiVersion !== 'backstage.io/v1beta1' || - envelope.kind !== 'Component' - ) { + if (envelope.apiVersion !== API_VERSION || envelope.kind !== KIND) { throw new Error('Unsupported apiVersion / kind'); } diff --git a/packages/catalog-model/src/kinds/LocationRefV1beta1.ts b/packages/catalog-model/src/kinds/LocationRefV1beta1.ts new file mode 100644 index 0000000000..74b68fe097 --- /dev/null +++ b/packages/catalog-model/src/kinds/LocationRefV1beta1.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 * as yup from 'yup'; +import type { Entity } from '../entity/Entity'; +import type { EntityPolicy } from '../types'; + +const API_VERSION = 'backstage.io/v1beta1'; +const KIND = 'LocationRef'; + +export interface LocationRefV1beta1 extends Entity { + apiVersion: typeof API_VERSION; + kind: typeof KIND; + spec: { + type: string; + target?: string; + targets?: string[]; + }; +} + +export class LocationRefV1beta1Policy implements EntityPolicy { + private schema: yup.Schema; + + constructor() { + this.schema = yup.object>({ + spec: yup + .object({ + type: yup.string().required(), + target: yup.string().notRequired(), + targets: yup.array(yup.string()).notRequired(), + }) + .required(), + }); + } + + async enforce(envelope: Entity): Promise { + if (envelope.apiVersion !== API_VERSION || envelope.kind !== KIND) { + throw new Error('Unsupported apiVersion / kind'); + } + + return await this.schema.validate(envelope, { strict: true }); + } +} diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts index ed79fed61d..8159b3b214 100644 --- a/packages/catalog-model/src/kinds/index.ts +++ b/packages/catalog-model/src/kinds/index.ts @@ -14,8 +14,13 @@ * limitations under the License. */ -export type { - ComponentV1beta1, - ComponentV1beta1 as Component, -} from './ComponentV1beta1'; export { ComponentV1beta1Policy } from './ComponentV1beta1'; +export type { + ComponentV1beta1 as Component, + ComponentV1beta1, +} from './ComponentV1beta1'; +export { LocationRefV1beta1Policy } from './LocationRefV1beta1'; +export type { + LocationRefV1beta1 as LocationRef, + LocationRefV1beta1, +} from './LocationRefV1beta1'; diff --git a/plugins/catalog-backend/examples/locationref.yaml b/plugins/catalog-backend/examples/locationref.yaml new file mode 100644 index 0000000000..78297f4fcd --- /dev/null +++ b/plugins/catalog-backend/examples/locationref.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: backstage.io/v1beta1 +kind: LocationRef +metadata: + name: location-1 +spec: + type: github + target: https://github.com/spotify/backstage/blob/master/plugins/catalog-backend/examples/example-components.yaml diff --git a/plugins/catalog-backend/src/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/ingestion/LocationReaders.ts index e806ecfbdb..270d859753 100644 --- a/plugins/catalog-backend/src/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/ingestion/LocationReaders.ts @@ -26,6 +26,7 @@ import { AnnotateLocationEntityProcessor } from './processors/AnnotateLocationEn import { EntityPolicyProcessor } from './processors/EntityPolicyProcessor'; import { FileReaderProcessor } from './processors/FileReaderProcessor'; import { GithubReaderProcessor } from './processors/GithubReaderProcessor'; +import { LocationRefProcessor } from './processors/LocationRefProcessor'; import * as result from './processors/results'; import { LocationProcessor, @@ -57,6 +58,7 @@ export class LocationReaders implements LocationReader { new GithubReaderProcessor(), new YamlProcessor(), new EntityPolicyProcessor(entityPolicy), + new LocationRefProcessor(), new AnnotateLocationEntityProcessor(), ]; } diff --git a/plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts new file mode 100644 index 0000000000..03cdd9229f --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { Entity, LocationRef, LocationSpec } from '@backstage/catalog-model'; +import * as result from './results'; +import { LocationProcessor, LocationProcessorEmit } from './types'; + +export class LocationRefProcessor implements LocationProcessor { + async processEntity( + entity: Entity, + _location: LocationSpec, + emit: LocationProcessorEmit, + ): Promise { + if (entity.kind === 'LocationRef') { + const location = entity as LocationRef; + if (location.spec.target) { + emit( + result.location( + { type: location.spec.type, target: location.spec.target }, + false, + ), + ); + } + if (location.spec.targets) { + for (const target of location.spec.targets) { + emit(result.location({ type: location.spec.type, target }, false)); + } + } + } + + return entity; + } +} From 1b2d70a70d2b879f070a3c87e40c5cd06fc81e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 15 Jun 2020 09:25:19 +0200 Subject: [PATCH 2/2] catalog: suffix entiy kind typeswith Entity --- packages/catalog-model/src/EntityPolicies.ts | 11 +++++++---- .../catalog-model/src/entity/policies/index.ts | 1 + ...onentV1beta1.ts => ComponentEntityV1beta1.ts} | 6 +++--- ...ionRefV1beta1.ts => LocationEntityV1beta1.ts} | 8 ++++---- packages/catalog-model/src/kinds/index.ts | 16 ++++++++-------- .../{locationref.yaml => example-location.yaml} | 2 +- .../src/ingestion/LocationReaders.ts | 2 +- ...efProcessor.ts => LocationEntityProcessor.ts} | 6 +++--- 8 files changed, 28 insertions(+), 24 deletions(-) rename packages/catalog-model/src/kinds/{ComponentV1beta1.ts => ComponentEntityV1beta1.ts} (87%) rename packages/catalog-model/src/kinds/{LocationRefV1beta1.ts => LocationEntityV1beta1.ts} (87%) rename plugins/catalog-backend/examples/{locationref.yaml => example-location.yaml} (91%) rename plugins/catalog-backend/src/ingestion/processors/{LocationRefProcessor.ts => LocationEntityProcessor.ts} (88%) diff --git a/packages/catalog-model/src/EntityPolicies.ts b/packages/catalog-model/src/EntityPolicies.ts index 1e71688c33..cf23bcdc88 100644 --- a/packages/catalog-model/src/EntityPolicies.ts +++ b/packages/catalog-model/src/EntityPolicies.ts @@ -15,14 +15,17 @@ */ import { + DefaultNamespaceEntityPolicy, Entity, FieldFormatEntityPolicy, NoForeignRootFieldsEntityPolicy, ReservedFieldsEntityPolicy, SchemaValidEntityPolicy, } from './entity'; -import { DefaultNamespaceEntityPolicy } from './entity/policies/DefaultNamespaceEntityPolicy'; -import { ComponentV1beta1Policy, LocationRefV1beta1Policy } from './kinds'; +import { + ComponentEntityV1beta1Policy, + LocationEntityV1beta1Policy, +} from './kinds'; import { EntityPolicy } from './types'; // Helper that requires that all of a set of policies can be successfully @@ -69,8 +72,8 @@ export class EntityPolicies implements EntityPolicy { new ReservedFieldsEntityPolicy(), ]), EntityPolicies.anyOf([ - new ComponentV1beta1Policy(), - new LocationRefV1beta1Policy(), + new ComponentEntityV1beta1Policy(), + new LocationEntityV1beta1Policy(), ]), ]); } diff --git a/packages/catalog-model/src/entity/policies/index.ts b/packages/catalog-model/src/entity/policies/index.ts index d64053f7cb..eb7c0e8378 100644 --- a/packages/catalog-model/src/entity/policies/index.ts +++ b/packages/catalog-model/src/entity/policies/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +export { DefaultNamespaceEntityPolicy } from './DefaultNamespaceEntityPolicy'; export { FieldFormatEntityPolicy } from './FieldFormatEntityPolicy'; export { NoForeignRootFieldsEntityPolicy } from './NoForeignRootFieldsEntityPolicy'; export { ReservedFieldsEntityPolicy } from './ReservedFieldsEntityPolicy'; diff --git a/packages/catalog-model/src/kinds/ComponentV1beta1.ts b/packages/catalog-model/src/kinds/ComponentEntityV1beta1.ts similarity index 87% rename from packages/catalog-model/src/kinds/ComponentV1beta1.ts rename to packages/catalog-model/src/kinds/ComponentEntityV1beta1.ts index 32e315bb06..2f5e8e079c 100644 --- a/packages/catalog-model/src/kinds/ComponentV1beta1.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1beta1.ts @@ -21,7 +21,7 @@ import type { EntityPolicy } from '../types'; const API_VERSION = 'backstage.io/v1beta1'; const KIND = 'Component'; -export interface ComponentV1beta1 extends Entity { +export interface ComponentEntityV1beta1 extends Entity { apiVersion: typeof API_VERSION; kind: typeof KIND; spec: { @@ -29,11 +29,11 @@ export interface ComponentV1beta1 extends Entity { }; } -export class ComponentV1beta1Policy implements EntityPolicy { +export class ComponentEntityV1beta1Policy implements EntityPolicy { private schema: yup.Schema; constructor() { - this.schema = yup.object>({ + this.schema = yup.object>({ spec: yup .object({ type: yup.string().required(), diff --git a/packages/catalog-model/src/kinds/LocationRefV1beta1.ts b/packages/catalog-model/src/kinds/LocationEntityV1beta1.ts similarity index 87% rename from packages/catalog-model/src/kinds/LocationRefV1beta1.ts rename to packages/catalog-model/src/kinds/LocationEntityV1beta1.ts index 74b68fe097..e68bb00aa0 100644 --- a/packages/catalog-model/src/kinds/LocationRefV1beta1.ts +++ b/packages/catalog-model/src/kinds/LocationEntityV1beta1.ts @@ -19,9 +19,9 @@ import type { Entity } from '../entity/Entity'; import type { EntityPolicy } from '../types'; const API_VERSION = 'backstage.io/v1beta1'; -const KIND = 'LocationRef'; +const KIND = 'Location'; -export interface LocationRefV1beta1 extends Entity { +export interface LocationEntityV1beta1 extends Entity { apiVersion: typeof API_VERSION; kind: typeof KIND; spec: { @@ -31,11 +31,11 @@ export interface LocationRefV1beta1 extends Entity { }; } -export class LocationRefV1beta1Policy implements EntityPolicy { +export class LocationEntityV1beta1Policy implements EntityPolicy { private schema: yup.Schema; constructor() { - this.schema = yup.object>({ + this.schema = yup.object>({ spec: yup .object({ type: yup.string().required(), diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts index 8159b3b214..2d2a0744c5 100644 --- a/packages/catalog-model/src/kinds/index.ts +++ b/packages/catalog-model/src/kinds/index.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -export { ComponentV1beta1Policy } from './ComponentV1beta1'; +export { ComponentEntityV1beta1Policy } from './ComponentEntityV1beta1'; export type { - ComponentV1beta1 as Component, - ComponentV1beta1, -} from './ComponentV1beta1'; -export { LocationRefV1beta1Policy } from './LocationRefV1beta1'; + ComponentEntityV1beta1 as ComponentEntity, + ComponentEntityV1beta1, +} from './ComponentEntityV1beta1'; +export { LocationEntityV1beta1Policy } from './LocationEntityV1beta1'; export type { - LocationRefV1beta1 as LocationRef, - LocationRefV1beta1, -} from './LocationRefV1beta1'; + LocationEntityV1beta1 as LocationEntity, + LocationEntityV1beta1, +} from './LocationEntityV1beta1'; diff --git a/plugins/catalog-backend/examples/locationref.yaml b/plugins/catalog-backend/examples/example-location.yaml similarity index 91% rename from plugins/catalog-backend/examples/locationref.yaml rename to plugins/catalog-backend/examples/example-location.yaml index 78297f4fcd..5c507b29b5 100644 --- a/plugins/catalog-backend/examples/locationref.yaml +++ b/plugins/catalog-backend/examples/example-location.yaml @@ -1,6 +1,6 @@ --- apiVersion: backstage.io/v1beta1 -kind: LocationRef +kind: Location metadata: name: location-1 spec: diff --git a/plugins/catalog-backend/src/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/ingestion/LocationReaders.ts index 270d859753..eee16ea0de 100644 --- a/plugins/catalog-backend/src/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/ingestion/LocationReaders.ts @@ -26,7 +26,7 @@ import { AnnotateLocationEntityProcessor } from './processors/AnnotateLocationEn import { EntityPolicyProcessor } from './processors/EntityPolicyProcessor'; import { FileReaderProcessor } from './processors/FileReaderProcessor'; import { GithubReaderProcessor } from './processors/GithubReaderProcessor'; -import { LocationRefProcessor } from './processors/LocationRefProcessor'; +import { LocationRefProcessor } from './processors/LocationEntityProcessor'; import * as result from './processors/results'; import { LocationProcessor, diff --git a/plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts similarity index 88% rename from plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts rename to plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts index 03cdd9229f..a5c9718574 100644 --- a/plugins/catalog-backend/src/ingestion/processors/LocationRefProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Entity, LocationRef, LocationSpec } from '@backstage/catalog-model'; +import { Entity, LocationEntity, LocationSpec } from '@backstage/catalog-model'; import * as result from './results'; import { LocationProcessor, LocationProcessorEmit } from './types'; @@ -24,8 +24,8 @@ export class LocationRefProcessor implements LocationProcessor { _location: LocationSpec, emit: LocationProcessorEmit, ): Promise { - if (entity.kind === 'LocationRef') { - const location = entity as LocationRef; + if (entity.kind === 'Location') { + const location = entity as LocationEntity; if (location.spec.target) { emit( result.location(