From 38e58529b12684f6ae2a7206a4926795c233747d Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Tue, 19 Sep 2023 18:14:35 +0800 Subject: [PATCH 1/8] temp: add unit test Signed-off-by: SuZhou-Joe --- test/api_integration/apis/workspace/index.ts | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/api_integration/apis/workspace/index.ts diff --git a/test/api_integration/apis/workspace/index.ts b/test/api_integration/apis/workspace/index.ts new file mode 100644 index 000000000000..18b0f9b7f511 --- /dev/null +++ b/test/api_integration/apis/workspace/index.ts @@ -0,0 +1,39 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import expect from '@osd/expect'; +import { WorkspaceAttribute } from 'opensearch-dashboards/server'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const testWorkspace: WorkspaceAttribute = { + id: 'fake_id', + name: 'test_workspace', + description: 'test_workspace_description', +}; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const opensearch = getService('legacyOpenSearch'); + + const MILLISECOND_IN_WEEK = 1000 * 60 * 60 * 24 * 7; + + describe('Workspace CRUD apis', () => { + it('basic CRUD', async () => { + const resp = await supertest + .post(`/api/workspaces`) + .set('osd-xsrf', 'opensearch-dashboards') + .send( + JSON.stringify({ + attributes: testWorkspace, + }) + ) + .expect(200); + + expect(resp.body).to.be.an('array'); + expect(resp.body.length).to.be.above(0); + expect(resp.body[0].status).to.be('not_installed'); + }); + }); +} From c63aa348885320c36aa59fd5f5a94ee72ff0817b Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 20 Sep 2023 09:42:02 +0000 Subject: [PATCH 2/8] feat: add function test for workspace CRUD routes Signed-off-by: SuZhou-Joe --- src/plugins/workspace/server/routes/index.ts | 10 +- test/api_integration/apis/index.js | 1 + test/api_integration/apis/workspace/index.ts | 121 ++++++++++++++++--- 3 files changed, 109 insertions(+), 23 deletions(-) diff --git a/src/plugins/workspace/server/routes/index.ts b/src/plugins/workspace/server/routes/index.ts index 39cc5877b469..f968c853fc90 100644 --- a/src/plugins/workspace/server/routes/index.ts +++ b/src/plugins/workspace/server/routes/index.ts @@ -55,15 +55,7 @@ export function registerRoutes({ return res.ok({ body: result }); } return res.ok({ - body: { - ...result, - result: { - ...result.result, - workspaces: result.result.workspaces.map((workspace) => ({ - ...workspace, - })), - }, - }, + body: result, }); }) ); diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js index 54ffe6e774a5..2d870d88251d 100644 --- a/test/api_integration/apis/index.js +++ b/test/api_integration/apis/index.js @@ -45,5 +45,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./stats')); loadTestFile(require.resolve('./ui_metric')); loadTestFile(require.resolve('./telemetry')); + loadTestFile(require.resolve('./workspace')); }); } diff --git a/test/api_integration/apis/workspace/index.ts b/test/api_integration/apis/workspace/index.ts index 18b0f9b7f511..553ee0dce1af 100644 --- a/test/api_integration/apis/workspace/index.ts +++ b/test/api_integration/apis/workspace/index.ts @@ -5,6 +5,7 @@ import expect from '@osd/expect'; import { WorkspaceAttribute } from 'opensearch-dashboards/server'; +import { omit } from 'lodash'; import { FtrProviderContext } from '../../ftr_provider_context'; const testWorkspace: WorkspaceAttribute = { @@ -15,25 +16,117 @@ const testWorkspace: WorkspaceAttribute = { export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const opensearch = getService('legacyOpenSearch'); - - const MILLISECOND_IN_WEEK = 1000 * 60 * 60 * 24 * 7; describe('Workspace CRUD apis', () => { - it('basic CRUD', async () => { - const resp = await supertest - .post(`/api/workspaces`) + afterEach(async () => { + const listResult = await supertest + .post(`/api/workspaces/_list`) + .send({ + page: 1, + }) .set('osd-xsrf', 'opensearch-dashboards') - .send( - JSON.stringify({ - attributes: testWorkspace, - }) + .expect(200); + await Promise.all( + listResult.body.result.workspaces.map((item: WorkspaceAttribute) => + supertest + .delete(`/api/workspaces/${item.id}`) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200) ) + ); + }); + it('create', async () => { + await supertest + .post(`/api/workspaces`) + .send({ + attributes: testWorkspace, + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(400); + + const result: any = await supertest + .post(`/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + expect(result.body.success).equal(true); + expect(result.body.result.id).to.be.a('string'); + }); + it('get', async () => { + const result = await supertest + .post(`/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + const getResult = await supertest.get(`/api/workspaces/${result.body.result.id}`); + expect(getResult.body.result.name).equal(testWorkspace.name); + }); + it('update', async () => { + const result: any = await supertest + .post(`/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .set('osd-xsrf', 'opensearch-dashboards') .expect(200); - expect(resp.body).to.be.an('array'); - expect(resp.body.length).to.be.above(0); - expect(resp.body[0].status).to.be('not_installed'); + await supertest + .put(`/api/workspaces/${result.body.result.id}`) + .send({ + attributes: { + ...omit(testWorkspace, 'id'), + name: 'updated', + }, + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + const getResult = await supertest.get(`/api/workspaces/${result.body.result.id}`); + + expect(getResult.body.success).equal(true); + expect(getResult.body.result.name).equal('updated'); + }); + it('delete', async () => { + const result: any = await supertest + .post(`/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + await supertest + .delete(`/api/workspaces/${result.body.result.id}`) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + const getResult = await supertest.get(`/api/workspaces/${result.body.result.id}`); + + expect(getResult.body.success).equal(false); + }); + it('list', async () => { + await supertest + .post(`/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + + const listResult = await supertest + .post(`/api/workspaces/_list`) + .send({ + page: 1, + }) + .set('osd-xsrf', 'opensearch-dashboards') + .expect(200); + expect(listResult.body.result.total).equal(1); }); - }); + }).tags('is:workspace'); } From 755825d170086cf581c37aad32493f4e4526e12d Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 20 Sep 2023 09:53:03 +0000 Subject: [PATCH 3/8] feat: use saved objects client instead of internal repository Signed-off-by: SuZhou-Joe --- src/plugins/workspace/server/plugin.ts | 11 ++++++++-- src/plugins/workspace/server/types.ts | 4 ++-- .../workspace/server/workspace_client.ts | 20 +++++++++++-------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 515ccc399f8e..568f536d65e8 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -2,7 +2,13 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ -import { PluginInitializerContext, CoreSetup, Plugin, Logger } from '../../../core/server'; +import { + PluginInitializerContext, + CoreSetup, + Plugin, + Logger, + CoreStart, +} from '../../../core/server'; import { IWorkspaceDBImpl } from './types'; import { WorkspaceClientWithSavedObject } from './workspace_client'; import { registerRoutes } from './routes'; @@ -33,8 +39,9 @@ export class WorkspacePlugin implements Plugin<{}, {}> { }; } - public start() { + public start(core: CoreStart) { this.logger.debug('Starting Workspace service'); + this.client?.setSavedObjects(core.savedObjects); return { client: this.client as IWorkspaceDBImpl, diff --git a/src/plugins/workspace/server/types.ts b/src/plugins/workspace/server/types.ts index d57cecd4a3c9..28d8c25fd3b0 100644 --- a/src/plugins/workspace/server/types.ts +++ b/src/plugins/workspace/server/types.ts @@ -9,7 +9,7 @@ import { SavedObjectsFindResponse, CoreSetup, WorkspaceAttribute, - ISavedObjectsRepository, + SavedObjectsServiceStart, } from '../../../core/server'; export interface WorkspaceFindOptions { @@ -29,7 +29,7 @@ export interface IRequestDetail { export interface IWorkspaceDBImpl { setup(dep: CoreSetup): Promise>; - setInternalRepository(repository: ISavedObjectsRepository): void; + setSavedObjects(savedObjects: SavedObjectsServiceStart): void; create( requestDetail: IRequestDetail, payload: Omit diff --git a/src/plugins/workspace/server/workspace_client.ts b/src/plugins/workspace/server/workspace_client.ts index ec49daf83b6a..e8e6b01c85c9 100644 --- a/src/plugins/workspace/server/workspace_client.ts +++ b/src/plugins/workspace/server/workspace_client.ts @@ -8,7 +8,7 @@ import type { SavedObjectsClientContract, CoreSetup, WorkspaceAttribute, - ISavedObjectsRepository, + SavedObjectsServiceStart, } from '../../../core/server'; import { WORKSPACE_TYPE } from '../../../core/server'; import { IWorkspaceDBImpl, WorkspaceFindOptions, IResponse, IRequestDetail } from './types'; @@ -23,15 +23,16 @@ const DUPLICATE_WORKSPACE_NAME_ERROR = i18n.translate('workspace.duplicate.name. export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { private setupDep: CoreSetup; - - private internalSavedObjectsRepository?: ISavedObjectsRepository; - setInternalRepository(repository: ISavedObjectsRepository) { - this.internalSavedObjectsRepository = repository; - } + private savedObjects?: SavedObjectsServiceStart; constructor(core: CoreSetup) { this.setupDep = core; } + + private getScopedClient(requestDetail: IRequestDetail): SavedObjectsClientContract | undefined { + return this.savedObjects?.getScopedClient(requestDetail.request); + } + private getSavedObjectClientsFromRequestDetail( requestDetail: IRequestDetail ): SavedObjectsClientContract { @@ -63,7 +64,7 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { const attributes = payload; const id = generateRandomId(WORKSPACE_ID_SIZE); const client = this.getSavedObjectClientsFromRequestDetail(requestDetail); - const existingWorkspaceRes = await this.internalSavedObjectsRepository?.find({ + const existingWorkspaceRes = await this.getScopedClient(requestDetail)?.find({ type: WORKSPACE_TYPE, search: attributes.name, searchFields: ['name'], @@ -148,7 +149,7 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { const client = this.getSavedObjectClientsFromRequestDetail(requestDetail); const workspaceInDB: SavedObject = await client.get(WORKSPACE_TYPE, id); if (workspaceInDB.attributes.name !== attributes.name) { - const existingWorkspaceRes = await this.internalSavedObjectsRepository?.find({ + const existingWorkspaceRes = await this.getScopedClient(requestDetail)?.find({ type: WORKSPACE_TYPE, search: attributes.name, searchFields: ['name'], @@ -184,6 +185,9 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { }; } } + public setSavedObjects(savedObjects: SavedObjectsServiceStart) { + this.savedObjects = savedObjects; + } public async destroy(): Promise> { return { success: true, From 1ba404b28aefd96ce2f7488a4de8d677d1198cc9 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 20 Sep 2023 17:59:11 +0800 Subject: [PATCH 4/8] feat: update CHANGELOG Signed-off-by: SuZhou-Joe --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93c8227d9765..8abc72aeb779 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Adds Data explorer framework and implements Discover using it ([#4806](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4806)) - [Theme] Use themes' definitions to render the initial view ([#4936](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4936/)) - [Theme] Make `next` theme the default ([#4854](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4854/)) +- [Workspace] Setup workspace skeleton and implement basic CRUD API ([#5075](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5075/)) ### 🐛 Bug Fixes From 426124aeda930959e0c7209d869003d5eca92275 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Wed, 20 Sep 2023 10:07:58 +0000 Subject: [PATCH 5/8] feat: exclude permission check wrapper Signed-off-by: SuZhou-Joe --- src/plugins/workspace/common/constants.ts | 6 +++++ .../workspace/server/workspace_client.ts | 25 +++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 src/plugins/workspace/common/constants.ts diff --git a/src/plugins/workspace/common/constants.ts b/src/plugins/workspace/common/constants.ts new file mode 100644 index 000000000000..b6bd7b00f676 --- /dev/null +++ b/src/plugins/workspace/common/constants.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID = 'workspace'; diff --git a/src/plugins/workspace/server/workspace_client.ts b/src/plugins/workspace/server/workspace_client.ts index e8e6b01c85c9..9dcbc2906d43 100644 --- a/src/plugins/workspace/server/workspace_client.ts +++ b/src/plugins/workspace/server/workspace_client.ts @@ -14,6 +14,7 @@ import { WORKSPACE_TYPE } from '../../../core/server'; import { IWorkspaceDBImpl, WorkspaceFindOptions, IResponse, IRequestDetail } from './types'; import { workspace } from './saved_objects'; import { generateRandomId } from './utils'; +import { WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID } from '../common/constants'; const WORKSPACE_ID_SIZE = 6; @@ -29,8 +30,12 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { this.setupDep = core; } - private getScopedClient(requestDetail: IRequestDetail): SavedObjectsClientContract | undefined { - return this.savedObjects?.getScopedClient(requestDetail.request); + private getScopedClientWithoutPermission( + requestDetail: IRequestDetail + ): SavedObjectsClientContract | undefined { + return this.savedObjects?.getScopedClient(requestDetail.request, { + excludedWrappers: [WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID], + }); } private getSavedObjectClientsFromRequestDetail( @@ -64,11 +69,13 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { const attributes = payload; const id = generateRandomId(WORKSPACE_ID_SIZE); const client = this.getSavedObjectClientsFromRequestDetail(requestDetail); - const existingWorkspaceRes = await this.getScopedClient(requestDetail)?.find({ - type: WORKSPACE_TYPE, - search: attributes.name, - searchFields: ['name'], - }); + const existingWorkspaceRes = await this.getScopedClientWithoutPermission(requestDetail)?.find( + { + type: WORKSPACE_TYPE, + search: attributes.name, + searchFields: ['name'], + } + ); if (existingWorkspaceRes && existingWorkspaceRes.total > 0) { throw new Error(DUPLICATE_WORKSPACE_NAME_ERROR); } @@ -149,7 +156,9 @@ export class WorkspaceClientWithSavedObject implements IWorkspaceDBImpl { const client = this.getSavedObjectClientsFromRequestDetail(requestDetail); const workspaceInDB: SavedObject = await client.get(WORKSPACE_TYPE, id); if (workspaceInDB.attributes.name !== attributes.name) { - const existingWorkspaceRes = await this.getScopedClient(requestDetail)?.find({ + const existingWorkspaceRes = await this.getScopedClientWithoutPermission( + requestDetail + )?.find({ type: WORKSPACE_TYPE, search: attributes.name, searchFields: ['name'], From a99870c4c12e04cb29fb5fbbc929c98edc115efd Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 21 Sep 2023 13:20:29 +0800 Subject: [PATCH 6/8] feat: add integration test Signed-off-by: SuZhou-Joe --- .../server/integration_tests/routes.test.ts | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/plugins/workspace/server/integration_tests/routes.test.ts diff --git a/src/plugins/workspace/server/integration_tests/routes.test.ts b/src/plugins/workspace/server/integration_tests/routes.test.ts new file mode 100644 index 000000000000..bdb342e00ade --- /dev/null +++ b/src/plugins/workspace/server/integration_tests/routes.test.ts @@ -0,0 +1,141 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { WorkspaceAttribute } from 'src/core/types'; +import { omit } from 'lodash'; +import * as osdTestServer from '../../../../core/test_helpers/osd_server'; + +const testWorkspace: WorkspaceAttribute = { + id: 'fake_id', + name: 'test_workspace', + description: 'test_workspace_description', +}; + +describe('workspace service', () => { + let root: ReturnType; + let opensearchServer: osdTestServer.TestOpenSearchUtils; + beforeAll(async () => { + const { startOpenSearch } = osdTestServer.createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + }); + opensearchServer = await startOpenSearch(); + root = osdTestServer.createRootWithCorePlugins(); + + await root.setup(); + await root.start(); + }, 30000); + afterAll(async () => { + await root.shutdown(); + await opensearchServer.stop(); + }); + describe('Workspace CRUD apis', () => { + afterEach(async () => { + const listResult = await osdTestServer.request + .post(root, `/api/workspaces/_list`) + .send({ + page: 1, + }) + .expect(200); + await Promise.all( + listResult.body.result.workspaces.map((item: WorkspaceAttribute) => + osdTestServer.request.delete(root, `/api/workspaces/${item.id}`).expect(200) + ) + ); + }); + it('create', async () => { + await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: testWorkspace, + }) + .expect(400); + + const result: any = await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .expect(200); + + expect(result.body.success).toEqual(true); + expect(typeof result.body.result.id).toBe('string'); + }); + it('get', async () => { + const result = await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .expect(200); + + const getResult = await osdTestServer.request.get( + root, + `/api/workspaces/${result.body.result.id}` + ); + expect(getResult.body.result.name).toEqual(testWorkspace.name); + }); + it('update', async () => { + const result: any = await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .expect(200); + + await osdTestServer.request + .put(root, `/api/workspaces/${result.body.result.id}`) + .send({ + attributes: { + ...omit(testWorkspace, 'id'), + name: 'updated', + }, + }) + .expect(200); + + const getResult = await osdTestServer.request.get( + root, + `/api/workspaces/${result.body.result.id}` + ); + + expect(getResult.body.success).toEqual(true); + expect(getResult.body.result.name).toEqual('updated'); + }); + it('delete', async () => { + const result: any = await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .expect(200); + + await osdTestServer.request + .delete(root, `/api/workspaces/${result.body.result.id}`) + .expect(200); + + const getResult = await osdTestServer.request.get( + root, + `/api/workspaces/${result.body.result.id}` + ); + + expect(getResult.body.success).toEqual(false); + }); + it('list', async () => { + await osdTestServer.request + .post(root, `/api/workspaces`) + .send({ + attributes: omit(testWorkspace, 'id'), + }) + .expect(200); + + const listResult = await osdTestServer.request + .post(root, `/api/workspaces/_list`) + .send({ + page: 1, + }) + .expect(200); + expect(listResult.body.result.total).toEqual(1); + }); + }); +}); From 54a2e0097d87d17714b26b9dc78ad60528d5e9d9 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 21 Sep 2023 13:43:01 +0800 Subject: [PATCH 7/8] feat: add configuration Signed-off-by: SuZhou-Joe --- src/plugins/workspace/config.ts | 12 ++++++++++++ src/plugins/workspace/server/index.ts | 9 ++++++++- .../workspace/server/saved_objects/workspace.ts | 11 +++++++---- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 src/plugins/workspace/config.ts diff --git a/src/plugins/workspace/config.ts b/src/plugins/workspace/config.ts new file mode 100644 index 000000000000..79412f5c02ee --- /dev/null +++ b/src/plugins/workspace/config.ts @@ -0,0 +1,12 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { schema, TypeOf } from '@osd/config-schema'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: false }), +}); + +export type ConfigSchema = TypeOf; diff --git a/src/plugins/workspace/server/index.ts b/src/plugins/workspace/server/index.ts index 936d3cf3ecec..9447b7c6dc8c 100644 --- a/src/plugins/workspace/server/index.ts +++ b/src/plugins/workspace/server/index.ts @@ -2,8 +2,9 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ -import { PluginInitializerContext } from '../../../core/server'; +import { PluginConfigDescriptor, PluginInitializerContext } from '../../../core/server'; import { WorkspacePlugin } from './plugin'; +import { configSchema } from '../config'; // This exports static code and TypeScript types, // as well as, OpenSearch Dashboards Platform `plugin()` initializer. @@ -11,3 +12,9 @@ import { WorkspacePlugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new WorkspacePlugin(initializerContext); } + +export const config: PluginConfigDescriptor = { + schema: configSchema, +}; + +export { WorkspaceFindOptions } from './types'; diff --git a/src/plugins/workspace/server/saved_objects/workspace.ts b/src/plugins/workspace/server/saved_objects/workspace.ts index 5142185b0c2d..a26e695d83cb 100644 --- a/src/plugins/workspace/server/saved_objects/workspace.ts +++ b/src/plugins/workspace/server/saved_objects/workspace.ts @@ -25,16 +25,19 @@ export const workspace: SavedObjectsType = { * In opensearch, string[] is also mapped to text */ features: { - type: 'text', + type: 'keyword', }, color: { - type: 'text', + type: 'keyword', }, icon: { - type: 'text', + type: 'keyword', }, defaultVISTheme: { - type: 'text', + type: 'keyword', + }, + reserved: { + type: 'boolean', }, }, }, From 9d3933ce81f9d2951d334198f1c147ba3a92567f Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 21 Sep 2023 15:02:28 +0800 Subject: [PATCH 8/8] feat: enable workspace flag when run workspace related test Signed-off-by: SuZhou-Joe --- .../server/integration_tests/routes.test.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/plugins/workspace/server/integration_tests/routes.test.ts b/src/plugins/workspace/server/integration_tests/routes.test.ts index bdb342e00ade..e4d29b86ac55 100644 --- a/src/plugins/workspace/server/integration_tests/routes.test.ts +++ b/src/plugins/workspace/server/integration_tests/routes.test.ts @@ -17,14 +17,19 @@ describe('workspace service', () => { let root: ReturnType; let opensearchServer: osdTestServer.TestOpenSearchUtils; beforeAll(async () => { - const { startOpenSearch } = osdTestServer.createTestServers({ + const { startOpenSearch, startOpenSearchDashboards } = osdTestServer.createTestServers({ adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + osd: { + workspace: { + enabled: true, + }, + }, + }, }); opensearchServer = await startOpenSearch(); - root = osdTestServer.createRootWithCorePlugins(); - - await root.setup(); - await root.start(); + const startOSDResp = await startOpenSearchDashboards(); + root = startOSDResp.root; }, 30000); afterAll(async () => { await root.shutdown();