Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Integrations Backend to abstract IO #947

Merged
merged 30 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c5cea8d
Stub catalog reader interface
Swiddis Aug 17, 2023
77ad89b
Add basic catalog functionality to new catalog reader
Swiddis Aug 17, 2023
676591d
Refactor validation logic with a deeper interface
Swiddis Aug 21, 2023
12c4bcf
Refactor validation logic with a deeper interface
Swiddis Aug 21, 2023
412480e
Remove redundant test.
Swiddis Aug 21, 2023
6d2bad1
Add tests for new validators
Swiddis Aug 21, 2023
c3dd111
Merge branch 'better-validation' into prototype-network-catalog
Swiddis Aug 21, 2023
55d6490
Make better failure mode for invalid objects
Swiddis Aug 21, 2023
c62d28b
Merge branch 'main' into prototype-network-catalog
Swiddis Aug 22, 2023
ba56fb8
Generalize Result type
Swiddis Aug 22, 2023
cb29208
Convert backend to use catalog reader (unstable)
Swiddis Aug 22, 2023
c9de36e
Repair tests for integrations class (unstable)
Swiddis Aug 22, 2023
37c7980
Refactor repository for new integration interface
Swiddis Aug 22, 2023
b331090
Fix outer repository and backend tests
Swiddis Aug 23, 2023
4b29e17
Add tests for sample data
Swiddis Aug 23, 2023
b35dfa8
Merge remote-tracking branch 'upstream/main' into prototype-network-c…
Swiddis Aug 23, 2023
1bef29e
Add CatalogReader JavaDocs
Swiddis Aug 23, 2023
a18cf47
Repair integrations builder
Swiddis Aug 23, 2023
047b14a
Remove extra commented test
Swiddis Aug 23, 2023
e65fe8b
Remove unnecessary log statement
Swiddis Aug 23, 2023
00ddb5b
Repair getSchemas behavior to return correct type
Swiddis Aug 23, 2023
8af7f4a
Add tests for getSchemas
Swiddis Aug 23, 2023
a31963d
Add tests for asset and sample data backend methods
Swiddis Aug 23, 2023
af78c27
Merge branch 'main' into prototype-network-catalog
Swiddis Sep 6, 2023
bfa9d1a
Merge branch 'main' into prototype-network-catalog
Swiddis Sep 11, 2023
339fb09
Refactor major class names
Swiddis Sep 13, 2023
fae680f
(WIP) begin refactoring functionality into adaptor
Swiddis Sep 13, 2023
3096626
Finish migrating functionality to data adaptor
Swiddis Sep 13, 2023
5498724
Rename integration types for more clarity
Swiddis Sep 14, 2023
ee33a51
Merge branch 'main' into prototype-network-catalog
Swiddis Sep 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 38 additions & 31 deletions server/adaptors/integrations/__test__/builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { SavedObjectsClientContract } from '../../../../../../src/core/server';
import { IntegrationInstanceBuilder } from '../integrations_builder';
import { Integration } from '../repository/integration';
import { IntegrationReader } from '../repository/integration';

