diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md
index 0afe87e709..f27cfa5417 100644
--- a/packages/catalog-model/api-report.md
+++ b/packages/catalog-model/api-report.md
@@ -231,6 +231,7 @@ export type EntityRefContext = {
export type EntityRelation = {
type: string;
target: EntityName;
+ targetRef: string;
};
// @public
diff --git a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx
index 18222eea3a..16b335b0a7 100644
--- a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx
+++ b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx
@@ -66,7 +66,8 @@ describe('DefaultApiExplorerPage', () => {
relations: [
{
type: RELATION_MEMBER_OF,
- target: { namespace: 'default', kind: 'Group', name: 'tools' },
+ targetRef: 'group:default/tools',
+ target: { namespace: 'default', kind: 'group', name: 'tools' },
},
],
};
diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx
index d04a36770d..f84f66cee8 100644
--- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx
+++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx
@@ -95,10 +95,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'API',
+ kind: 'api',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'api:my-namespace/target-name',
type: RELATION_CONSUMES_API,
},
],
diff --git a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx
index 050eeb8707..daa909c7f8 100644
--- a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx
+++ b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx
@@ -95,10 +95,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'API',
+ kind: 'api',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'api:my-namespace/target-name',
type: RELATION_HAS_PART,
},
],
diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx
index 34043c519b..852386140c 100644
--- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx
+++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx
@@ -95,10 +95,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'API',
+ kind: 'api',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'api:my-namespace/target-name',
type: RELATION_PROVIDES_API,
},
],
diff --git a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx
index c81b4750bc..a62b2119c7 100644
--- a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx
+++ b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx
@@ -98,10 +98,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_API_CONSUMED_BY,
},
],
diff --git a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx
index 84e45dc058..1a0aae12c7 100644
--- a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx
+++ b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx
@@ -98,10 +98,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_API_PROVIDED_BY,
},
],
diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts
index 4388c2f82f..d2cee7bd89 100644
--- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts
+++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts
@@ -79,8 +79,9 @@ describe('CatalogIdentityClient', () => {
relations: [
{
type: RELATION_MEMBER_OF,
+ targetRef: 'group:default/team-a',
target: {
- kind: 'Group',
+ kind: 'group',
namespace: 'default',
name: 'team-a',
},
@@ -100,8 +101,9 @@ describe('CatalogIdentityClient', () => {
relations: [
{
type: RELATION_MEMBER_OF,
+ targetRef: 'group:reality/screen-actors-guild',
target: {
- kind: 'Group',
+ kind: 'group',
namespace: 'reality',
name: 'screen-actors-guild',
},
diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts
index aecf018975..d948af2e05 100644
--- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts
+++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.ts
@@ -120,11 +120,11 @@ export class CatalogIdentityClient {
e =>
e!.relations
?.filter(r => r.type === RELATION_MEMBER_OF)
- .map(r => r.target) ?? [],
+ .map(r => r.targetRef) ?? [],
);
const newEntityRefs = [
- ...new Set(resolvedEntityRefs.concat(memberOf).map(stringifyEntityRef)),
+ ...new Set(resolvedEntityRefs.map(stringifyEntityRef).concat(memberOf)),
];
logger?.debug(`Found catalog membership: ${newEntityRefs.join()}`);
diff --git a/plugins/auth-backend/src/lib/catalog/helpers.ts b/plugins/auth-backend/src/lib/catalog/helpers.ts
index 61dc428b3f..db9b38e2a6 100644
--- a/plugins/auth-backend/src/lib/catalog/helpers.ts
+++ b/plugins/auth-backend/src/lib/catalog/helpers.ts
@@ -27,11 +27,9 @@ export function getEntityClaims(entity: UserEntity): TokenParams['claims'] {
const membershipRefs =
entity.relations
?.filter(
- r =>
- r.type === RELATION_MEMBER_OF &&
- r.target.kind.toLocaleLowerCase('en-US') === 'group',
+ r => r.type === RELATION_MEMBER_OF && r.targetRef.startsWith('group:'),
)
- .map(r => stringifyEntityRef(r.target)) ?? [];
+ .map(r => r.targetRef) ?? [];
return {
sub: userRef,
diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts
index abf9e4d114..b575b96c6c 100644
--- a/plugins/catalog-backend/src/catalog/types.ts
+++ b/plugins/catalog-backend/src/catalog/types.ts
@@ -40,7 +40,7 @@ export type EntityPagination = {
};
/**
- * Matches rows in the entities_search table.
+ * Matches rows in the search table.
* @public
*/
export type EntitiesSearchFilter = {
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts
index 282d2558ef..8e20655393 100644
--- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts
@@ -29,6 +29,7 @@ describe('isEntityOwner', () => {
relations: [
{
type: 'ownedBy',
+ targetRef: 'user:default/spiderman',
target: {
kind: 'user',
namespace: 'default',
@@ -52,6 +53,7 @@ describe('isEntityOwner', () => {
relations: [
{
type: 'ownedBy',
+ targetRef: 'user:default/green-goblin',
target: {
kind: 'user',
namespace: 'default',
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts
index 3176b31b87..a6dda13c29 100644
--- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-import {
- Entity,
- RELATION_OWNED_BY,
- stringifyEntityRef,
-} from '@backstage/catalog-model';
+import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model';
import { createCatalogPermissionRule } from './util';
/**
* A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
* filters for entities with a specified owner.
+ *
* @public
*/
export const isEntityOwner = createCatalogPermissionRule({
@@ -36,7 +33,7 @@ export const isEntityOwner = createCatalogPermissionRule({
return resource.relations
.filter(relation => relation.type === RELATION_OWNED_BY)
- .some(relation => claims.includes(stringifyEntityRef(relation.target)));
+ .some(relation => claims.includes(relation.targetRef));
},
toQuery: (claims: string[]) => ({
key: 'relations.ownedBy',
diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts
index 7094cfd1c2..43e208197f 100644
--- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts
+++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts
@@ -469,6 +469,62 @@ describe('DefaultEntitiesCatalog', () => {
expect(entities.length).toBe(0);
},
);
+
+ it.each(databases.eachSupportedId())(
+ 'should return both target and targetRef for entities',
+ async databaseId => {
+ const { knex } = await createDatabase(databaseId);
+ await addEntity(
+ knex,
+ {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'one' },
+ spec: {},
+ relations: [{ type: 'r', targetRef: 'x:y/z' } as any],
+ },
+ [],
+ );
+ await addEntity(
+ knex,
+ {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'two' },
+ spec: {},
+ relations: [
+ {
+ type: 'r',
+ target: { kind: 'x', namespace: 'y', name: 'z' },
+ } as any,
+ ],
+ },
+ [],
+ );
+ const catalog = new DefaultEntitiesCatalog(knex);
+
+ const { entities } = await catalog.entities();
+
+ expect(
+ entities.find(e => e.metadata.name === 'one')!.relations,
+ ).toEqual([
+ {
+ type: 'r',
+ targetRef: 'x:y/z',
+ target: { kind: 'x', namespace: 'y', name: 'z' },
+ },
+ ]);
+ expect(
+ entities.find(e => e.metadata.name === 'two')!.relations,
+ ).toEqual([
+ {
+ type: 'r',
+ targetRef: 'x:y/z',
+ target: { kind: 'x', namespace: 'y', name: 'z' },
+ },
+ ]);
+ },
+ );
});
describe('removeEntityByUid', () => {
diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts
index 1ac70bda30..3b20282d78 100644
--- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts
+++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts
@@ -14,7 +14,11 @@
* limitations under the License.
*/
-import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
+import {
+ Entity,
+ parseEntityRef,
+ stringifyEntityRef,
+} from '@backstage/catalog-model';
import { InputError, NotFoundError } from '@backstage/errors';
import { Knex } from 'knex';
import lodash from 'lodash';
@@ -194,11 +198,32 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog {
};
}
- const dbResponse = rows.map(e => JSON.parse(e.final_entity!));
+ let entities: Entity[] = rows.map(e => JSON.parse(e.final_entity!));
- const entities = dbResponse.map(e =>
- request?.fields ? request.fields(e) : e,
- );
+ if (request?.fields) {
+ entities = entities.map(e => request.fields!(e));
+ }
+
+ // TODO(freben): This is added as a compatibility guarantee, until we can be
+ // sure that all adopters have re-stitched their entities so that the new
+ // targetRef field is present on them, and that they have stopped consuming
+ // the now-removed old field
+ for (const entity of entities) {
+ if (entity.relations) {
+ for (const relation of entity.relations) {
+ if (!relation.targetRef) {
+ // This is the case where an old-form entity, not yet stitched with
+ // the updated code, was in the database
+ relation.targetRef = stringifyEntityRef(relation.target);
+ } else if (!relation.target) {
+ // This is the case where a new-form entity, stitched with the
+ // updated code, was in the database but we still want to produce
+ // the old data shape as well for compatibility reasons
+ relation.target = parseEntityRef(relation.targetRef);
+ }
+ }
+ }
+ }
return {
entities,
diff --git a/plugins/catalog-backend/src/stitching/Stitcher.test.ts b/plugins/catalog-backend/src/stitching/Stitcher.test.ts
index be57ff7083..9df4bedd60 100644
--- a/plugins/catalog-backend/src/stitching/Stitcher.test.ts
+++ b/plugins/catalog-backend/src/stitching/Stitcher.test.ts
@@ -93,6 +93,7 @@ describe('Stitcher', () => {
relations: [
{
type: 'looksAt',
+ targetRef: 'k:ns/other',
target: {
kind: 'k',
namespace: 'ns',
@@ -159,6 +160,7 @@ describe('Stitcher', () => {
relations: expect.arrayContaining([
{
type: 'looksAt',
+ targetRef: 'k:ns/other',
target: {
kind: 'k',
namespace: 'ns',
@@ -167,6 +169,7 @@ describe('Stitcher', () => {
},
{
type: 'looksAt',
+ targetRef: 'k:ns/third',
target: {
kind: 'k',
namespace: 'ns',
diff --git a/plugins/catalog-backend/src/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts
index 9ec028ed35..018e223e46 100644
--- a/plugins/catalog-backend/src/stitching/Stitcher.ts
+++ b/plugins/catalog-backend/src/stitching/Stitcher.ts
@@ -186,6 +186,7 @@ export class Stitcher {
.map(row => ({
type: row.relationType!,
target: parseEntityRef(row.relationTarget!),
+ targetRef: row.relationTarget!,
}));
if (statusItems.length) {
entity.status = {
@@ -210,7 +211,7 @@ export class Stitcher {
}
// This may throw if the entity is invalid, so we call it before
- // the final_entites write, even though we may end up not needing
+ // the final_entities write, even though we may end up not needing
// to write the search index.
const searchEntries = buildEntitySearch(entityId, entity);
diff --git a/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts
index 173538f18f..52e3392676 100644
--- a/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts
+++ b/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts
@@ -141,8 +141,16 @@ describe('buildEntitySearch', () => {
it('adds relations', () => {
const input: Entity = {
relations: [
- { type: 't1', target: { kind: 'k', namespace: 'ns', name: 'a' } },
- { type: 't2', target: { kind: 'k', namespace: 'ns', name: 'b' } },
+ {
+ type: 't1',
+ targetRef: 'k:ns/a',
+ target: { kind: 'k', namespace: 'ns', name: 'a' },
+ },
+ {
+ type: 't2',
+ targetRef: 'k:ns/b',
+ target: { kind: 'k', namespace: 'ns', name: 'b' },
+ },
],
apiVersion: 'a',
kind: 'b',
@@ -182,8 +190,16 @@ describe('buildEntitySearch', () => {
expect(() =>
buildEntitySearch('eid', {
relations: [
- { type: 'dup', target: { kind: 'k', namespace: 'ns', name: 'a' } },
- { type: 'DUP', target: { kind: 'k', namespace: 'ns', name: 'b' } },
+ {
+ type: 'dup',
+ targetRef: 'k:ns/a',
+ target: { kind: 'k', namespace: 'ns', name: 'a' },
+ },
+ {
+ type: 'DUP',
+ targetRef: 'k:ns/b',
+ target: { kind: 'k', namespace: 'ns', name: 'b' },
+ },
],
apiVersion: 'a',
kind: 'b',
diff --git a/plugins/catalog-backend/src/stitching/buildEntitySearch.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.ts
index d0506e8998..cd8a3735de 100644
--- a/plugins/catalog-backend/src/stitching/buildEntitySearch.ts
+++ b/plugins/catalog-backend/src/stitching/buildEntitySearch.ts
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-import {
- Entity,
- DEFAULT_NAMESPACE,
- stringifyEntityRef,
-} from '@backstage/catalog-model';
+import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model';
import { InputError } from '@backstage/errors';
import { DbSearchRow } from '../database/tables';
@@ -181,7 +177,7 @@ export function buildEntitySearch(
for (const relation of entity.relations ?? []) {
raw.push({
key: `relations.${relation.type}`,
- value: stringifyEntityRef(relation.target),
+ value: relation.targetRef,
});
}
diff --git a/plugins/catalog-graph/dev/index.tsx b/plugins/catalog-graph/dev/index.tsx
index 3ff9285a81..0fceb87e02 100644
--- a/plugins/catalog-graph/dev/index.tsx
+++ b/plugins/catalog-graph/dev/index.tsx
@@ -118,6 +118,11 @@ const entities = (
},
relations: relations.map(([type, k, n]) => ({
target: { kind: k, name: n, namespace: DEFAULT_NAMESPACE },
+ targetRef: stringifyEntityRef({
+ kind: k,
+ namespace: DEFAULT_NAMESPACE,
+ name: n,
+ }),
type,
})),
};
diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx
index f98aca0081..2f686f8f62 100644
--- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx
+++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx
@@ -58,6 +58,7 @@ describe('', () => {
relations: [
{
type: RELATION_PART_OF,
+ targetRef: 'b:d/e',
target: {
kind: 'b',
namespace: 'd',
@@ -76,6 +77,7 @@ describe('', () => {
relations: [
{
type: RELATION_HAS_PART,
+ targetRef: 'b:d/c',
target: {
kind: 'b',
namespace: 'd',
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx
index f16d06f809..36dc816444 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx
@@ -54,6 +54,7 @@ describe('', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -62,6 +63,7 @@ describe('', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_HAS_PART,
},
],
@@ -80,6 +82,7 @@ describe('', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_OWNED_BY,
},
{
@@ -88,6 +91,7 @@ describe('', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_OWNED_BY,
},
],
@@ -106,6 +110,7 @@ describe('', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_PART_OF,
},
{
@@ -114,6 +119,7 @@ describe('', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -122,6 +128,7 @@ describe('', () => {
name: 'c2',
namespace: 'd',
},
+ targetRef: 'b:d/c2',
type: RELATION_HAS_PART,
},
],
@@ -140,6 +147,7 @@ describe('', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_PART_OF,
},
],
@@ -225,6 +233,7 @@ describe('', () => {
name: 'some-component',
namespace: 'default',
},
+ targetRef: 'component:default/some-component',
type: RELATION_OWNER_OF,
},
],
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts
index bf6fc9ee3f..7e0cd411ce 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts
@@ -49,6 +49,7 @@ describe('useEntityRelationGraph', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -57,6 +58,7 @@ describe('useEntityRelationGraph', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_HAS_PART,
},
],
@@ -75,6 +77,7 @@ describe('useEntityRelationGraph', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_OWNED_BY,
},
{
@@ -83,6 +86,7 @@ describe('useEntityRelationGraph', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_OWNED_BY,
},
],
@@ -101,6 +105,7 @@ describe('useEntityRelationGraph', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_PART_OF,
},
{
@@ -109,6 +114,7 @@ describe('useEntityRelationGraph', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -117,6 +123,7 @@ describe('useEntityRelationGraph', () => {
name: 'c2',
namespace: 'd',
},
+ targetRef: 'b:d/c2',
type: RELATION_HAS_PART,
},
],
@@ -135,6 +142,7 @@ describe('useEntityRelationGraph', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_PART_OF,
},
],
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts
index e0d393168b..957f35dc25 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.ts
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
+import { Entity } from '@backstage/catalog-model';
import { useEffect } from 'react';
import { useEntityStore } from './useEntityStore';
@@ -64,13 +64,15 @@ export function useEntityRelationGraph({
if (
(!relations || relations.includes(rel.type)) &&
(!kinds ||
- kinds.includes(rel.target.kind.toLocaleLowerCase('en-US')))
+ kinds.some(kind =>
+ rel.targetRef.startsWith(
+ `${kind.toLocaleLowerCase('en-US')}:`,
+ ),
+ ))
) {
- const relationEntityRef = stringifyEntityRef(rel.target);
-
- if (!processedEntityRefs.has(relationEntityRef)) {
- nextDepthRefQueue.push(relationEntityRef);
- expectedEntities.add(relationEntityRef);
+ if (!processedEntityRefs.has(rel.targetRef)) {
+ nextDepthRefQueue.push(rel.targetRef);
+ expectedEntities.add(rel.targetRef);
}
}
}
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts
index 37073352d6..4715cb106a 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts
@@ -49,6 +49,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -57,6 +58,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_HAS_PART,
},
],
@@ -75,6 +77,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_OWNED_BY,
},
{
@@ -83,6 +86,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_OWNED_BY,
},
],
@@ -101,6 +105,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c',
namespace: 'd',
},
+ targetRef: 'b:d/c',
type: RELATION_PART_OF,
},
{
@@ -109,6 +114,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'a1',
namespace: 'd',
},
+ targetRef: 'k:d/a1',
type: RELATION_OWNER_OF,
},
{
@@ -117,6 +123,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c2',
namespace: 'd',
},
+ targetRef: 'b:d/c2',
type: RELATION_HAS_PART,
},
],
@@ -135,6 +142,7 @@ describe('useEntityRelationNodesAndEdges', () => {
name: 'c1',
namespace: 'd',
},
+ targetRef: 'b:d/c1',
type: RELATION_PART_OF,
},
],
diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts
index b272abc654..a1c3416d4f 100644
--- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts
+++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts
@@ -13,10 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {
- DEFAULT_NAMESPACE,
- stringifyEntityRef,
-} from '@backstage/catalog-model';
+import { DEFAULT_NAMESPACE } from '@backstage/catalog-model';
import { MouseEvent, useState } from 'react';
import useDebounce from 'react-use/lib/useDebounce';
import { RelationPairs, ALL_RELATION_PAIRS } from './relations';
@@ -100,11 +97,9 @@ export function useEntityRelationNodesAndEdges({
if (entity) {
entity?.relations?.forEach(rel => {
- const targetRef = stringifyEntityRef(rel.target);
-
// Check if the related entity should be displayed, if not, ignore
// the relation too
- if (!entities[targetRef]) {
+ if (!entities[rel.targetRef]) {
return;
}
@@ -114,12 +109,14 @@ export function useEntityRelationNodesAndEdges({
if (
kinds &&
- !kinds.includes(rel.target.kind.toLocaleLowerCase('en-US'))
+ !kinds.some(kind =>
+ rel.targetRef.startsWith(`${kind.toLocaleLowerCase('en-US')}:`),
+ )
) {
return;
}
- if (!unidirectional || !visitedNodes.has(targetRef)) {
+ if (!unidirectional || !visitedNodes.has(rel.targetRef)) {
if (mergeRelations) {
const pair = relationPairs.find(
([l, r]) => l === rel.type || r === rel.type,
@@ -127,24 +124,24 @@ export function useEntityRelationNodesAndEdges({
const [left] = pair;
edges.push({
- from: left === rel.type ? entityRef : targetRef,
- to: left === rel.type ? targetRef : entityRef,
+ from: left === rel.type ? entityRef : rel.targetRef,
+ to: left === rel.type ? rel.targetRef : entityRef,
relations: pair,
label: 'visible',
});
} else {
edges.push({
from: entityRef,
- to: targetRef,
+ to: rel.targetRef,
relations: [rel.type],
label: 'visible',
});
}
}
- if (!visitedNodes.has(targetRef)) {
- nodeQueue.push(targetRef);
- visitedNodes.add(targetRef);
+ if (!visitedNodes.has(rel.targetRef)) {
+ nodeQueue.push(rel.targetRef);
+ visitedNodes.add(rel.targetRef);
}
});
}
diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md
index 37e959f93b..15a22c98d7 100644
--- a/plugins/catalog-react/api-report.md
+++ b/plugins/catalog-react/api-report.md
@@ -266,7 +266,7 @@ export const EntityRefLink: (props: EntityRefLinkProps) => JSX.Element;
// @public
export type EntityRefLinkProps = {
- entityRef: Entity | EntityName;
+ entityRef: Entity | EntityName | string;
defaultKind?: string;
title?: string;
children?: React_2.ReactNode;
@@ -592,10 +592,7 @@ export function useOwnUser(): AsyncState;
// @public (undocumented)
export function useRelatedEntities(
entity: Entity,
- {
- type,
- kind,
- }: {
+ relationFilter: {
type?: string;
kind?: string;
},
diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx
index 14abc358db..de21bfeee3 100644
--- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx
+++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.test.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { Entity } from '@backstage/catalog-model';
+import { Entity, parseEntityRef } from '@backstage/catalog-model';
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import { MockEntityListContextProvider } from '../../testUtils/providers';
@@ -31,6 +31,7 @@ const sampleEntities: Entity[] = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/some-owner',
target: {
name: 'some-owner',
namespace: 'default',
@@ -39,6 +40,7 @@ const sampleEntities: Entity[] = [
},
{
type: 'ownedBy',
+ targetRef: 'group:default/some-owner-2',
target: {
name: 'some-owner-2',
namespace: 'default',
@@ -56,6 +58,7 @@ const sampleEntities: Entity[] = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/another-owner',
target: {
name: 'another-owner',
namespace: 'default',
@@ -73,6 +76,7 @@ const sampleEntities: Entity[] = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/some-owner',
target: {
name: 'some-owner',
namespace: 'default',
@@ -96,7 +100,7 @@ describe('', () => {
fireEvent.click(rendered.getByTestId('owner-picker-expand'));
sampleEntities
- .flatMap(e => e.relations?.map(r => r.target.name))
+ .flatMap(e => e.relations?.map(r => parseEntityRef(r.targetRef).name))
.forEach(owner => {
expect(rendered.getByText(owner as string)).toBeInTheDocument();
});
diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx
index f2c67f1087..1e01402ddf 100644
--- a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx
+++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx
@@ -18,6 +18,7 @@ import {
Entity,
EntityName,
DEFAULT_NAMESPACE,
+ parseEntityRef,
} from '@backstage/catalog-model';
import React, { forwardRef } from 'react';
import { entityRouteRef } from '../../routes';
@@ -32,7 +33,7 @@ import { Tooltip } from '@material-ui/core';
* @public
*/
export type EntityRefLinkProps = {
- entityRef: Entity | EntityName;
+ entityRef: Entity | EntityName | string;
defaultKind?: string;
title?: string;
children?: React.ReactNode;
@@ -52,7 +53,12 @@ export const EntityRefLink = forwardRef(
let namespace;
let name;
- if ('metadata' in entityRef) {
+ if (typeof entityRef === 'string') {
+ const parsed = parseEntityRef(entityRef);
+ kind = parsed.kind;
+ namespace = parsed.namespace;
+ name = parsed.name;
+ } else if ('metadata' in entityRef) {
kind = entityRef.kind;
namespace = entityRef.metadata.namespace;
name = entityRef.metadata.name;
@@ -63,15 +69,13 @@ export const EntityRefLink = forwardRef(
}
kind = kind.toLocaleLowerCase('en-US');
+ namespace = namespace?.toLocaleLowerCase('en-US') ?? DEFAULT_NAMESPACE;
- const routeParams = {
- kind,
- namespace: namespace?.toLocaleLowerCase('en-US') ?? DEFAULT_NAMESPACE,
- name,
- };
- const formattedEntityRefTitle = formatEntityRefTitle(entityRef, {
- defaultKind,
- });
+ const routeParams = { kind, namespace, name };
+ const formattedEntityRefTitle = formatEntityRefTitle(
+ { kind, namespace, name },
+ { defaultKind },
+ );
const link = (
diff --git a/plugins/catalog-react/src/components/EntityTable/presets.test.tsx b/plugins/catalog-react/src/components/EntityTable/presets.test.tsx
index a509b67477..f2fcd016f0 100644
--- a/plugins/catalog-react/src/components/EntityTable/presets.test.tsx
+++ b/plugins/catalog-react/src/components/EntityTable/presets.test.tsx
@@ -44,17 +44,19 @@ describe('systemEntityColumns', () => {
relations: [
{
type: RELATION_PART_OF,
+ targetRef: 'domain:my-namespace/my-domain',
target: {
- kind: 'Domain',
+ kind: 'domain',
name: 'my-domain',
namespace: 'my-namespace',
},
},
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/test',
target: {
- kind: 'Group',
- name: 'Test',
+ kind: 'group',
+ name: 'test',
namespace: 'default',
},
},
@@ -79,7 +81,7 @@ describe('systemEntityColumns', () => {
await waitFor(() => {
expect(getByText('my-namespace/my-system')).toBeInTheDocument();
expect(getByText('my-namespace/my-domain')).toBeInTheDocument();
- expect(getByText('Test')).toBeInTheDocument();
+ expect(getByText('test')).toBeInTheDocument();
expect(getByText(/Some/)).toBeInTheDocument();
});
});
@@ -104,17 +106,19 @@ describe('componentEntityColumns', () => {
relations: [
{
type: RELATION_PART_OF,
+ targetRef: 'system:my-namespace/my-system',
target: {
- kind: 'System',
+ kind: 'system',
name: 'my-system',
namespace: 'my-namespace',
},
},
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/test',
target: {
- kind: 'Group',
- name: 'Test',
+ kind: 'group',
+ name: 'test',
namespace: 'default',
},
},
@@ -139,7 +143,7 @@ describe('componentEntityColumns', () => {
await waitFor(() => {
expect(getByText('my-namespace/my-component')).toBeInTheDocument();
expect(getByText('my-namespace/my-system')).toBeInTheDocument();
- expect(getByText('Test')).toBeInTheDocument();
+ expect(getByText('test')).toBeInTheDocument();
expect(getByText('production')).toBeInTheDocument();
expect(getByText('service')).toBeInTheDocument();
expect(getByText(/Some/)).toBeInTheDocument();
diff --git a/plugins/catalog-react/src/components/EntityTable/presets.tsx b/plugins/catalog-react/src/components/EntityTable/presets.tsx
index 971ecfed20..6e4ddb2081 100644
--- a/plugins/catalog-react/src/components/EntityTable/presets.tsx
+++ b/plugins/catalog-react/src/components/EntityTable/presets.tsx
@@ -15,9 +15,8 @@
*/
import { ComponentEntity, SystemEntity } from '@backstage/catalog-model';
-import { columnFactories } from './columns';
-
import { TableColumn } from '@backstage/core-components';
+import { columnFactories } from './columns';
export const systemEntityColumns: TableColumn[] = [
columnFactories.createEntityRefColumn({ defaultKind: 'system' }),
diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/EntityKindIcon.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/EntityKindIcon.tsx
index c2fc49aa0c..4bb41c91c1 100644
--- a/plugins/catalog-react/src/components/InspectEntityDialog/components/EntityKindIcon.tsx
+++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/EntityKindIcon.tsx
@@ -14,23 +14,54 @@
* limitations under the License.
*/
+import { parseEntityRef } from '@backstage/catalog-model';
import { useApp } from '@backstage/core-plugin-api';
import WorkIcon from '@material-ui/icons/Work';
import React from 'react';
+const DEFAULT_ICON = WorkIcon;
+
+function getKind(
+ kind: string | undefined,
+ entityRef: string | undefined,
+): string | undefined {
+ if (kind) {
+ return kind.toLocaleLowerCase('en-US');
+ }
+
+ if (entityRef) {
+ try {
+ return parseEntityRef(entityRef).kind.toLocaleLowerCase('en-US');
+ } catch {
+ return undefined;
+ }
+ }
+
+ return undefined;
+}
+
+function useIcon(kind: string | undefined, entityRef: string | undefined) {
+ const app = useApp();
+
+ const actualKind = getKind(kind, entityRef);
+ if (!actualKind) {
+ return DEFAULT_ICON;
+ }
+
+ const icon = app.getSystemIcon(`kind:${actualKind}`);
+ return icon || DEFAULT_ICON;
+}
+
export function EntityKindIcon(props: {
- kind: string;
+ kind?: string;
+ entityRef?: string;
x?: number;
y?: number;
width?: number;
height?: number;
className?: string;
}) {
- const app = useApp();
-
- const { kind, ...otherProps } = props;
- const Icon =
- app.getSystemIcon(`kind:${kind.toLocaleLowerCase('en-US')}`) ?? WorkIcon;
-
+ const { kind, entityRef, ...otherProps } = props;
+ const Icon = useIcon(kind, entityRef);
return ;
}
diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx
index dbb7399481..a4e8523beb 100644
--- a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx
+++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { AlphaEntity, stringifyEntityRef } from '@backstage/catalog-model';
+import { AlphaEntity } from '@backstage/catalog-model';
import {
Box,
DialogContentText,
@@ -56,7 +56,7 @@ export function OverviewPage(props: { entity: AlphaEntity }) {
} = props.entity;
const groupedRelations = groupBy(
- sortBy(relations, r => stringifyEntityRef(r.target)),
+ sortBy(relations, r => r.targetRef),
'type',
);
@@ -143,12 +143,14 @@ export function OverviewPage(props: { entity: AlphaEntity }) {
{type}}>
{groupRelations.map(group => (
-
+
-
+
}
+ primary={
+
+ }
/>
))}
diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx
index 630a995bbe..316a0f2c06 100644
--- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx
+++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx
@@ -103,6 +103,7 @@ const backendEntities: Entity[] = [
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/testuser',
target: { kind: 'User', namespace: 'default', name: 'testUser' },
},
],
@@ -136,6 +137,7 @@ const backendEntities: Entity[] = [
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/testuser',
target: { kind: 'User', namespace: 'default', name: 'testUser' },
},
],
diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
index c0a90fa834..c8ca29b07f 100644
--- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
+++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
@@ -45,6 +45,7 @@ const entities: Entity[] = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'user:default/guest',
target: {
name: 'guest',
namespace: 'default',
diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx
index 7f838163a2..17c35afecc 100644
--- a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx
+++ b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx
@@ -70,10 +70,12 @@ describe('useEntityOwnership', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/user1',
target: { kind: 'User', namespace: 'default', name: 'user1' },
},
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/group1',
target: { kind: 'Group', namespace: 'default', name: 'group1' },
},
],
@@ -92,6 +94,7 @@ describe('useEntityOwnership', () => {
relations: [
{
type: RELATION_MEMBER_OF,
+ targetRef: 'group:default/group1',
target: { kind: 'Group', namespace: 'default', name: 'group1' },
},
],
diff --git a/plugins/catalog-react/src/hooks/useRelatedEntities.ts b/plugins/catalog-react/src/hooks/useRelatedEntities.ts
index 56dfbe6403..4cf5690ac3 100644
--- a/plugins/catalog-react/src/hooks/useRelatedEntities.ts
+++ b/plugins/catalog-react/src/hooks/useRelatedEntities.ts
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Entity, EntityRelation } from '@backstage/catalog-model';
+import { Entity, parseEntityRef } from '@backstage/catalog-model';
import { useApi } from '@backstage/core-plugin-api';
import { chunk, groupBy } from 'lodash';
import useAsync from 'react-use/lib/useAsync';
@@ -24,28 +24,28 @@ const BATCH_SIZE = 20;
/** @public */
export function useRelatedEntities(
entity: Entity,
- { type, kind }: { type?: string; kind?: string },
+ relationFilter: { type?: string; kind?: string },
): {
entities: Entity[] | undefined;
loading: boolean;
error: Error | undefined;
} {
+ const filterByTypeLower = relationFilter?.type?.toLocaleLowerCase('en-US');
+ const filterByKindLower = relationFilter?.kind?.toLocaleLowerCase('en-US');
+
const catalogApi = useApi(catalogApiRef);
const {
loading,
value: entities,
error,
} = useAsync(async () => {
- const relations =
- entity.relations &&
- entity.relations.filter(
+ const relations = entity.relations
+ ?.map(r => ({ type: r.type, target: parseEntityRef(r.targetRef) }))
+ .filter(
r =>
- (!type ||
- r.type.toLocaleLowerCase('en-US') ===
- type.toLocaleLowerCase('en-US')) &&
- (!kind ||
- r.target.kind.toLocaleLowerCase('en-US') ===
- kind.toLocaleLowerCase('en-US')),
+ (!filterByTypeLower ||
+ r.type.toLocaleLowerCase('en-US') === filterByTypeLower) &&
+ (!filterByKindLower || r.target.kind === filterByKindLower),
);
if (!relations) {
@@ -57,7 +57,7 @@ export function useRelatedEntities(
// `filter=kind=component,namespace=default,name=example1&filter=kind=component,namespace=default,name=example2`
// with grouping, we can generate a query a string like
// `filter=kind=component,namespace=default,name=example1,example2`
- const relationsByKindAndNamespace: EntityRelation[][] = Object.values(
+ const relationsByKindAndNamespace = Object.values(
groupBy(relations, ({ target }) => {
return `${target.kind}:${target.namespace}`.toLocaleLowerCase('en-US');
}),
@@ -96,7 +96,7 @@ export function useRelatedEntities(
);
return results.flatMap(r => r.items);
- }, [entity, type]);
+ }, [entity, filterByTypeLower, filterByKindLower]);
return {
entities,
diff --git a/plugins/catalog-react/src/utils/getEntityRelations.test.ts b/plugins/catalog-react/src/utils/getEntityRelations.test.ts
index 22c695043f..ea0ba59399 100644
--- a/plugins/catalog-react/src/utils/getEntityRelations.test.ts
+++ b/plugins/catalog-react/src/utils/getEntityRelations.test.ts
@@ -31,17 +31,19 @@ describe('getEntityRelations', () => {
relations: [
{
type: RELATION_MEMBER_OF,
- target: { kind: 'group', name: 'member' },
+ targetRef: 'group:default/member',
+ target: { kind: 'group', namespace: 'default', name: 'member' },
},
{
type: RELATION_CHILD_OF,
- target: { kind: 'group', name: 'child' },
+ targetRef: 'group:default/child',
+ target: { kind: 'group', namespace: 'default', name: 'child' },
},
],
} as Entity;
expect(getEntityRelations(entity, RELATION_MEMBER_OF)).toEqual([
- { kind: 'group', name: 'member' },
+ { kind: 'group', namespace: 'default', name: 'member' },
]);
});
@@ -50,17 +52,19 @@ describe('getEntityRelations', () => {
relations: [
{
type: RELATION_MEMBER_OF,
- target: { kind: 'group', name: 'member' },
+ targetRef: 'group:default/member',
+ target: { kind: 'group', namespace: 'default', name: 'member' },
},
{
type: RELATION_MEMBER_OF,
- target: { kind: 'user', name: 'child' },
+ targetRef: 'user:default/child',
+ target: { kind: 'user', namespace: 'default', name: 'child' },
},
],
} as Entity;
expect(
getEntityRelations(entity, RELATION_MEMBER_OF, { kind: 'Group' }),
- ).toEqual([{ kind: 'group', name: 'member' }]);
+ ).toEqual([{ kind: 'group', namespace: 'default', name: 'member' }]);
});
});
diff --git a/plugins/catalog-react/src/utils/getEntityRelations.ts b/plugins/catalog-react/src/utils/getEntityRelations.ts
index 25666a9960..45cbc6967f 100644
--- a/plugins/catalog-react/src/utils/getEntityRelations.ts
+++ b/plugins/catalog-react/src/utils/getEntityRelations.ts
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-import { Entity, EntityName } from '@backstage/catalog-model';
+import { Entity, EntityName, parseEntityRef } from '@backstage/catalog-model';
+// TODO(freben): This should be returning entity refs instead
/**
* Get the related entity references.
+ *
* @public
*/
export function getEntityRelations(
@@ -28,10 +30,10 @@ export function getEntityRelations(
let entityNames =
entity?.relations
?.filter(r => r.type === relationType)
- ?.map(r => r.target) || [];
+ .map(r => parseEntityRef(r.targetRef)) || [];
if (filter?.kind) {
- entityNames = entityNames?.filter(
+ entityNames = entityNames.filter(
e =>
e.kind.toLocaleLowerCase('en-US') ===
filter.kind.toLocaleLowerCase('en-US'),
diff --git a/plugins/catalog-react/src/utils/isOwnerOf.test.ts b/plugins/catalog-react/src/utils/isOwnerOf.test.ts
index 2cd6cfafa3..d3053646d8 100644
--- a/plugins/catalog-react/src/utils/isOwnerOf.test.ts
+++ b/plugins/catalog-react/src/utils/isOwnerOf.test.ts
@@ -31,6 +31,7 @@ describe('isOwnerOf', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/user',
target: { kind: 'user', namespace: 'default', name: 'user' },
},
],
@@ -46,6 +47,7 @@ describe('isOwnerOf', () => {
relations: [
{
type: RELATION_MEMBER_OF,
+ targetRef: 'group:default/group',
target: { kind: 'group', namespace: 'default', name: 'group' },
},
],
@@ -54,6 +56,7 @@ describe('isOwnerOf', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/group',
target: { kind: 'group', namespace: 'default', name: 'group' },
},
],
diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx
index 74c6490534..9a878e3b60 100644
--- a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx
+++ b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx
@@ -63,6 +63,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
diff --git a/plugins/catalog/src/components/AboutCard/AboutContent.test.tsx b/plugins/catalog/src/components/AboutCard/AboutContent.test.tsx
index 860ef2c532..cf9673eeeb 100644
--- a/plugins/catalog/src/components/AboutCard/AboutContent.test.tsx
+++ b/plugins/catalog/src/components/AboutCard/AboutContent.test.tsx
@@ -47,6 +47,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/o',
target: {
kind: 'user',
name: 'o',
@@ -55,6 +56,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'system:default/s',
target: {
kind: 'system',
name: 's',
@@ -63,6 +65,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'domain:default/d',
target: {
kind: 'domain',
name: 'd',
@@ -152,6 +155,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
@@ -160,6 +164,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'system:default/system',
target: {
kind: 'system',
name: 'system',
@@ -257,6 +262,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
@@ -265,6 +271,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'system:default/system',
target: {
kind: 'system',
name: 'system',
@@ -273,6 +280,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'component:default/parent-software',
target: {
kind: 'component',
name: 'parent-software',
@@ -369,6 +377,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
@@ -528,6 +537,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
@@ -536,6 +546,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'system:default/system',
target: {
kind: 'system',
name: 'system',
@@ -625,6 +636,7 @@ describe('', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'user:default/guest',
target: {
kind: 'user',
name: 'guest',
@@ -633,6 +645,7 @@ describe('', () => {
},
{
type: RELATION_PART_OF,
+ targetRef: 'domain:default/domain',
target: {
kind: 'domain',
name: 'domain',
diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx
index 34aee0bbf3..dcf819f976 100644
--- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx
+++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx
@@ -73,7 +73,8 @@ describe('DefaultCatalogPage', () => {
relations: [
{
type: RELATION_OWNED_BY,
- target: { kind: 'Group', name: 'tools', namespace: 'default' },
+ targetRef: 'group:default/tools',
+ target: { kind: 'group', name: 'tools', namespace: 'default' },
},
],
},
@@ -90,8 +91,9 @@ describe('DefaultCatalogPage', () => {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/not-tools',
target: {
- kind: 'Group',
+ kind: 'group',
name: 'not-tools',
namespace: 'default',
},
@@ -110,6 +112,7 @@ describe('DefaultCatalogPage', () => {
relations: [
{
type: RELATION_MEMBER_OF,
+ targetRef: 'group:default/tools',
target: { namespace: 'default', kind: 'Group', name: 'tools' },
},
],
diff --git a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx
index e43104b67d..05d836870f 100644
--- a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx
+++ b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.test.tsx
@@ -81,10 +81,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_DEPENDENCY_OF,
},
],
diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx
index b654136d18..b7ef594522 100644
--- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx
+++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.test.tsx
@@ -81,10 +81,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_DEPENDS_ON,
},
],
diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx
index 40685705aa..b8d2801e48 100644
--- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx
+++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.test.tsx
@@ -81,10 +81,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Resource',
+ kind: 'resource',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'resource:my-namespace/target-name',
type: RELATION_DEPENDS_ON,
},
],
diff --git a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx
index 45f7561d6e..fbb474825f 100644
--- a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx
+++ b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.test.tsx
@@ -81,10 +81,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_HAS_PART,
},
],
diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx
index a01922d988..c75273e484 100644
--- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx
+++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.test.tsx
@@ -76,10 +76,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Resource',
+ kind: 'resource',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'resource:my-namespace/target-name',
type: RELATION_HAS_PART,
},
],
diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx
index e517bd38ae..e021fea2f3 100644
--- a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx
+++ b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.test.tsx
@@ -81,10 +81,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Component',
+ kind: 'component',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'component:my-namespace/target-name',
type: RELATION_HAS_PART,
},
],
diff --git a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx
index 050550101f..6a2e2a0b7f 100644
--- a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx
+++ b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.test.tsx
@@ -79,10 +79,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'System',
+ kind: 'system',
namespace: 'my-namespace',
name: 'target-name',
},
+ targetRef: 'system:my-namespace/target-name',
type: RELATION_HAS_PART,
},
],
diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx
index e0ec48fbed..eb6b71c47e 100644
--- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx
+++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.test.tsx
@@ -103,10 +103,11 @@ describe('', () => {
relations: [
{
target: {
- kind: 'Domain',
+ kind: 'domain',
namespace: 'namespace',
name: 'domain',
},
+ targetRef: 'domain:namespace/domain',
type: RELATION_PART_OF,
},
],
@@ -166,6 +167,7 @@ describe('', () => {
namespace: 'namespace',
name: 'alongdomainthatshouldgettruncated',
},
+ targetRef: 'domain:namespace/alongdomainthatshouldgettruncated',
type: RELATION_PART_OF,
},
],
diff --git a/plugins/fossa/dev/index.tsx b/plugins/fossa/dev/index.tsx
index 018d3e3acb..1ce9ec58b2 100644
--- a/plugins/fossa/dev/index.tsx
+++ b/plugins/fossa/dev/index.tsx
@@ -42,7 +42,8 @@ const entity = (name?: string) =>
relations: [
{
type: RELATION_OWNED_BY,
- target: { kind: 'Group', namespace: 'default', name },
+ targetRef: `group:default/${name}`,
+ target: { kind: 'group', namespace: 'default', name },
},
],
} as Entity);
diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx
index dc90a46fdf..cdf6240fc0 100644
--- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx
+++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx
@@ -28,6 +28,7 @@ export default {
const dummyDepartment = {
type: 'childOf',
+ targetRef: 'group:default/department-a',
target: {
namespace: 'default',
kind: 'group',
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx
index b6b549d934..b0a7ed8c70 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.stories.tsx
@@ -54,6 +54,7 @@ const makeUser = ({
relations: [
{
type: 'memberOf',
+ targetRef: 'group:default/team-a',
target: {
namespace: 'default',
kind: 'group',
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
index 99be8571e0..cffe3e0228 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
@@ -59,6 +59,7 @@ describe('MemberTab Test', () => {
relations: [
{
type: 'memberOf',
+ targetRef: 'group:default/team-d',
target: {
kind: 'group',
name: 'team-d',
diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx
index a0536e1a74..c07815f39e 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx
+++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.stories.tsx
@@ -69,9 +69,10 @@ const makeComponent = ({ type, name }: { type: string; name: string }) => ({
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/team-a',
target: {
namespace: 'default',
- kind: 'Group',
+ kind: 'group',
name: 'team-a',
},
},
diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
index 2030f4c100..3fc770e6b5 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
+++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
@@ -43,10 +43,11 @@ const items = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/my-team',
target: {
name: 'my-team',
namespace: 'default',
- kind: 'Group',
+ kind: 'group',
},
},
],
@@ -62,10 +63,11 @@ const items = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/my-team',
target: {
name: 'my-team',
namespace: 'default',
- kind: 'Group',
+ kind: 'group',
},
},
],
@@ -82,10 +84,11 @@ const items = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/my-team',
target: {
name: 'my-team',
namespace: 'default',
- kind: 'Group',
+ kind: 'group',
},
},
],
@@ -99,10 +102,11 @@ const items = [
relations: [
{
type: 'ownedBy',
+ targetRef: 'group:default/my-team',
target: {
name: 'my-team',
namespace: 'default',
- kind: 'Group',
+ kind: 'group',
},
},
],
@@ -135,9 +139,10 @@ describe('OwnershipCard', () => {
relations: [
{
type: 'memberOf',
+ targetRef: 'group:default/examplegroup',
target: {
kind: 'group',
- name: 'ExampleGroup',
+ name: 'examplegroup',
namespace: 'default',
},
},
@@ -260,8 +265,9 @@ describe('OwnershipCard', () => {
relations: [
{
type: 'memberOf',
+ targetRef: 'group:default/my-team',
target: {
- kind: 'Group',
+ kind: 'group',
name: 'my-team',
namespace: 'default',
},
diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.stories.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.stories.tsx
index 0cb3987c77..0b2d2790a0 100644
--- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.stories.tsx
+++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.stories.tsx
@@ -28,6 +28,7 @@ export default {
const dummyGroup = {
type: 'memberOf',
+ targetRef: 'group:default/team-a',
target: {
namespace: 'default',
kind: 'group',
diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx
index cf84381830..3e5e595eef 100644
--- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx
+++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx
@@ -42,6 +42,7 @@ describe('UserSummary Test', () => {
relations: [
{
type: 'memberOf',
+ targetRef: 'group:default/examplegroup',
target: {
kind: 'group',
name: 'ExampleGroup',
@@ -70,9 +71,9 @@ describe('UserSummary Test', () => {
'src',
'https://example.com/staff/calum.jpeg',
);
- expect(rendered.getByText('ExampleGroup')).toHaveAttribute(
+ expect(rendered.getByText('examplegroup')).toHaveAttribute(
'href',
- '/catalog/default/group/ExampleGroup',
+ '/catalog/default/group/examplegroup',
);
expect(rendered.getByText('Super awesome human')).toBeInTheDocument();
});
diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts
index a51ce0ab83..14d0728cf6 100644
--- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts
+++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts
@@ -57,6 +57,7 @@ const defaultEntityListResponse: GetEntitiesResponse = {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/my-team',
target: { name: 'team-a', kind: 'group', namespace: 'default' },
},
],
diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts
index 2108379f06..374bda2569 100644
--- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts
+++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts
@@ -57,6 +57,7 @@ const defaultEntityListResponse: GetEntitiesResponse = {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/team-a',
target: { name: 'team-a', kind: 'group', namespace: 'default' },
},
],
diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts
index a3604129b7..b4fa8ba67c 100644
--- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts
+++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts
@@ -57,6 +57,7 @@ const defaultEntityListResponse: GetEntitiesResponse = {
relations: [
{
type: RELATION_OWNED_BY,
+ targetRef: 'group:default/team-a',
target: { name: 'team-a', kind: 'group', namespace: 'default' },
},
],
diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts
index 86b70379ad..2c8786d92e 100644
--- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts
+++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts
@@ -20,6 +20,7 @@ import {
} from '@backstage/backend-common';
import {
Entity,
+ parseEntityRef,
RELATION_OWNED_BY,
stringifyEntityRef,
} from '@backstage/catalog-model';
@@ -154,9 +155,7 @@ export class DefaultTechDocsCollator implements DocumentCollator {
entityTitle: entity.metadata.title,
componentType: entity.spec?.type?.toString() || 'other',
lifecycle: (entity.spec?.lifecycle as string) || '',
- owner:
- entity.relations?.find(r => r.type === RELATION_OWNED_BY)
- ?.target?.name || '',
+ owner: getSimpleEntityOwnerString(entity),
authorization: {
resourceRef: stringifyEntityRef(entity),
},
@@ -202,3 +201,14 @@ export class DefaultTechDocsCollator implements DocumentCollator {
}, {} as EntityInfo);
}
}
+
+function getSimpleEntityOwnerString(entity: Entity): string {
+ if (entity.relations) {
+ const owner = entity.relations.find(r => r.type === RELATION_OWNED_BY);
+ if (owner) {
+ const { name } = parseEntityRef(owner.targetRef);
+ return name;
+ }
+ }
+ return '';
+}
diff --git a/plugins/techdocs/src/home/components/DocsTable.test.tsx b/plugins/techdocs/src/home/components/DocsTable.test.tsx
index 4564725db6..9586cfb2ef 100644
--- a/plugins/techdocs/src/home/components/DocsTable.test.tsx
+++ b/plugins/techdocs/src/home/components/DocsTable.test.tsx
@@ -66,6 +66,7 @@ describe('DocsTable test', () => {
namespace: 'default',
name: 'owned',
},
+ targetRef: 'user:default/owned',
type: 'ownedBy',
},
],
@@ -86,6 +87,7 @@ describe('DocsTable test', () => {
namespace: 'default',
name: 'not-owned',
},
+ targetRef: 'user:default/not-owned',
type: 'ownedBy',
},
],
@@ -137,6 +139,7 @@ describe('DocsTable test', () => {
namespace: 'default',
name: 'owned',
},
+ targetRef: 'user:default/owned',
type: 'ownedBy',
},
],