diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.test.ts index fe4cd18645..62769288fd 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.test.ts @@ -40,7 +40,11 @@ const defaultEntityListResponse: CatalogListResponse = { items: [ { apiVersion: 'backstage.io/v1beta1', - metadata: { name: 'service-with-owner' }, + metadata: { + name: 'service-with-owner', + description: 'service with an owner', + tags: ['a-tag'], + }, kind: 'Component', spec: { type: 'service', @@ -57,7 +61,9 @@ const defaultEntityListResponse: CatalogListResponse = { { apiVersion: 'backstage.io/v1beta1', metadata: { - name: 'service-without-owner', + name: 'service-with-incomplete-data', + description: '', + tags: [], }, kind: 'Component', spec: { @@ -78,6 +84,16 @@ const defaultEntityListResponse: CatalogListResponse = { owner: 'user:my-user', }, }, + { + apiVersion: 'backstage.io/v1beta1', + metadata: { + name: 'user-a', + }, + kind: 'User', + spec: { + memberOf: 'group-a', + }, + }, ], }; @@ -95,65 +111,138 @@ describe('entityFactRetriever', () => { getEntitiesMock.mockClear(); }); - describe('hasSpecWithOwner', () => { + describe('hasOwner', () => { describe('where the entity has an owner in the spec', () => { - it('returns true for hasSpecWithOwner', async () => { + it('returns true for hasOwner', async () => { const facts = await entityFactRetriever.handler(handlerContext); expect( facts.find(it => it.entity.name === 'service-with-owner'), ).toMatchObject({ facts: { - hasSpecWithOwner: true, + hasOwner: true, }, }); }); }); - describe('where the entity does not have an owner in the spec', () => { - it('returns false for hasSpecWithOwner', async () => { + describe('where the entity has an empty value for owner in the spec', () => { + it('returns false for hasOwner', async () => { const facts = await entityFactRetriever.handler(handlerContext); expect( - facts.find(it => it.entity.name === 'service-without-owner'), + facts.find(it => it.entity.name === 'service-with-incomplete-data'), ).toMatchObject({ facts: { - hasSpecWithOwner: false, + hasOwner: false, + }, + }); + }); + }); + + describe('where the entity doesn not have an owner in the spec', () => { + it('returns false for hasOwner', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect(facts.find(it => it.entity.name === 'user-a')).toMatchObject({ + facts: { + hasOwner: false, }, }); }); }); }); - describe('hasSpecWithGroupOwner', () => { + describe('hasGroupOwner', () => { describe('where the entity has an group as owner in the spec', () => { - it('returns true for hasSpecWithGroupOwner', async () => { + it('returns true for hasGroupOwner', async () => { const facts = await entityFactRetriever.handler(handlerContext); expect( facts.find(it => it.entity.name === 'service-with-owner'), ).toMatchObject({ facts: { - hasSpecWithGroupOwner: true, + hasGroupOwner: true, }, }); }); }); describe('where the entity has a user as owner in the spec', () => { - it('returns false for hasSpecWithGroupOwner', async () => { + it('returns false for hasGroupOwner', async () => { const facts = await entityFactRetriever.handler(handlerContext); expect( facts.find(it => it.entity.name === 'service-with-user-owner'), ).toMatchObject({ facts: { - hasSpecWithGroupOwner: false, + hasGroupOwner: false, }, }); }); }); - describe('where the entity does not have an owner in the spec', () => { - it('returns false for hasSpecWithGroupOwner', async () => { + describe('where the entity has an empty value for owner in the spec', () => { + it('returns false for hasGroupOwner', async () => { const facts = await entityFactRetriever.handler(handlerContext); expect( - facts.find(it => it.entity.name === 'service-without-owner'), + facts.find(it => it.entity.name === 'service-with-incomplete-data'), ).toMatchObject({ facts: { - hasSpecWithGroupOwner: false, + hasGroupOwner: false, + }, + }); + }); + }); + }); + describe('hasDescription', () => { + describe('where the entity has a description', () => { + it('returns true for hasDescription', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect( + facts.find(it => it.entity.name === 'service-with-owner'), + ).toMatchObject({ + facts: { + hasDescription: true, + }, + }); + }); + }); + describe('where the entity does not have a description', () => { + it('returns false for hasDescription', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect(facts.find(it => it.entity.name === 'user-a')).toMatchObject({ + facts: { + hasDescription: false, + }, + }); + }); + }); + describe('where the entity has an empty value for description', () => { + it('returns false for hasDescription', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect( + facts.find(it => it.entity.name === 'service-with-incomplete-data'), + ).toMatchObject({ + facts: { + hasDescription: false, + }, + }); + }); + }); + }); + describe('hasTags', () => { + describe('where the entity has tags', () => { + it('returns true for hasTags', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect( + facts.find(it => it.entity.name === 'service-with-owner'), + ).toMatchObject({ + facts: { + hasTags: true, + }, + }); + }); + }); + describe('where the entity has no tags', () => { + it('returns false for hasTags', async () => { + const facts = await entityFactRetriever.handler(handlerContext); + expect( + facts.find(it => it.entity.name === 'service-with-incomplete-data'), + ).toMatchObject({ + facts: { + hasTags: false, }, }); }); diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.ts index 1488cf71ca..7d6a3987e0 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityFactRetriever.ts @@ -16,53 +16,31 @@ import { FactRetrieverContext } from '@backstage/plugin-tech-insights-node'; import { CatalogClient } from '@backstage/catalog-client'; -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; - -const applicableEntityKinds = [ - 'component', - 'api', - 'template', - 'domain', - 'resource', - 'system', -]; - -const entityKindFilter = { field: 'kind', values: applicableEntityKinds }; +import { Entity } from '@backstage/catalog-model'; +import isEmpty from 'lodash/isEmpty'; export const entityFactRetriever = { id: 'entityRetriever', version: '0.0.1', - entityFilter: [ - { - field: 'kind', - values: applicableEntityKinds, - }, - ], schema: { - hasSpecWithOwner: { + hasOwner: { type: 'boolean', description: 'The spec.owner field is set', }, - hasSpecWithGroupOwner: { + hasGroupOwner: { type: 'boolean', description: 'The spec.owner field is set and refers to a group', }, - hasOwnedByRelation: { + hasDescription: { type: 'boolean', description: 'The entity has an owned_by relation', }, - hasOwnedByRelationWithGroupTarget: { - type: 'boolean', - description: 'The entity has an owned_by relation which targets a group', - }, }, handler: async ({ discovery }: FactRetrieverContext) => { const catalogClient = new CatalogClient({ discoveryApi: discovery, }); - const entities = await catalogClient.getEntities({ - filter: entityKindFilter, - }); + const entities = await catalogClient.getEntities(); return entities.items.map((it: Entity) => { return { @@ -72,21 +50,12 @@ export const entityFactRetriever = { name: it.metadata.name, }, facts: { - hasSpecWithOwner: Boolean(it.spec?.owner), - hasSpecWithGroupOwner: Boolean( + hasOwner: Boolean(it.spec?.owner), + hasGroupOwner: Boolean( it.spec?.owner && (it.spec?.owner as string).startsWith('group:'), ), - hasOwnedByRelation: Boolean( - it.relations && - it.relations.find(({ type }) => type === RELATION_OWNED_BY), - ), - hasOwnedByRelationWithGroupTarget: Boolean( - it.relations && - it.relations.find( - ({ type, target }) => - type === RELATION_OWNED_BY && target.kind === 'group', - ), - ), + hasDescription: Boolean(it.metadata?.description), + hasTags: !isEmpty(it.metadata?.tags), }, }; });