diff --git a/packages/catalog-model/src/EntityPolicies.ts b/packages/catalog-model/src/EntityPolicies.ts index abc953ab6f..fa25334d5f 100644 --- a/packages/catalog-model/src/EntityPolicies.ts +++ b/packages/catalog-model/src/EntityPolicies.ts @@ -29,10 +29,10 @@ import { EntityPolicy } from './types'; class AllEntityPolicies implements EntityPolicy { constructor(private readonly policies: EntityPolicy[]) {} - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { let result = entity; for (const policy of this.policies) { - result = await policy.apply(entity); + result = await policy.enforce(entity); } return result; } @@ -43,10 +43,10 @@ class AllEntityPolicies implements EntityPolicy { class AnyEntityPolicy implements EntityPolicy { constructor(private readonly policies: EntityPolicy[]) {} - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { for (const policy of this.policies) { try { - return await policy.apply(entity); + return await policy.enforce(entity); } catch { continue; } @@ -82,7 +82,7 @@ export class EntityPolicies implements EntityPolicy { this.policy = policy; } - apply(entity: Entity): Promise { - return this.policy.apply(entity); + enforce(entity: Entity): Promise { + return this.policy.enforce(entity); } } diff --git a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.test.ts index d81b1155be..14b44108e5 100644 --- a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.test.ts +++ b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.test.ts @@ -42,64 +42,64 @@ describe('FieldFormatEntityPolicy', () => { }); it('works for the happy path', async () => { - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad apiVersion', async () => { data.apiVersion = 7; - await expect(policy.apply(data)).rejects.toThrow(/apiVersion/); + await expect(policy.enforce(data)).rejects.toThrow(/apiVersion/); data.apiVersion = 'a#b'; - await expect(policy.apply(data)).rejects.toThrow(/apiVersion/); + await expect(policy.enforce(data)).rejects.toThrow(/apiVersion/); }); it('rejects bad kind', async () => { data.kind = 7; - await expect(policy.apply(data)).rejects.toThrow(/kind/); + await expect(policy.enforce(data)).rejects.toThrow(/kind/); data.kind = 'a#b'; - await expect(policy.apply(data)).rejects.toThrow(/kind/); + await expect(policy.enforce(data)).rejects.toThrow(/kind/); }); it('handles missing metadata gracefully', async () => { delete data.medatata; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('handles missing spec gracefully', async () => { delete data.spec; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad name', async () => { data.metadata.name = 7; - await expect(policy.apply(data)).rejects.toThrow(/name.*7/); + await expect(policy.enforce(data)).rejects.toThrow(/name.*7/); data.metadata.name = 'a'.repeat(1000); - await expect(policy.apply(data)).rejects.toThrow(/name.*aaaa/); + await expect(policy.enforce(data)).rejects.toThrow(/name.*aaaa/); }); it('rejects bad namespace', async () => { data.metadata.namespace = 7; - await expect(policy.apply(data)).rejects.toThrow(/namespace.*7/); + await expect(policy.enforce(data)).rejects.toThrow(/namespace.*7/); data.metadata.namespace = 'a'.repeat(1000); - await expect(policy.apply(data)).rejects.toThrow(/namespace.*aaaa/); + await expect(policy.enforce(data)).rejects.toThrow(/namespace.*aaaa/); }); it('rejects bad label key', async () => { data.metadata.labels['a#b'] = 'value'; - await expect(policy.apply(data)).rejects.toThrow(/label.*a#b/i); + await expect(policy.enforce(data)).rejects.toThrow(/label.*a#b/i); }); it('rejects bad label value', async () => { data.metadata.labels.a = 'a#b'; - await expect(policy.apply(data)).rejects.toThrow(/label.*a#b/i); + await expect(policy.enforce(data)).rejects.toThrow(/label.*a#b/i); }); it('rejects bad annotation key', async () => { data.metadata.annotations['a#b'] = 'value'; - await expect(policy.apply(data)).rejects.toThrow(/annotation.*a#b/i); + await expect(policy.enforce(data)).rejects.toThrow(/annotation.*a#b/i); }); it('rejects bad annotation value', async () => { data.metadata.annotations.a = 7; - await expect(policy.apply(data)).rejects.toThrow(/annotation.*7/i); + await expect(policy.enforce(data)).rejects.toThrow(/annotation.*7/i); }); }); diff --git a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts index 1f94354f3f..697e45b371 100644 --- a/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts +++ b/packages/catalog-model/src/entity/policies/FieldFormatEntityPolicy.ts @@ -32,7 +32,7 @@ export class FieldFormatEntityPolicy implements EntityPolicy { this.validators = validators; } - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { function require( field: string, value: any, diff --git a/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.test.ts index 190024bb29..50496682e8 100644 --- a/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.test.ts +++ b/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.test.ts @@ -42,11 +42,11 @@ describe('NoForeignRootFieldsEntityPolicy', () => { }); it('works for the happy path', async () => { - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects unknown root fields', async () => { data.spec2 = {}; - await expect(policy.apply(data)).rejects.toThrow(/spec2/i); + await expect(policy.enforce(data)).rejects.toThrow(/spec2/i); }); }); diff --git a/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.ts b/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.ts index 3c0a2f5d61..9d1851bc02 100644 --- a/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.ts +++ b/packages/catalog-model/src/entity/policies/NoForeignRootFieldsEntityPolicy.ts @@ -29,7 +29,7 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { this.knownFields = knownFields; } - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { for (const field of Object.keys(entity)) { if (!this.knownFields.includes(field)) { throw new Error(`Unknown field ${field}`); diff --git a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts index 348eabbdac..8db33955a7 100644 --- a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts +++ b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts @@ -42,21 +42,23 @@ describe('ReservedFieldsEntityPolicy', () => { }); it('works for the happy path', async () => { - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects reserved keys in the spec root', async () => { data.spec.apiVersion = 'a/b'; - await expect(policy.apply(data)).rejects.toThrow(/spec.*apiVersion/i); + await expect(policy.enforce(data)).rejects.toThrow(/spec.*apiVersion/i); }); it('rejects reserved keys in labels', async () => { data.metadata.labels.apiVersion = 'a'; - await expect(policy.apply(data)).rejects.toThrow(/label.*apiVersion/i); + await expect(policy.enforce(data)).rejects.toThrow(/label.*apiVersion/i); }); it('rejects reserved keys in annotations', async () => { data.metadata.annotations.apiVersion = 'a'; - await expect(policy.apply(data)).rejects.toThrow(/annotation.*apiVersion/i); + await expect(policy.enforce(data)).rejects.toThrow( + /annotation.*apiVersion/i, + ); }); }); diff --git a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts index be2f732ca4..d97469eecc 100644 --- a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts +++ b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts @@ -43,7 +43,7 @@ export class ReservedFieldsEntityPolicy implements EntityPolicy { ]; } - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { for (const field of this.reservedFields) { if (entity.spec?.hasOwnProperty(field)) { throw new Error( diff --git a/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.test.ts index b9d1165a60..d24aee9fe6 100644 --- a/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.test.ts +++ b/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.test.ts @@ -43,7 +43,7 @@ describe('SchemaValidEntityPolicy', () => { }); it('works for the happy path', async () => { - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); // @@ -51,113 +51,113 @@ describe('SchemaValidEntityPolicy', () => { // it('rejects wrong root type', async () => { - await expect(policy.apply((7 as unknown) as Entity)).rejects.toThrow( + await expect(policy.enforce((7 as unknown) as Entity)).rejects.toThrow( /object/, ); }); it('rejects missing apiVersion', async () => { delete data.apiVersion; - await expect(policy.apply(data)).rejects.toThrow(/apiVersion/); + await expect(policy.enforce(data)).rejects.toThrow(/apiVersion/); }); it('rejects bad apiVersion type', async () => { data.apiVersion = 7; - await expect(policy.apply(data)).rejects.toThrow(/apiVersion/); + await expect(policy.enforce(data)).rejects.toThrow(/apiVersion/); }); it('rejects missing kind', async () => { delete data.kind; - await expect(policy.apply(data)).rejects.toThrow(/kind/); + await expect(policy.enforce(data)).rejects.toThrow(/kind/); }); it('rejects bad kind type', async () => { data.kind = 7; - await expect(policy.apply(data)).rejects.toThrow(/kind/); + await expect(policy.enforce(data)).rejects.toThrow(/kind/); }); // // metadata // - it('accepts missing metadata', async () => { - delete data.medatata; - await expect(policy.apply(data)).resolves.toBe(data); + it('rejects missing metadata', async () => { + delete data.metadata; + await expect(policy.enforce(data)).rejects.toThrow(/metadata/); }); it('rejects bad metadata type', async () => { data.metadata = 7; - await expect(policy.apply(data)).rejects.toThrow(/metadata/); + await expect(policy.enforce(data)).rejects.toThrow(/metadata/); }); it('accepts missing uid', async () => { delete data.metadata.uid; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad uid type', async () => { data.metadata.uid = 7; - await expect(policy.apply(data)).rejects.toThrow(/uid/); + await expect(policy.enforce(data)).rejects.toThrow(/uid/); }); it('accepts missing etag', async () => { delete data.metadata.etag; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad etag type', async () => { data.metadata.etag = 7; - await expect(policy.apply(data)).rejects.toThrow(/etag/); + await expect(policy.enforce(data)).rejects.toThrow(/etag/); }); it('accepts missing generation', async () => { delete data.metadata.generation; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad generation type', async () => { data.metadata.generation = 'a'; - await expect(policy.apply(data)).rejects.toThrow(/generation/); + await expect(policy.enforce(data)).rejects.toThrow(/generation/); }); it('accepts missing name', async () => { delete data.metadata.name; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad name type', async () => { data.metadata.name = 7; - await expect(policy.apply(data)).rejects.toThrow(/name/); + await expect(policy.enforce(data)).rejects.toThrow(/name/); }); it('accepts missing namespace', async () => { delete data.metadata.namespace; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad namespace type', async () => { data.metadata.namespace = 7; - await expect(policy.apply(data)).rejects.toThrow(/namespace/); + await expect(policy.enforce(data)).rejects.toThrow(/namespace/); }); it('accepts missing labels', async () => { delete data.metadata.labels; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad labels type', async () => { data.metadata.labels = 7; - await expect(policy.apply(data)).rejects.toThrow(/labels/); + await expect(policy.enforce(data)).rejects.toThrow(/labels/); }); it('accepts missing annotations', async () => { delete data.metadata.annotations; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects bad annotations type', async () => { data.metadata.annotations = 7; - await expect(policy.apply(data)).rejects.toThrow(/annotations/); + await expect(policy.enforce(data)).rejects.toThrow(/annotations/); }); // @@ -166,11 +166,11 @@ describe('SchemaValidEntityPolicy', () => { it('accepts missing spec', async () => { delete data.spec; - await expect(policy.apply(data)).resolves.toBe(data); + await expect(policy.enforce(data)).resolves.toBe(data); }); it('rejects non-object spec', async () => { data.spec = 7; - await expect(policy.apply(data)).rejects.toThrow(/spec/); + await expect(policy.enforce(data)).rejects.toThrow(/spec/); }); }); diff --git a/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.ts b/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.ts index 7c0f5c20b6..3ae20a5094 100644 --- a/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.ts +++ b/packages/catalog-model/src/entity/policies/SchemaValidEntityPolicy.ts @@ -70,7 +70,7 @@ export class SchemaValidEntityPolicy implements EntityPolicy { this.schema = schema; } - async apply(entity: Entity): Promise { + async enforce(entity: Entity): Promise { try { return await this.schema.validate(entity, { strict: true }); } catch (e) { diff --git a/packages/catalog-model/src/kinds/ComponentV1beta1.ts b/packages/catalog-model/src/kinds/ComponentV1beta1.ts index b0a3f627a5..b041bf7967 100644 --- a/packages/catalog-model/src/kinds/ComponentV1beta1.ts +++ b/packages/catalog-model/src/kinds/ComponentV1beta1.ts @@ -50,7 +50,7 @@ export class ComponentV1beta1Policy implements EntityPolicy { }); } - async apply(envelope: Entity): Promise { + async enforce(envelope: Entity): Promise { if ( envelope.apiVersion !== 'backstage.io/v1beta1' || envelope.kind !== 'Component' diff --git a/packages/catalog-model/src/setupTests.ts b/packages/catalog-model/src/setupTests.ts deleted file mode 100644 index f3b69cc361..0000000000 --- a/packages/catalog-model/src/setupTests.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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. - */ diff --git a/packages/catalog-model/src/types.ts b/packages/catalog-model/src/types.ts index 1d581cf23f..29ca8bdfa3 100644 --- a/packages/catalog-model/src/types.ts +++ b/packages/catalog-model/src/types.ts @@ -28,5 +28,5 @@ export type EntityPolicy = { * @returns The incoming entity, or a mutated version of the same * @throws An error if the entity should be rejected */ - apply(entity: Entity): Promise; + enforce(entity: Entity): Promise; }; diff --git a/plugins/catalog-backend/src/database/DatabaseManager.test.ts b/plugins/catalog-backend/src/database/DatabaseManager.test.ts index c8d0aec332..9a4297904a 100644 --- a/plugins/catalog-backend/src/database/DatabaseManager.test.ts +++ b/plugins/catalog-backend/src/database/DatabaseManager.test.ts @@ -32,14 +32,14 @@ describe('DatabaseManager', () => { readLocation: jest.fn(), }; const policy: EntityPolicy = { - apply: jest.fn(), + enforce: jest.fn(), }; await expect( DatabaseManager.refreshLocations(db, reader, policy, getVoidLogger()), ).resolves.toBeUndefined(); expect(reader.readLocation).not.toHaveBeenCalled(); - expect(policy.apply).not.toHaveBeenCalled(); + expect(policy.enforce).not.toHaveBeenCalled(); }); it('can update a single location', async () => { @@ -70,7 +70,7 @@ describe('DatabaseManager', () => { ), }; const policy: EntityPolicy = { - apply: jest.fn(() => Promise.resolve(desc)), + enforce: jest.fn(() => Promise.resolve(desc)), }; await expect( @@ -118,7 +118,7 @@ describe('DatabaseManager', () => { ), }; const policy: EntityPolicy = { - apply: jest.fn(() => Promise.resolve(desc)), + enforce: jest.fn(() => Promise.resolve(desc)), }; await expect( @@ -170,7 +170,9 @@ describe('DatabaseManager', () => { ), }; const policy: EntityPolicy = { - apply: jest.fn(() => Promise.reject(new Error('parser error message'))), + enforce: jest.fn(() => + Promise.reject(new Error('parser error message')), + ), }; await expect( @@ -217,7 +219,9 @@ describe('DatabaseManager', () => { ), }; const policy: EntityPolicy = { - apply: jest.fn(() => Promise.reject(new Error('parser error message'))), + enforce: jest.fn(() => + Promise.reject(new Error('parser error message')), + ), }; await expect( diff --git a/plugins/catalog-backend/src/database/DatabaseManager.ts b/plugins/catalog-backend/src/database/DatabaseManager.ts index a3aded18ec..c6e7a2e684 100644 --- a/plugins/catalog-backend/src/database/DatabaseManager.ts +++ b/plugins/catalog-backend/src/database/DatabaseManager.ts @@ -86,7 +86,7 @@ export class DatabaseManager { } try { - const entity = await entityPolicy.apply(readerItem.data); + const entity = await entityPolicy.enforce(readerItem.data); await DatabaseManager.refreshSingleEntity( database, location.id, diff --git a/plugins/catalog-backend/src/ingestion/IngestionModels.ts b/plugins/catalog-backend/src/ingestion/IngestionModels.ts index 616f1b49ae..def6f1fa5c 100644 --- a/plugins/catalog-backend/src/ingestion/IngestionModels.ts +++ b/plugins/catalog-backend/src/ingestion/IngestionModels.ts @@ -60,7 +60,7 @@ export class IngestionModels implements IngestionModel { result.push(item); } else { try { - const output = await this.entityPolicy.apply(item.data); + const output = await this.entityPolicy.enforce(item.data); result.push({ type: 'data', data: output }); } catch (e) { result.push({ type: 'error', error: e });