Skip to content

Commit

Permalink
Merge pull request #17747 from Andy2003/feature/improve-catalog-fetch
Browse files Browse the repository at this point in the history
Add ability to use `defaultNamespace` and `defaultKind` for scaffolder action `catalog:fetch`
  • Loading branch information
benjdlambert authored May 16, 2023
2 parents 4558511 + a73b3c0 commit 93daeb8
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 131 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-students-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': minor
---

Add ability to use `defaultNamespace` and `defaultKind` for scaffolder action `catalog:fetch`
2 changes: 2 additions & 0 deletions plugins/scaffolder-backend/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export function createFetchCatalogEntityAction(options: {
entityRef?: string | undefined;
entityRefs?: string[] | undefined;
optional?: boolean | undefined;
defaultKind?: string | undefined;
defaultNamespace?: string | undefined;
},
{
entity?: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,179 +46,249 @@ describe('catalog:fetch', () => {
jest.resetAllMocks();
});

it('should return entity from catalog', async () => {
getEntityByRef.mockReturnValueOnce({
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity);

await action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
},
});
describe('fetch single entity', () => {
it('should return entity from catalog', async () => {
getEntityByRef.mockReturnValueOnce({
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity);

await action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
},
});

expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
});
expect(mockContext.output).toHaveBeenCalledWith('entity', {
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
});
});
expect(mockContext.output).toHaveBeenCalledWith('entity', {
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',

it('should throw error if entity fetch fails from catalog and optional is false', async () => {
getEntityByRef.mockImplementationOnce(() => {
throw new Error('Not found');
});

await expect(
action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
},
}),
).rejects.toThrow('Not found');

expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
});
expect(mockContext.output).not.toHaveBeenCalled();
});
});

it('should throw error if entity fetch fails from catalog and optional is false', async () => {
getEntityByRef.mockImplementationOnce(() => {
throw new Error('Not found');
it('should throw error if entity not in catalog and optional is false', async () => {
getEntityByRef.mockReturnValueOnce(null);

await expect(
action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
},
}),
).rejects.toThrow('Entity component:default/test not found');

expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
});
expect(mockContext.output).not.toHaveBeenCalled();
});

await expect(
action.handler({
it('should use defaultKind and defaultNamespace if provided', async () => {
const entity: Entity = {
metadata: {
namespace: 'ns',
name: 'test',
},
kind: 'Group',
} as Entity;
getEntityByRef.mockReturnValueOnce(entity);

await action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
entityRef: 'test',
defaultKind: 'Group',
defaultNamespace: 'ns',
},
}),
).rejects.toThrow('Not found');
});

expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
expect(getEntityByRef).toHaveBeenCalledWith('group:ns/test', {
token: 'secret',
});
expect(mockContext.output).toHaveBeenCalledWith('entity', entity);
});
expect(mockContext.output).not.toHaveBeenCalled();
});

it('should throw error if entity not in catalog and optional is false', async () => {
getEntityByRef.mockReturnValueOnce(null);
describe('fetch multiple entities', () => {
it('should return entities from catalog', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
],
});

await expect(
action.handler({
await action.handler({
...mockContext,
input: {
entityRef: 'component:default/test',
entityRefs: ['component:default/test'],
},
}),
).rejects.toThrow('Entity component:default/test not found');
});

expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', {
token: 'secret',
});
expect(mockContext.output).not.toHaveBeenCalled();
});

it('should return entities from catalog', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test'] },
{
token: 'secret',
},
);
expect(mockContext.output).toHaveBeenCalledWith('entities', [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
],
},
]);
});

await action.handler({
...mockContext,
input: {
entityRefs: ['component:default/test'],
},
});
it('should throw error if undefined is returned for some entity', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
undefined,
],
});

expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test'] },
{
token: 'secret',
},
);
expect(mockContext.output).toHaveBeenCalledWith('entities', [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
},
]);
});
await expect(
action.handler({
...mockContext,
input: {
entityRefs: ['component:default/test', 'component:default/test2'],
optional: false,
},
}),
).rejects.toThrow('Entity component:default/test2 not found');

it('should throw error if undefined is returned for some entity', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test', 'component:default/test2'] },
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
undefined,
],
token: 'secret',
},
);
expect(mockContext.output).not.toHaveBeenCalled();
});

await expect(
action.handler({
it('should return null in case some of the entities not found and optional is true', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
undefined,
],
});

await action.handler({
...mockContext,
input: {
entityRefs: ['component:default/test', 'component:default/test2'],
optional: false,
optional: true,
},
}),
).rejects.toThrow('Entity component:default/test2 not found');

expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test', 'component:default/test2'] },
{
token: 'secret',
},
);
expect(mockContext.output).not.toHaveBeenCalled();
});
});

it('should return null in case some of the entities not found and optional is true', async () => {
getEntitiesByRefs.mockReturnValueOnce({
items: [
expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test', 'component:default/test2'] },
{
token: 'secret',
},
);
expect(mockContext.output).toHaveBeenCalledWith('entities', [
{
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
} as Entity,
undefined,
],
});

await action.handler({
...mockContext,
input: {
entityRefs: ['component:default/test', 'component:default/test2'],
optional: true,
},
},
null,
]);
});

expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['component:default/test', 'component:default/test2'] },
{
token: 'secret',
},
);
expect(mockContext.output).toHaveBeenCalledWith('entities', [
{
it('should use defaultKind and defaultNamespace if provided', async () => {
const entity1: Entity = {
metadata: {
namespace: 'ns',
name: 'test',
},
kind: 'Group',
} as Entity;
const entity2: Entity = {
metadata: {
namespace: 'default',
name: 'test',
},
kind: 'Component',
},
null,
]);
kind: 'User',
} as Entity;
getEntitiesByRefs.mockReturnValueOnce({
items: [entity1, entity2],
});

await action.handler({
...mockContext,
input: {
entityRefs: ['test', 'user:default/test'],
defaultKind: 'Group',
defaultNamespace: 'ns',
},
});

expect(getEntitiesByRefs).toHaveBeenCalledWith(
{ entityRefs: ['group:ns/test', 'user:default/test'] },
{
token: 'secret',
},
);

expect(mockContext.output).toHaveBeenCalledWith('entities', [
entity1,
entity2,
]);
});
});
});
Loading

0 comments on commit 93daeb8

Please sign in to comment.