catalog-backend: revert GroupPopulatorProc, replace with OwnerRelationProc + relation consts
Co-authored-by: blam <ben@blam.sh> Co-authored-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Group
|
||||
metadata:
|
||||
name: root
|
||||
spec:
|
||||
type: org
|
||||
---
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Group
|
||||
metadata:
|
||||
name: platform
|
||||
spec:
|
||||
type: mission
|
||||
parent: root
|
||||
# ---
|
||||
# apiVersion: backstage.io/v1alpha1
|
||||
# kind: Group
|
||||
# metadata:
|
||||
# name: pdx
|
||||
# spec:
|
||||
# type: tribe
|
||||
# parent: platform
|
||||
# ---
|
||||
# apiVersion: backstage.io/v1alpha1
|
||||
# kind: Group
|
||||
# metadata:
|
||||
# name: tools
|
||||
# spec:
|
||||
# type: squad
|
||||
# parent: pdx
|
||||
# ---
|
||||
# apiVersion: backstage.io/v1alpha1
|
||||
# kind: Group
|
||||
# metadata:
|
||||
# name: pulp-fiction
|
||||
# spec:
|
||||
# type: squad
|
||||
# parent: pdx
|
||||
@@ -32,21 +32,21 @@ const schema = yup.object<Partial<GroupEntityV1alpha1>>({
|
||||
// one element and there is no simple workaround -_-
|
||||
// the cast is there to convince typescript that the array itself is
|
||||
// required without using .required()
|
||||
// ancestors: yup.array(yup.string().required()).test({
|
||||
// name: 'isDefined',
|
||||
// message: 'ancestors must be defined',
|
||||
// test: v => Boolean(v),
|
||||
// }) as yup.ArraySchema<string, object>,
|
||||
// children: yup.array(yup.string().required()).test({
|
||||
// name: 'isDefined',
|
||||
// message: 'children must be defined',
|
||||
// test: v => Boolean(v),
|
||||
// }) as yup.ArraySchema<string, object>,
|
||||
// descendants: yup.array(yup.string().required()).test({
|
||||
// name: 'isDefined',
|
||||
// message: 'descendants must be defined',
|
||||
// test: v => Boolean(v),
|
||||
// }) as yup.ArraySchema<string, object>,
|
||||
ancestors: yup.array(yup.string().required()).test({
|
||||
name: 'isDefined',
|
||||
message: 'ancestors must be defined',
|
||||
test: v => Boolean(v),
|
||||
}) as yup.ArraySchema<string, object>,
|
||||
children: yup.array(yup.string().required()).test({
|
||||
name: 'isDefined',
|
||||
message: 'children must be defined',
|
||||
test: v => Boolean(v),
|
||||
}) as yup.ArraySchema<string, object>,
|
||||
descendants: yup.array(yup.string().required()).test({
|
||||
name: 'isDefined',
|
||||
message: 'descendants must be defined',
|
||||
test: v => Boolean(v),
|
||||
}) as yup.ArraySchema<string, object>,
|
||||
})
|
||||
.required(),
|
||||
});
|
||||
|
||||
@@ -37,11 +37,11 @@ const schema = yup.object<Partial<UserEntityV1alpha1>>({
|
||||
// element and there is no simple workaround -_-
|
||||
// the cast is there to convince typescript that the array itself is
|
||||
// required without using .required()
|
||||
// memberOf: yup.array(yup.string().required()).test({
|
||||
// name: 'isDefined',
|
||||
// message: 'memberOf must be defined',
|
||||
// test: v => Boolean(v),
|
||||
// }) as yup.ArraySchema<string, object>,
|
||||
memberOf: yup.array(yup.string().required()).test({
|
||||
name: 'isDefined',
|
||||
message: 'memberOf must be defined',
|
||||
test: v => Boolean(v),
|
||||
}) as yup.ArraySchema<string, object>,
|
||||
})
|
||||
.required(),
|
||||
});
|
||||
|
||||
@@ -44,3 +44,4 @@ export type {
|
||||
UserEntityV1alpha1 as UserEntity,
|
||||
UserEntityV1alpha1,
|
||||
} from './UserEntityV1alpha1';
|
||||
export * from './relations';
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Naming rules for relations in priority order:
|
||||
|
||||
1. Use at most two words. One main verb and a specifier, e.g. "ownerOf"
|
||||
2. Reading out "<source-kind> <type> <target-kind>" should make sense in English.
|
||||
3. Maintain symmetry between pairs, e.g. "ownedBy" and "ownerOf" rather than "owns".
|
||||
*/
|
||||
|
||||
/**
|
||||
* An ownership relation where the owner is usually an organizational
|
||||
* entity (user or group), and the other entity can be anything.
|
||||
*/
|
||||
export const RELATION_OWNED_BY = 'ownedBy';
|
||||
export const RELATION_OWNER_OF = 'ownerOf';
|
||||
|
||||
/**
|
||||
* A relation with an API entity, typically from a component or system
|
||||
*/
|
||||
export const RELATION_IMPLEMENTED_BY = 'implementedBy';
|
||||
export const RELATION_IMPLEMENTS = 'implements';
|
||||
|
||||
/**
|
||||
* A relation denoting a dependency on another entity.
|
||||
*/
|
||||
export const RELATION_DEPENDS_ON = 'dependsOn';
|
||||
export const RELATION_DEPENDENCY_OF = 'dependencyOf';
|
||||
|
||||
/**
|
||||
* A parent/child relation to build up a tree, used for example to describe
|
||||
* the organizational structure between groups.
|
||||
*/
|
||||
export const RELATION_PARENT_OF = 'parentOf';
|
||||
export const RELATION_CHILD_OF = 'childOf';
|
||||
|
||||
/**
|
||||
* A membership relation, typically for users in a group.
|
||||
*/
|
||||
export const RELATION_MEMBER_OF = 'memberOf';
|
||||
export const RELATION_HAS_MEMBER = 'hasMember';
|
||||
+31
-36
@@ -17,66 +17,61 @@
|
||||
import {
|
||||
Entity,
|
||||
ENTITY_DEFAULT_NAMESPACE,
|
||||
GroupEntity,
|
||||
LocationSpec,
|
||||
parseEntityRef,
|
||||
ApiEntityV1alpha1,
|
||||
ComponentEntityV1alpha1,
|
||||
RELATION_OWNED_BY,
|
||||
RELATION_OWNER_OF,
|
||||
} from '@backstage/catalog-model';
|
||||
import { CatalogProcessor, CatalogProcessorEmit } from './types';
|
||||
import * as result from './results';
|
||||
|
||||
export class GroupPopulatorProcessor implements CatalogProcessor {
|
||||
const includedKinds = new Set(['api', 'component']);
|
||||
|
||||
export class OwnerRelationProcessor implements CatalogProcessor {
|
||||
async postProcessEntity(
|
||||
entity: Entity,
|
||||
_location: LocationSpec,
|
||||
emit: CatalogProcessorEmit,
|
||||
): Promise<Entity> {
|
||||
if (entity.kind.toLowerCase() !== 'group') {
|
||||
if (!includedKinds.has(entity.kind.toLowerCase())) {
|
||||
return entity;
|
||||
}
|
||||
const spec = entity.spec as GroupEntity['spec'];
|
||||
const apiOrComponentEntity = entity as
|
||||
| ApiEntityV1alpha1
|
||||
| ComponentEntityV1alpha1;
|
||||
|
||||
const { parent, children } = spec;
|
||||
const self = {
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
namespace: entity.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE,
|
||||
};
|
||||
const owner = apiOrComponentEntity.spec?.owner;
|
||||
if (owner) {
|
||||
const namespace = entity.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE;
|
||||
|
||||
const selfRef = {
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
namespace,
|
||||
};
|
||||
const ownerRef = parseEntityRef(owner, {
|
||||
defaultKind: 'group',
|
||||
defaultNamespace: namespace,
|
||||
});
|
||||
|
||||
if (parent) {
|
||||
emit(
|
||||
result.relation({
|
||||
type: 'parent',
|
||||
source: self,
|
||||
target: { ...self, name: parent },
|
||||
type: RELATION_OWNED_BY,
|
||||
source: selfRef,
|
||||
target: ownerRef,
|
||||
}),
|
||||
);
|
||||
emit(
|
||||
result.relation({
|
||||
type: 'child',
|
||||
source: { ...self, name: parent },
|
||||
target: self,
|
||||
type: RELATION_OWNER_OF,
|
||||
source: ownerRef,
|
||||
target: selfRef,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (children) {
|
||||
for (const child of children) {
|
||||
emit(
|
||||
result.relation({
|
||||
type: 'child',
|
||||
source: self,
|
||||
target: { ...self, name: child },
|
||||
}),
|
||||
);
|
||||
emit(
|
||||
result.relation({
|
||||
type: 'parent',
|
||||
source: { ...self, name: child },
|
||||
target: self,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor';
|
||||
export { GithubReaderProcessor } from './GithubReaderProcessor';
|
||||
export { GitlabApiReaderProcessor } from './GitlabApiReaderProcessor';
|
||||
export { GitlabReaderProcessor } from './GitlabReaderProcessor';
|
||||
export { GroupPopulatorProcessor } from './GroupPopulatorProcessor';
|
||||
export { OwnerRelationProcessor } from './OwnerRelationProcessor';
|
||||
export { LocationRefProcessor } from './LocationEntityProcessor';
|
||||
export { PlaceholderProcessor } from './PlaceholderProcessor';
|
||||
export type { PlaceholderResolver } from './PlaceholderProcessor';
|
||||
|
||||
@@ -52,7 +52,7 @@ import {
|
||||
GithubReaderProcessor,
|
||||
GitlabApiReaderProcessor,
|
||||
GitlabReaderProcessor,
|
||||
GroupPopulatorProcessor,
|
||||
OwnerRelationProcessor,
|
||||
HigherOrderOperation,
|
||||
HigherOrderOperations,
|
||||
LocationReaders,
|
||||
@@ -335,7 +335,7 @@ export class CatalogBuilder {
|
||||
new YamlProcessor(),
|
||||
new CodeOwnersProcessor({ reader }),
|
||||
new LocationRefProcessor(),
|
||||
new GroupPopulatorProcessor(),
|
||||
new OwnerRelationProcessor(),
|
||||
new AnnotateLocationEntityProcessor(),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user