Skip to content

Commit

Permalink
[Multiple DataSource] Integrate multiple datasource with dev tool con…
Browse files Browse the repository at this point in the history
…sole

Signed-off-by: Su <[email protected]>
  • Loading branch information
zhongnansu committed Mar 31, 2023
1 parent fd61f7a commit 638b6bf
Show file tree
Hide file tree
Showing 24 changed files with 299 additions and 85 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Use mirrors to download Node.js binaries to escape sporadic 404 errors ([#3619](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3619))
- [Multiple DataSource] Refactor dev tool console to use opensearch-js client to send requests ([#3544](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3544))
- [Data] Add geo shape filter field ([#3605](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3605))
- [Multiple DataSource] Integrate multiple datasource with dev tool console ([#3754](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3754))

### 🐛 Bug Fixes

Expand Down
4 changes: 4 additions & 0 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,10 @@ export interface AppMountParameters<HistoryLocationState = unknown> {
* ```
*/
setHeaderActionMenu: (menuMount: MountPoint | undefined) => void;
/**
* Optional datasource id to pass while mounting app
*/
dataSourceId?: string;
}

/**
Expand Down
9 changes: 7 additions & 2 deletions src/plugins/console/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"server": true,
"ui": true,
"requiredPlugins": ["devTools"],
"optionalPlugins": ["usageCollection", "home"],
"requiredBundles": ["opensearchUiShared", "opensearchDashboardsReact", "opensearchDashboardsUtils", "home"]
"optionalPlugins": ["usageCollection", "home", "dataSource"],
"requiredBundles": [
"opensearchUiShared",
"opensearchDashboardsReact",
"opensearchDashboardsUtils",
"home"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,50 @@
* under the License.
*/

import React, { useCallback, memo } from 'react';
import React, { useCallback, memo, useEffect } from 'react';
import { debounce } from 'lodash';
import { EuiProgress } from '@elastic/eui';

import { EditorContentSpinner } from '../../components';
import { Panel, PanelsContainer } from '../../../../../opensearch_dashboards_react/public';
import { Editor as EditorUI, EditorOutput } from './legacy/console_editor';
import { StorageKeys } from '../../../services';
import { useEditorReadContext, useServicesContext, useRequestReadContext } from '../../contexts';
import {
useEditorReadContext,
useServicesContext,
useRequestReadContext,
useRequestActionContext,
} from '../../contexts';

const INITIAL_PANEL_WIDTH = 50;
const PANEL_MIN_WIDTH = '100px';

interface Props {
loading: boolean;
dataSourceId?: string;
}

export const Editor = memo(({ loading }: Props) => {
export const Editor = memo(({ loading, dataSourceId }: Props) => {
const {
services: { storage },
} = useServicesContext();

const { currentTextObject } = useEditorReadContext();
const { requestInFlight } = useRequestReadContext();
const dispatch = useRequestActionContext();

const [firstPanelWidth, secondPanelWidth] = storage.get(StorageKeys.WIDTH, [
INITIAL_PANEL_WIDTH,
INITIAL_PANEL_WIDTH,
]);

useEffect(() => {
dispatch({
type: 'resetLastResult',
payload: undefined,
});
}, [dispatch, dataSourceId]);

/* eslint-disable-next-line react-hooks/exhaustive-deps */
const onPanelWidthChange = useCallback(
debounce((widths: number[]) => {
Expand All @@ -83,7 +97,7 @@ export const Editor = memo(({ loading }: Props) => {
{loading ? (
<EditorContentSpinner />
) : (
<EditorUI initialTextValue={currentTextObject.text} />
<EditorUI initialTextValue={currentTextObject.text} dataSourceId={dataSourceId} />
)}
</Panel>
<Panel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ import { ace } from '../../../../../../../opensearch_ui_shared/public';
// @ts-ignore
import { retrieveAutoCompleteInfo, clearSubscriptions } from '../../../../../lib/mappings/mappings';
import { ConsoleMenu } from '../../../../components';
import { useEditorReadContext, useServicesContext } from '../../../../contexts';
import {
useEditorReadContext,
useRequestActionContext,
useServicesContext,
} from '../../../../contexts';
import {
useSaveCurrentTextObject,
useSendCurrentRequestToOpenSearch,
Expand All @@ -53,6 +57,7 @@ const { useUIAceKeyboardMode } = ace;

export interface EditorProps {
initialTextValue: string;
dataSourceId?: string;
}

interface QueryParams {
Expand All @@ -76,15 +81,15 @@ const DEFAULT_INPUT_VALUE = `GET _search

const inputId = 'ConAppInputTextarea';

function EditorUI({ initialTextValue }: EditorProps) {
function EditorUI({ initialTextValue, dataSourceId }: EditorProps) {
const {
services: { history, notifications, settings: settingsService, opensearchHostService },
docLinkVersion,
} = useServicesContext();

const { settings } = useEditorReadContext();
const setInputEditor = useSetInputEditor();
const sendCurrentRequestToOpenSearch = useSendCurrentRequestToOpenSearch();
const sendCurrentRequestToOpenSearch = useSendCurrentRequestToOpenSearch(dataSourceId);
const saveCurrentTextObject = useSaveCurrentTextObject();

const editorRef = useRef<HTMLDivElement | null>(null);
Expand Down Expand Up @@ -197,7 +202,14 @@ function EditorUI({ initialTextValue }: EditorProps) {
editorInstanceRef.current.getCoreEditor().destroy();
}
};
}, [saveCurrentTextObject, initialTextValue, history, setInputEditor, settingsService]);
}, [
saveCurrentTextObject,
initialTextValue,
history,
setInputEditor,
settingsService,
dataSourceId,
]);

useEffect(() => {
const { current: editor } = editorInstanceRef;
Expand Down
10 changes: 7 additions & 3 deletions src/plugins/console/public/application/containers/main/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* under the License.
*/

import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { i18n } from '@osd/i18n';
import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiPageContent } from '@elastic/eui';
import { ConsoleHistory } from '../console_history';
Expand All @@ -48,7 +48,11 @@ import { useDataInit } from '../../hooks';

import { getTopNavConfig } from './get_top_nav';

export function Main() {
interface MainProps {
dataSourceId?: string;
}

export function Main({ dataSourceId }: MainProps) {
const {
services: { storage },
} = useServicesContext();
Expand Down Expand Up @@ -130,7 +134,7 @@ export function Main() {
</EuiFlexItem>
{showingHistory ? <EuiFlexItem grow={false}>{renderConsoleHistory()}</EuiFlexItem> : null}
<EuiFlexItem>
<Editor loading={!done} />
<Editor loading={!done} dataSourceId={dataSourceId} />
</EuiFlexItem>
</EuiFlexGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { BaseResponseType } from '../../../types';
export interface OpenSearchRequestArgs {
http: HttpSetup;
requests: any;
dataSourceId?: string;
}

export interface OpenSearchRequestObject {
Expand Down Expand Up @@ -101,7 +102,8 @@ export function sendRequestToOpenSearch(
args.http,
opensearchMethod,
opensearchPath,
opensearchData
opensearchData,
args.dataSourceId
);
if (reqId !== CURRENT_REQ_ID) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { track } from './track';
// @ts-ignore
import { retrieveAutoCompleteInfo } from '../../../lib/mappings/mappings';

export const useSendCurrentRequestToOpenSearch = () => {
export const useSendCurrentRequestToOpenSearch = (dataSourceId?: string) => {
const {
services: { history, settings, notifications, trackUiMetric, http },
} = useServicesContext();
Expand All @@ -64,7 +64,7 @@ export const useSendCurrentRequestToOpenSearch = () => {
// Fire and forget
setTimeout(() => track(requests, editor, trackUiMetric), 0);

const results = await sendRequestToOpenSearch({ http, requests });
const results = await sendRequestToOpenSearch({ http, requests, dataSourceId });

results.forEach(({ request: { path, method, data } }) => {
try {
Expand Down Expand Up @@ -112,5 +112,5 @@ export const useSendCurrentRequestToOpenSearch = () => {
});
}
}
}, [dispatch, settings, history, notifications, trackUiMetric, http]);
}, [dispatch, http, dataSourceId, settings, notifications.toasts, trackUiMetric, history]);
};
4 changes: 3 additions & 1 deletion src/plugins/console/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface BootDependencies {
notifications: NotificationsSetup;
usageCollection?: UsageCollectionSetup;
element: HTMLElement;
dataSourceId?: string;
}

export function renderApp({
Expand All @@ -55,6 +56,7 @@ export function renderApp({
usageCollection,
element,
http,
dataSourceId,
}: BootDependencies) {
const trackUiMetric = createUsageTracker(usageCollection);
trackUiMetric.load('opened_app');
Expand Down Expand Up @@ -88,7 +90,7 @@ export function renderApp({
>
<RequestContextProvider>
<EditorContextProvider settings={settings.toJSON()}>
<Main />
<Main dataSourceId={dataSourceId} />
</EditorContextProvider>
</RequestContextProvider>
</ServicesContextProvider>
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/console/public/application/stores/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ import { OpenSearchRequestResult } from '../hooks/use_send_current_request_to_op
export type Actions =
| { type: 'sendRequest'; payload: undefined }
| { type: 'requestSuccess'; payload: { data: OpenSearchRequestResult[] } }
| { type: 'requestFail'; payload: OpenSearchRequestResult<string> | undefined };
| { type: 'requestFail'; payload: OpenSearchRequestResult<string> | undefined }
| { type: 'resetLastResult'; payload: undefined };

export interface Store {
requestInFlight: boolean;
Expand Down Expand Up @@ -79,4 +80,11 @@ export const reducer: Reducer<Store, Actions> = (state, action) =>
draft.lastResult = { ...initialResultValue, error: action.payload };
return;
}

if (action.type === 'resetLastResult') {
draft.lastResult = initialResultValue;
return;
}

return draft;
});
4 changes: 3 additions & 1 deletion src/plugins/console/public/lib/opensearch/opensearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ export async function send(
http: HttpSetup,
method: string,
path: string,
data: any
data: any,
dataSourceId?: string
): Promise<HttpResponse> {
return await http.post<HttpResponse>('/api/console/proxy', {
query: {
path,
method,
dataSourceId,
},
body: data,
prependBasePath: true,
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/console/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
defaultMessage: 'Console',
}),
enableRouting: false,
mount: async ({ element }) => {
mount: async ({ element, dataSourceId }) => {
const [core] = await getStartServices();

const {
Expand All @@ -79,6 +79,7 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
notifications,
usageCollection,
element,
dataSourceId,
});
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { isResponseError } from '../../../../../../../core/server/opensearch/cli
import { RouteDependencies } from '../../../';

import { Body, Query } from './validation_config';
import { buildBufferedBody } from './utils';

function getProxyHeaders(req: OpenSearchDashboardsRequest) {
const headers = Object.create(null);
Expand Down Expand Up @@ -84,9 +85,10 @@ export const createHandler = ({
proxy: { readLegacyOpenSearchConfig, pathFilters, proxyConfigCollection },
}: RouteDependencies): RequestHandler<unknown, Query, Body> => async (ctx, request, response) => {
const { body, query } = request;
const { path, method } = query;
const client = ctx.core.opensearch.client.asCurrentUser;

const { path, method, dataSourceId } = query;
const client = dataSourceId
? await ctx.dataSource.opensearch.getClient(dataSourceId)
: ctx.core.opensearch.client.asCurrentUser;
let opensearchResponse: ApiResponse;

if (!pathFilters.some((re) => re.test(path))) {
Expand All @@ -99,12 +101,16 @@ export const createHandler = ({
}

try {
const requestHeaders = {
...getProxyHeaders(request),
};

// TODO: proxy header will fail sigv4 auth type in data source, need create issue in opensearch-js repo to track
const requestHeaders = dataSourceId
? {}
: {
...getProxyHeaders(request),
};

const bufferedBody = await buildBufferedBody(body);
opensearchResponse = await client.transport.request(
{ path: toUrlPath(path), method, body },
{ path: toUrlPath(path), method, body: bufferedBody },
{ headers: requestHeaders }
);

Expand All @@ -130,7 +136,7 @@ export const createHandler = ({
});
} catch (e: any) {
const isResponseErrorFlag = isResponseError(e);

if (!isResponseError) log.error(e);
const errorMessage = isResponseErrorFlag ? JSON.stringify(e.meta.body) : e.message;
// core http route handler has special logic that asks for stream readable input to pass error opaquely
const errorResponseBody = new Readable({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* under the License.
*/

import { getProxyRouteHandlerDeps } from './mocks';
import { buildBufferedBodyMock, getProxyRouteHandlerDeps } from './mocks';

import expect from '@osd/expect';

Expand All @@ -47,7 +47,6 @@ describe('Console Proxy Route', () => {
beforeEach(() => {
request = (method: string, path: string, response: string) => {
const mockResponse = opensearchServiceMock.createSuccessTransportRequestPromise(response);

const requestHandlerContextMock = coreMock.createRequestHandlerContext();
opensearchClient = requestHandlerContextMock.opensearch.client;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ jest.mock('../../../../../lib/proxy_request', () => ({
proxyRequest: jest.fn(),
}));

export const buildBufferedBodyMock = jest.fn();
jest.doMock('../utils.ts', () => ({
buildBufferedBody: buildBufferedBodyMock,
}));

import { duration } from 'moment';
import { ProxyConfigCollection } from '../../../../../lib';
import { RouteDependencies, ProxyDependencies } from '../../../../../routes';
Expand Down
Loading

0 comments on commit 638b6bf

Please sign in to comment.