+37
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { entityFactRetriever } from './entityFactRetriever';
|
||||
import { createEntityFactRetriever } from './entityFactRetriever';
|
||||
import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model';
|
||||
import {
|
||||
PluginEndpointDiscovery,
|
||||
@@ -44,6 +44,9 @@ const defaultEntityListResponse: CatalogListResponse<Entity> = {
|
||||
name: 'service-with-owner',
|
||||
description: 'service with an owner',
|
||||
tags: ['a-tag'],
|
||||
annotations: {
|
||||
'backstage.io/techdocs-ref': 'dir:.',
|
||||
},
|
||||
},
|
||||
kind: 'Component',
|
||||
spec: {
|
||||
@@ -103,6 +106,10 @@ const handlerContext = {
|
||||
config: ConfigReader.fromConfigs([]),
|
||||
};
|
||||
|
||||
const entityFactRetriever = createEntityFactRetriever({
|
||||
annotations: ['backstage.io/techdocs-ref'],
|
||||
});
|
||||
|
||||
describe('entityFactRetriever', () => {
|
||||
beforeEach(() => {
|
||||
getEntitiesMock.mockResolvedValue(defaultEntityListResponse);
|
||||
@@ -248,4 +255,33 @@ describe('entityFactRetriever', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dynamic annotation facts', () => {
|
||||
describe('where the retriever is configured to check for the techdocs annotation', () => {
|
||||
describe('where the entity has the techdocs annotation', () => {
|
||||
it('returns true for hasAnnotationBackstageIoTechdocsRef', async () => {
|
||||
const facts = await entityFactRetriever.handler(handlerContext);
|
||||
expect(
|
||||
facts.find(it => it.entity.name === 'service-with-owner'),
|
||||
).toMatchObject({
|
||||
facts: {
|
||||
hasAnnotationBackstageIoTechdocsRef: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('where the entity is missing the techdocs annotation', () => {
|
||||
it('returns false for hasAnnotationBackstageIoTechdocsRef', async () => {
|
||||
const facts = await entityFactRetriever.handler(handlerContext);
|
||||
expect(
|
||||
facts.find(it => it.entity.name === 'service-with-incomplete-data'),
|
||||
).toMatchObject({
|
||||
facts: {
|
||||
hasAnnotationBackstageIoTechdocsRef: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+35
-10
@@ -18,8 +18,14 @@ import { FactRetrieverContext } from '@backstage/plugin-tech-insights-node';
|
||||
import { CatalogClient } from '@backstage/catalog-client';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { get } from 'lodash';
|
||||
|
||||
export const entityFactRetriever = {
|
||||
export const createEntityFactRetriever = ({
|
||||
annotations = [],
|
||||
}: {
|
||||
annotations?: string[];
|
||||
}) => ({
|
||||
id: 'entityRetriever',
|
||||
version: '0.0.1',
|
||||
schema: {
|
||||
@@ -35,6 +41,15 @@ export const entityFactRetriever = {
|
||||
type: 'boolean',
|
||||
description: 'The entity has an owned_by relation',
|
||||
},
|
||||
...annotations.reduce((acc: object, it: string) => {
|
||||
return {
|
||||
...acc,
|
||||
[camelCase(`hasAnnotation-${it}`)]: {
|
||||
type: 'boolean',
|
||||
description: `The entity has the annotation: ${it} `,
|
||||
},
|
||||
};
|
||||
}, {}),
|
||||
},
|
||||
handler: async ({ discovery }: FactRetrieverContext) => {
|
||||
const catalogClient = new CatalogClient({
|
||||
@@ -42,22 +57,32 @@ export const entityFactRetriever = {
|
||||
});
|
||||
const entities = await catalogClient.getEntities();
|
||||
|
||||
return entities.items.map((it: Entity) => {
|
||||
return entities.items.map((entity: Entity) => {
|
||||
return {
|
||||
entity: {
|
||||
namespace: it.metadata.namespace!!,
|
||||
kind: it.kind,
|
||||
name: it.metadata.name,
|
||||
namespace: entity.metadata.namespace!!,
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
},
|
||||
facts: {
|
||||
hasOwner: Boolean(it.spec?.owner),
|
||||
hasOwner: Boolean(entity.spec?.owner),
|
||||
hasGroupOwner: Boolean(
|
||||
it.spec?.owner && (it.spec?.owner as string).startsWith('group:'),
|
||||
entity.spec?.owner &&
|
||||
(entity.spec?.owner as string).startsWith('group:'),
|
||||
),
|
||||
hasDescription: Boolean(entity.metadata?.description),
|
||||
hasTags: !isEmpty(entity.metadata?.tags),
|
||||
...annotations.reduce(
|
||||
(acc: object, annotation: string) => ({
|
||||
...acc,
|
||||
[camelCase(`hasAnnotation-${annotation}`)]: Boolean(
|
||||
get(entity, ['metadata', 'annotations', annotation]),
|
||||
),
|
||||
}),
|
||||
{},
|
||||
),
|
||||
hasDescription: Boolean(it.metadata?.description),
|
||||
hasTags: !isEmpty(it.metadata?.tags),
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user