const mockSavedObjectsClient: SavedObjectsClientContract = ({
bulkCreate: jest.fn(),
Expand All @@ -16,7 +16,7 @@ const mockSavedObjectsClient: SavedObjectsClientContract = ({
update: jest.fn(),
} as unknown) as SavedObjectsClientContract;

const sampleIntegration: Integration = ({
const sampleIntegration: IntegrationReader = ({
deepCheck: jest.fn().mockResolvedValue(true),
getAssets: jest.fn().mockResolvedValue({
savedObjects: [
Expand All @@ -34,7 +34,7 @@ const sampleIntegration: Integration = ({
name: 'integration-template',
type: 'integration-type',
}),
} as unknown) as Integration;
} as unknown) as IntegrationReader;

describe('IntegrationInstanceBuilder', () => {
let builder: IntegrationInstanceBuilder;
Expand Down Expand Up @@ -93,13 +93,23 @@ describe('IntegrationInstanceBuilder', () => {
],
};

// Mock the implementation of the methods in the Integration class
sampleIntegration.deepCheck = jest.fn().mockResolvedValue(true);
sampleIntegration.getAssets = jest.fn().mockResolvedValue({ savedObjects: remappedAssets });
sampleIntegration.getConfig = jest.fn().mockResolvedValue({
const mockTemplate: Partial<IntegrationConfig> = {
name: 'integration-template',
type: 'integration-type',
});
assets: {
savedObjects: {
name: 'assets',
version: '1.0.0',
},
},
};

// Mock the implementation of the methods in the Integration class
sampleIntegration.deepCheck = jest.fn().mockResolvedValue({ ok: true, value: mockTemplate });
sampleIntegration.getAssets = jest
.fn()
.mockResolvedValue({ ok: true, value: { savedObjects: remappedAssets } });
sampleIntegration.getConfig = jest.fn().mockResolvedValue({ ok: true, value: mockTemplate });

// Mock builder sub-methods
const remapIDsSpy = jest.spyOn(builder, 'remapIDs');
Expand All @@ -121,22 +131,24 @@ describe('IntegrationInstanceBuilder', () => {
dataSource: 'instance-datasource',
name: 'instance-name',
};
sampleIntegration.deepCheck = jest.fn().mockResolvedValue(false);
sampleIntegration.deepCheck = jest
.fn()
.mockResolvedValue({ ok: false, error: new Error('Mock error') });
Swiddis marked this conversation as resolved.
Show resolved Hide resolved

await expect(builder.build(sampleIntegration, options)).rejects.toThrowError(
'Integration is not valid'
);
await expect(builder.build(sampleIntegration, options)).rejects.toThrowError('Mock error');
});

it('should reject with an error if getAssets throws an error', async () => {
it('should reject with an error if getAssets rejects', async () => {
const options = {
dataSource: 'instance-datasource',
name: 'instance-name',
};

const errorMessage = 'Failed to get assets';
sampleIntegration.deepCheck = jest.fn().mockResolvedValue(true);
sampleIntegration.getAssets = jest.fn().mockRejectedValue(new Error(errorMessage));
sampleIntegration.deepCheck = jest.fn().mockResolvedValue({ ok: true, value: {} });
sampleIntegration.getAssets = jest
.fn()
.mockResolvedValue({ ok: false, error: new Error(errorMessage) });

await expect(builder.build(sampleIntegration, options)).rejects.toThrowError(errorMessage);
});
Expand All @@ -153,22 +165,14 @@ describe('IntegrationInstanceBuilder', () => {
},
];
const errorMessage = 'Failed to post assets';
sampleIntegration.deepCheck = jest.fn().mockResolvedValue(true);
sampleIntegration.getAssets = jest.fn().mockResolvedValue({ savedObjects: remappedAssets });
sampleIntegration.deepCheck = jest.fn().mockResolvedValue({ ok: true, value: {} });
sampleIntegration.getAssets = jest
.fn()
.mockResolvedValue({ ok: true, value: { savedObjects: remappedAssets } });
builder.postAssets = jest.fn().mockRejectedValue(new Error(errorMessage));

await expect(builder.build(sampleIntegration, options)).rejects.toThrowError(errorMessage);
});

it('should reject with an error if getConfig returns null', async () => {
const options = {
dataSource: 'instance-datasource',
name: 'instance-name',
};
sampleIntegration.getConfig = jest.fn().mockResolvedValue(null);

await expect(builder.build(sampleIntegration, options)).rejects.toThrowError();
});
});

describe('remapIDs', () => {
Expand Down Expand Up @@ -264,8 +268,11 @@ describe('IntegrationInstanceBuilder', () => {
it('should build an integration instance', async () => {
const integration = {
getConfig: jest.fn().mockResolvedValue({
name: 'integration-template',
type: 'integration-type',
ok: true,
value: {
name: 'integration-template',
type: 'integration-type',
},
}),
};
const refs = [
Expand All @@ -291,7 +298,7 @@ describe('IntegrationInstanceBuilder', () => {
};

const instance = await builder.buildInstance(
(integration as unknown) as Integration,
(integration as unknown) as IntegrationReader,
refs,
options
);
Expand Down Expand Up @@ -319,7 +326,7 @@ describe('IntegrationInstanceBuilder', () => {
};

await expect(
builder.buildInstance((integration as unknown) as Integration, refs, options)
builder.buildInstance((integration as unknown) as IntegrationReader, refs, options)
).rejects.toThrowError();
});
});
Expand Down
24 changes: 17 additions & 7 deletions server/adaptors/integrations/__test__/local_repository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Repository } from '../repository/repository';
import { Integration } from '../repository/integration';
import { RepositoryReader } from '../repository/repository';
import { IntegrationReader } from '../repository/integration';
import path from 'path';
import * as fs from 'fs/promises';

Expand All @@ -20,15 +20,25 @@ describe('The local repository', () => {
return Promise.resolve(null);
}
// Otherwise, all directories must be integrations
const integ = new Integration(integPath);
await expect(integ.check()).resolves.toBe(true);
const integ = new IntegrationReader(integPath);
expect(integ.getConfig()).resolves.toHaveProperty('ok', true);
})
);
});

it('Should pass deep validation for all local integrations.', async () => {
const repository: Repository = new Repository(path.join(__dirname, '../__data__/repository'));
const integrations: Integration[] = await repository.getIntegrationList();
await Promise.all(integrations.map((i) => expect(i.deepCheck()).resolves.toBeTruthy()));
const repository: RepositoryReader = new RepositoryReader(
path.join(__dirname, '../__data__/repository')
);
const integrations: IntegrationReader[] = await repository.getIntegrationList();
await Promise.all(
integrations.map(async (i) => {
const result = await i.deepCheck();
if (!result.ok) {
console.error(result.error);
}
expect(result.ok).toBe(true);
})
);
});
});
Loading
Loading