From 03c98af127f9f6c54cfb219be76ef28758bdffb5 Mon Sep 17 00:00:00 2001 From: Rosalie Liu <52677246+rosalie-liu@users.noreply.github.com> Date: Thu, 31 Oct 2019 16:39:26 -0400 Subject: [PATCH] feat(ml): add ml models resource --- .../MachineLearning/MachineLearning.ts | 23 ++++++++ .../MachineLearningInterfaces.ts | 26 +++++++++ .../ModelInformation/ModelInformation.ts | 22 +++++++ .../ModelInformationInterfaces.ts | 4 ++ .../MachineLearning/ModelInformation/index.ts | 2 + .../tests/ModelInformation.spec.ts | 57 +++++++++++++++++++ .../MachineLearning/Models/Models.ts | 24 ++++++++ .../Models/ModelsInterfaces.ts | 55 ++++++++++++++++++ src/resources/MachineLearning/Models/index.ts | 2 + .../Models/tests/Models.spec.ts | 52 +++++++++++++++++ src/resources/MachineLearning/index.ts | 4 ++ .../tests/MachineLearning.spec.ts | 33 +++++++++++ src/resources/PlatformResources.ts | 3 + src/resources/index.ts | 1 + src/resources/tests/PlatformResources.spec.ts | 11 +++- 15 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 src/resources/MachineLearning/MachineLearning.ts create mode 100644 src/resources/MachineLearning/MachineLearningInterfaces.ts create mode 100644 src/resources/MachineLearning/ModelInformation/ModelInformation.ts create mode 100644 src/resources/MachineLearning/ModelInformation/ModelInformationInterfaces.ts create mode 100644 src/resources/MachineLearning/ModelInformation/index.ts create mode 100644 src/resources/MachineLearning/ModelInformation/tests/ModelInformation.spec.ts create mode 100644 src/resources/MachineLearning/Models/Models.ts create mode 100644 src/resources/MachineLearning/Models/ModelsInterfaces.ts create mode 100644 src/resources/MachineLearning/Models/index.ts create mode 100644 src/resources/MachineLearning/Models/tests/Models.spec.ts create mode 100644 src/resources/MachineLearning/index.ts create mode 100644 src/resources/MachineLearning/tests/MachineLearning.spec.ts diff --git a/src/resources/MachineLearning/MachineLearning.ts b/src/resources/MachineLearning/MachineLearning.ts new file mode 100644 index 000000000..53686f38e --- /dev/null +++ b/src/resources/MachineLearning/MachineLearning.ts @@ -0,0 +1,23 @@ +import API from '../../APICore'; +import Resource from '../Resource'; +import {MLModelCreated, RegistrationModel} from './MachineLearningInterfaces'; +import ModelInformation from './ModelInformation/ModelInformation'; +import Models from './Models/Models'; + +export default class MachineLearning extends Resource { + static baseUrl = `/rest/organizations/${API.orgPlaceholder}/machinelearning`; + + models: Models; + modelInfo: ModelInformation; + + constructor(protected api: API) { + super(api); + + this.models = new Models(api); + this.modelInfo = new ModelInformation(api); + } + + register(registration: RegistrationModel) { + return this.api.post(`${MachineLearning.baseUrl}/model`, registration); + } +} diff --git a/src/resources/MachineLearning/MachineLearningInterfaces.ts b/src/resources/MachineLearning/MachineLearningInterfaces.ts new file mode 100644 index 000000000..07f9a8225 --- /dev/null +++ b/src/resources/MachineLearning/MachineLearningInterfaces.ts @@ -0,0 +1,26 @@ +import {IdAndDisplayNameModel} from '../BaseInterfaces'; +import {MLModel} from './Models/ModelsInterfaces'; + +export interface RegistrationModel { + engineId: string; + modelName: string; + modelDisplayName?: string; + exportPeriod: string; + intervalTime: number; + intervalUnit: 'DAY' | 'WEEK' | 'MONTH'; + exportOffset?: string; + apiKeysThatCanEdit?: IdAndDisplayNameModel[]; + groupsThatCanEdit?: IdAndDisplayNameModel[]; + commandLineParameters?: string[]; + commonFilter?: string; + customEventFilter?: string; + searchEventFilter?: string; + viewEventFilter?: string; + versionMatcher?: string; +} + +export interface MLModelCreated extends MLModel { + endTime?: number; + startTime?: number; + resourceId?: string; +} diff --git a/src/resources/MachineLearning/ModelInformation/ModelInformation.ts b/src/resources/MachineLearning/ModelInformation/ModelInformation.ts new file mode 100644 index 000000000..5c031659b --- /dev/null +++ b/src/resources/MachineLearning/ModelInformation/ModelInformation.ts @@ -0,0 +1,22 @@ +import API from '../../../APICore'; +import Resource from '../../Resource'; +import {RegistrationModel} from '../MachineLearningInterfaces'; +import {MLModel} from '../Models/ModelsInterfaces'; +import {MLModelInfo} from './ModelInformationInterfaces'; + +export default class ModelInformation extends Resource { + static getBaseUrl = (engineId: string, modelName: string) => + `/rest/organizations/${API.orgPlaceholder}/machinelearning/engines/${engineId}/models/${modelName}`; + + get(engineId: string, modelName: string) { + return this.api.get(`${ModelInformation.getBaseUrl(engineId, modelName)}/details`); + } + + delete(engineId: string, modelName: string) { + return this.api.delete(ModelInformation.getBaseUrl(engineId, modelName)); + } + + update(engineId: string, modelName: string, modelInformation: RegistrationModel) { + return this.api.put>(ModelInformation.getBaseUrl(engineId, modelName), modelInformation); + } +} diff --git a/src/resources/MachineLearning/ModelInformation/ModelInformationInterfaces.ts b/src/resources/MachineLearning/ModelInformation/ModelInformationInterfaces.ts new file mode 100644 index 000000000..8b53cc872 --- /dev/null +++ b/src/resources/MachineLearning/ModelInformation/ModelInformationInterfaces.ts @@ -0,0 +1,4 @@ +export interface MLModelInfo { + id: string; + info?: {}; +} diff --git a/src/resources/MachineLearning/ModelInformation/index.ts b/src/resources/MachineLearning/ModelInformation/index.ts new file mode 100644 index 000000000..7511e6601 --- /dev/null +++ b/src/resources/MachineLearning/ModelInformation/index.ts @@ -0,0 +1,2 @@ +export * from './ModelInformation'; +export * from './ModelInformationInterfaces'; diff --git a/src/resources/MachineLearning/ModelInformation/tests/ModelInformation.spec.ts b/src/resources/MachineLearning/ModelInformation/tests/ModelInformation.spec.ts new file mode 100644 index 000000000..e073b4c4a --- /dev/null +++ b/src/resources/MachineLearning/ModelInformation/tests/ModelInformation.spec.ts @@ -0,0 +1,57 @@ +import API from '../../../../APICore'; +import {RegistrationModel} from '../../MachineLearningInterfaces'; +import ModelInformation from '../ModelInformation'; + +jest.mock('../../../../APICore'); + +const APIMock: jest.Mock = API as any; + +describe('ModelInformation', () => { + let modelInfo: ModelInformation; + const api = new APIMock() as jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + modelInfo = new ModelInformation(api); + }); + + describe('get', () => { + it('should make a GET call to the specific ModelInformation url', () => { + const engineId = 'O. O'; + const modelName = 'O .O'; + + modelInfo.get(engineId, modelName); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(`${ModelInformation.getBaseUrl(engineId, modelName)}/details`); + }); + }); + + describe('delete', () => { + it('should make a DELETE call to the specific ModelInformation url', () => { + const engineId = 'OAO'; + const modelName = 'QAQ'; + + modelInfo.delete(engineId, modelName); + expect(api.delete).toHaveBeenCalledTimes(1); + expect(api.delete).toHaveBeenCalledWith(ModelInformation.getBaseUrl(engineId, modelName)); + }); + }); + + describe('update', () => { + it('should make a PUT call to the specific ModelInformation url', () => { + const engineId = '-_-'; + const modelName = '@_@'; + const modelInformation: RegistrationModel = { + engineId: 'O_O', + modelName: 'mini model', + exportPeriod: 'XYZ', + intervalTime: 999, + intervalUnit: 'WEEK', + }; + + modelInfo.update(engineId, modelName, modelInformation); + expect(api.put).toHaveBeenCalledTimes(1); + expect(api.put).toHaveBeenCalledWith(ModelInformation.getBaseUrl(engineId, modelName), modelInformation); + }); + }); +}); diff --git a/src/resources/MachineLearning/Models/Models.ts b/src/resources/MachineLearning/Models/Models.ts new file mode 100644 index 000000000..ed0592ebf --- /dev/null +++ b/src/resources/MachineLearning/Models/Models.ts @@ -0,0 +1,24 @@ +import API from '../../../APICore'; +import Resource from '../../Resource'; +import {MLModelInfo} from '../ModelInformation/ModelInformationInterfaces'; +import {MLModel} from './ModelsInterfaces'; + +export default class Models extends Resource { + static baseUrl = `/rest/organizations/${API.orgPlaceholder}/machinelearning/models`; + + list() { + return this.api.get(Models.baseUrl); + } + + listDetails() { + return this.api.get(`${Models.baseUrl}/details`); + } + + get(modelId: string) { + return this.api.get(`${Models.baseUrl}/${modelId}/details`); + } + + delete(modelId: string) { + return this.api.delete(`${Models.baseUrl}/${modelId}`); + } +} diff --git a/src/resources/MachineLearning/Models/ModelsInterfaces.ts b/src/resources/MachineLearning/Models/ModelsInterfaces.ts new file mode 100644 index 000000000..e2c6e6c5c --- /dev/null +++ b/src/resources/MachineLearning/Models/ModelsInterfaces.ts @@ -0,0 +1,55 @@ +import {IdAndDisplayNameModel} from '../../BaseInterfaces'; +import {MLModelInfo} from '../ModelInformation/ModelInformationInterfaces'; + +export interface MLModel extends MLModelInfo { + orgId: string; + id: string; + engineId: string; + modelName: string; + modelDisplayName?: string; + modelCreationTime: number; + nextModelUpdateTime?: number; + modelVersion?: string; + engineVersion?: string; + platformVersion?: 1 | 2; + versionMatcher?: string; + apiKeysThatCanEdit?: IdAndDisplayNameModel[]; + groupsThatCanEdit?: IdAndDisplayNameModel[]; + modelErrorDescription?: ModelErrorDescription; + previousModelUpdateTime?: number; + intervalTime: number; + intervalUnit: 'DAY' | 'WEEK' | 'MONTH'; + exportPeriod: string; + exportOffset?: string; + status: + | 'DELETED' + | 'SCHEDULING' + | 'SCHEDULED' + | 'ERROR' + | 'PENDING' + | 'REGISTERED' + | 'PAUSED' + | 'REGISTERING' + | 'IN_PROGRESS' + | 'ERROR_DELETING' + | 'ONLINE' + | 'OFFLINE' + | 'IN_CREATION'; + commandLineParameters?: string[]; + commonFilter?: string; + customEventFilter?: string; + searchEventFilter?: string; + viewEventFilter?: string; +} + +export interface ModelErrorDescription { + customer_errors?: CustomerError[]; +} + +export interface CustomerError { + description?: string; + errorCode?: string; + errorType?: string; + precision?: string; + troubleshoot?: string; +} diff --git a/src/resources/MachineLearning/Models/index.ts b/src/resources/MachineLearning/Models/index.ts new file mode 100644 index 000000000..6833d11a0 --- /dev/null +++ b/src/resources/MachineLearning/Models/index.ts @@ -0,0 +1,2 @@ +export * from './Models'; +export * from './ModelsInterfaces'; diff --git a/src/resources/MachineLearning/Models/tests/Models.spec.ts b/src/resources/MachineLearning/Models/tests/Models.spec.ts new file mode 100644 index 000000000..34d9661a2 --- /dev/null +++ b/src/resources/MachineLearning/Models/tests/Models.spec.ts @@ -0,0 +1,52 @@ +import API from '../../../../APICore'; +import Models from '../Models'; + +jest.mock('../../../../APICore'); + +const APIMock: jest.Mock = API as any; + +describe('Models', () => { + let models: Models; + const api = new APIMock() as jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + models = new Models(api); + }); + + describe('list', () => { + it('should make a GET call to the Models base url', () => { + models.list(); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(Models.baseUrl); + }); + }); + + describe('listDetails', () => { + it('should make a GET call to the specific Models url', () => { + models.listDetails(); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(`${Models.baseUrl}/details`); + }); + }); + + describe('get', () => { + it('should make a GET call to the specific Models url', () => { + const modelId = 'O. O'; + + models.get(modelId); + expect(api.get).toHaveBeenCalledTimes(1); + expect(api.get).toHaveBeenCalledWith(`${Models.baseUrl}/${modelId}/details`); + }); + }); + + describe('delete', () => { + it('should make a DELETE call to the specific Models url', () => { + const modelId = 'O .O'; + + models.delete(modelId); + expect(api.delete).toHaveBeenCalledTimes(1); + expect(api.delete).toHaveBeenCalledWith(`${Models.baseUrl}/${modelId}`); + }); + }); +}); diff --git a/src/resources/MachineLearning/index.ts b/src/resources/MachineLearning/index.ts new file mode 100644 index 000000000..ccbc6e6a2 --- /dev/null +++ b/src/resources/MachineLearning/index.ts @@ -0,0 +1,4 @@ +export * from './MachineLearning'; +export * from './MachineLearningInterfaces'; +export * from './Models/'; +export * from './ModelInformation/'; diff --git a/src/resources/MachineLearning/tests/MachineLearning.spec.ts b/src/resources/MachineLearning/tests/MachineLearning.spec.ts new file mode 100644 index 000000000..058a261fc --- /dev/null +++ b/src/resources/MachineLearning/tests/MachineLearning.spec.ts @@ -0,0 +1,33 @@ +import API from '../../../APICore'; +import MachineLearning from '../MachineLearning'; +import {RegistrationModel} from '../MachineLearningInterfaces'; + +jest.mock('../../../APICore'); + +const APIMock: jest.Mock = API as any; + +describe('MachineLearning', () => { + let ml: MachineLearning; + const api = new APIMock() as jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + ml = new MachineLearning(api); + }); + + describe('register', () => { + it('should make a POST call to the specific MachineLearning url', () => { + const registration: RegistrationModel = { + engineId: 'OvO', + modelName: 'super model', + exportPeriod: 'ABC', + intervalTime: 666, + intervalUnit: 'DAY', + }; + + ml.register(registration); + expect(api.post).toHaveBeenCalledTimes(1); + expect(api.post).toHaveBeenCalledWith(`${MachineLearning.baseUrl}/model`, registration); + }); + }); +}); diff --git a/src/resources/PlatformResources.ts b/src/resources/PlatformResources.ts index b040906f7..1a2f7ed89 100644 --- a/src/resources/PlatformResources.ts +++ b/src/resources/PlatformResources.ts @@ -5,6 +5,7 @@ import Catalog from './Catalogs/Catalog'; import Cluster from './Clusters/Cluster'; import Group from './Groups/Groups'; import Index from './Indexes/Indexes'; +import MachineLearning from './MachineLearning/MachineLearning'; import Organization from './Organizations/Organization'; import Resource from './Resource'; import SecurityCache from './SecurityCache/SecurityCache'; @@ -18,6 +19,7 @@ const resourcesMap: Array<{key: string; resource: typeof Resource}> = [ {key: 'index', resource: Index}, {key: 'securityCache', resource: SecurityCache}, {key: 'apiKey', resource: ApiKey}, + {key: 'ml', resource: MachineLearning}, ]; class PlatformResources { @@ -30,6 +32,7 @@ class PlatformResources { organization: Organization; index: Index; apiKey: ApiKey; + ml: MachineLearning; securityCache: SecurityCache; registerAll() { diff --git a/src/resources/index.ts b/src/resources/index.ts index 7447aaec8..2976fd8bf 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -9,3 +9,4 @@ export * from './Indexes'; export * from './License'; export * from './Organizations'; export * from './ApiKeys'; +export * from './MachineLearning'; diff --git a/src/resources/tests/PlatformResources.spec.ts b/src/resources/tests/PlatformResources.spec.ts index d2782cce8..397b52122 100644 --- a/src/resources/tests/PlatformResources.spec.ts +++ b/src/resources/tests/PlatformResources.spec.ts @@ -3,6 +3,7 @@ import AWS from '../AWS/AWS'; import Catalog from '../Catalogs/Catalog'; import Cluster from '../Clusters/Cluster'; import Group from '../Groups/Groups'; +import MachineLearning from '../MachineLearning/MachineLearning'; import Organization from '../Organizations/Organization'; import PlatformResources from '../PlatformResources'; import SecurityCache from '../SecurityCache/SecurityCache'; @@ -57,12 +58,20 @@ describe('PlatformResources', () => { expect(platformResources.securityCache).toBeInstanceOf(SecurityCache); }); - it('should register the api keys ressource on the platform instance', () => { + it('should register the apiKey resource on the platform instance', () => { const platformResources = new PlatformResources(); platformResources.registerAll(); expect(platformResources.apiKey).toBeDefined(); expect(platformResources.apiKey).toBeInstanceOf(ApiKey); }); + + it('should register the ml resource on the platform instance', () => { + const platformResources = new PlatformResources(); + platformResources.registerAll(); + + expect(platformResources.ml).toBeDefined(); + expect(platformResources.ml).toBeInstanceOf(MachineLearning); + }); }); });