feat(catalog): new kind LocationRef

This commit is contained in:
Fredrik Adelöw
2020-06-12 22:53:39 +02:00
parent 8054f61246
commit 319012e0f9
7 changed files with 129 additions and 20 deletions
+6 -3
View File
@@ -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(),
]),
]);
}
@@ -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<Partial<ComponentV1beta1>>({
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<Entity> {
if (
envelope.apiVersion !== 'backstage.io/v1beta1' ||
envelope.kind !== 'Component'
) {
if (envelope.apiVersion !== API_VERSION || envelope.kind !== KIND) {
throw new Error('Unsupported apiVersion / kind');
}
@@ -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<any>;
constructor() {
this.schema = yup.object<Partial<LocationRefV1beta1>>({
spec: yup
.object({
type: yup.string().required(),
target: yup.string().notRequired(),
targets: yup.array(yup.string()).notRequired(),
})
.required(),
});
}
async enforce(envelope: Entity): Promise<Entity> {
if (envelope.apiVersion !== API_VERSION || envelope.kind !== KIND) {
throw new Error('Unsupported apiVersion / kind');
}
return await this.schema.validate(envelope, { strict: true });
}
}
+9 -4
View File
@@ -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';
@@ -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
@@ -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(),
];
}
@@ -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<Entity> {
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;
}
}