Skip to content

Commit

Permalink
[Feature] Setup workspace skeleton and implement basic CRUD API (open…
Browse files Browse the repository at this point in the history
…search-project#130)

* feature: setup workspace skeleton and implement basic CRUD API on workspace

Signed-off-by: Zhou Su <suzhou@dev-dsk-suzhou-2a-8ce7a7a7.us-west-2.amazon.com>

* feat: remove useless required plugins and logger typo

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

* feat: setup public side skeleton

Signed-off-by: SuZhou-Joe <suzhou@amazon.com>

---------

Signed-off-by: Zhou Su <suzhou@dev-dsk-suzhou-2a-8ce7a7a7.us-west-2.amazon.com>
Signed-off-by: SuZhou-Joe <suzhou@amazon.com>
Co-authored-by: Zhou Su <suzhou@dev-dsk-suzhou-2a-8ce7a7a7.us-west-2.amazon.com>
  • Loading branch information
2 people authored and ruanyl committed Sep 15, 2023
1 parent b9b2b79 commit 074d23b
Show file tree
Hide file tree
Showing 17 changed files with 638 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/core/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ export {
MetricsServiceStart,
} from './metrics';

export { AppCategory } from '../types';
export { DEFAULT_APP_CATEGORIES } from '../utils';
export { AppCategory, WorkspaceAttribute } from '../types';
export { DEFAULT_APP_CATEGORIES, WORKSPACE_TYPE } from '../utils';

export {
SavedObject,
Expand Down
1 change: 1 addition & 0 deletions src/core/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ export * from './ui_settings';
export * from './saved_objects';
export * from './serializable';
export * from './custom_branding';
export * from './workspace';
14 changes: 14 additions & 0 deletions src/core/types/workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export interface WorkspaceAttribute {
id: string;
name: string;
description?: string;
features?: string[];
color?: string;
icon?: string;
defaultVISTheme?: string;
}
6 changes: 6 additions & 0 deletions src/core/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const WORKSPACE_TYPE = 'workspace';
1 change: 1 addition & 0 deletions src/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export {
IContextProvider,
} from './context';
export { DEFAULT_APP_CATEGORIES } from './default_app_categories';
export { WORKSPACE_TYPE } from './constants';
9 changes: 9 additions & 0 deletions src/plugins/workspace/opensearch_dashboards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "workspace",
"version": "opensearchDashboards",
"server": true,
"ui": true,
"requiredPlugins": [],
"optionalPlugins": [],
"requiredBundles": []
}
10 changes: 10 additions & 0 deletions src/plugins/workspace/public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { WorkspacePlugin } from './plugin';

export function plugin() {
return new WorkspacePlugin();
}
17 changes: 17 additions & 0 deletions src/plugins/workspace/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { Plugin } from '../../../core/public';

export class WorkspacePlugin implements Plugin<{}, {}, {}> {
public async setup() {
return {};
}

public start() {
return {};
}

public stop() {}
}
13 changes: 13 additions & 0 deletions src/plugins/workspace/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { PluginInitializerContext } from '../../../core/server';
import { WorkspacePlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, OpenSearch Dashboards Platform `plugin()` initializer.

export function plugin(initializerContext: PluginInitializerContext) {
return new WorkspacePlugin(initializerContext);
}
45 changes: 45 additions & 0 deletions src/plugins/workspace/server/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { PluginInitializerContext, CoreSetup, Plugin, Logger } from '../../../core/server';
import { IWorkspaceDBImpl } from './types';
import { WorkspaceClientWithSavedObject } from './workspace_client';
import { registerRoutes } from './routes';

export class WorkspacePlugin implements Plugin<{}, {}> {
private readonly logger: Logger;
private client?: IWorkspaceDBImpl;

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get('plugins', 'workspace');
}

public async setup(core: CoreSetup) {
this.logger.debug('Setting up Workspaces service');

this.client = new WorkspaceClientWithSavedObject(core);

await this.client.setup(core);

registerRoutes({
http: core.http,
logger: this.logger,
client: this.client as IWorkspaceDBImpl,
});

return {
client: this.client,
};
}

public start() {
this.logger.debug('Starting Workspace service');

return {
client: this.client as IWorkspaceDBImpl,
};
}

public stop() {}
}
181 changes: 181 additions & 0 deletions src/plugins/workspace/server/routes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { schema } from '@osd/config-schema';

import { CoreSetup, Logger } from '../../../../core/server';
import { IWorkspaceDBImpl } from '../types';

const WORKSPACES_API_BASE_URL = '/api/workspaces';

const workspaceAttributesSchema = schema.object({
description: schema.maybe(schema.string()),
name: schema.string(),
features: schema.maybe(schema.arrayOf(schema.string())),
color: schema.maybe(schema.string()),
icon: schema.maybe(schema.string()),
defaultVISTheme: schema.maybe(schema.string()),
});

export function registerRoutes({
client,
logger,
http,
}: {
client: IWorkspaceDBImpl;
logger: Logger;
http: CoreSetup['http'];
}) {
const router = http.createRouter();
router.post(
{
path: `${WORKSPACES_API_BASE_URL}/_list`,
validate: {
body: schema.object({
search: schema.maybe(schema.string()),
sortOrder: schema.maybe(schema.string()),
perPage: schema.number({ min: 0, defaultValue: 20 }),
page: schema.number({ min: 0, defaultValue: 1 }),
sortField: schema.maybe(schema.string()),
searchFields: schema.maybe(schema.arrayOf(schema.string())),
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const result = await client.list(
{
context,
request: req,
logger,
},
req.body
);
if (!result.success) {
return res.ok({ body: result });
}
return res.ok({
body: {
...result,
result: {
...result.result,
workspaces: result.result.workspaces.map((workspace) => ({
...workspace,
})),
},
},
});
})
);
router.get(
{
path: `${WORKSPACES_API_BASE_URL}/{id}`,
validate: {
params: schema.object({
id: schema.string(),
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { id } = req.params;
const result = await client.get(
{
context,
request: req,
logger,
},
id
);
if (!result.success) {
return res.ok({ body: result });
}

return res.ok({
body: {
...result,
result: {
...result.result,
},
},
});
})
);
router.post(
{
path: `${WORKSPACES_API_BASE_URL}`,
validate: {
body: schema.object({
attributes: workspaceAttributesSchema,
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { attributes } = req.body;

const result = await client.create(
{
context,
request: req,
logger,
},
{
...attributes,
}
);
return res.ok({ body: result });
})
);
router.put(
{
path: `${WORKSPACES_API_BASE_URL}/{id?}`,
validate: {
params: schema.object({
id: schema.string(),
}),
body: schema.object({
attributes: workspaceAttributesSchema,
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { id } = req.params;
const { attributes } = req.body;

const result = await client.update(
{
context,
request: req,
logger,
},
id,
{
...attributes,
}
);
return res.ok({ body: result });
})
);
router.delete(
{
path: `${WORKSPACES_API_BASE_URL}/{id?}`,
validate: {
params: schema.object({
id: schema.string(),
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { id } = req.params;

const result = await client.delete(
{
context,
request: req,
logger,
},
id
);
return res.ok({ body: result });
})
);
}
6 changes: 6 additions & 0 deletions src/plugins/workspace/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { workspace } from './workspace';
41 changes: 41 additions & 0 deletions src/plugins/workspace/server/saved_objects/workspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { SavedObjectsType, WORKSPACE_TYPE } from '../../../../core/server';

export const workspace: SavedObjectsType = {
name: WORKSPACE_TYPE,
namespaceType: 'agnostic',
hidden: false,
/**
* workspace won't appear in management page.
*/
mappings: {
dynamic: false,
properties: {
name: {
type: 'keyword',
},
description: {
type: 'text',
},
/**
* In opensearch, string[] is also mapped to text
*/
features: {
type: 'text',
},
color: {
type: 'text',
},
icon: {
type: 'text',
},
defaultVISTheme: {
type: 'text',
},
},
},
};
Loading

0 comments on commit 074d23b

Please sign in to comment.