Skip to content

Commit

Permalink
Merge branch 'main' into fix/table-vis-filter-split-table
Browse files Browse the repository at this point in the history
Signed-off-by: Ashwin P Chandran <ashwinpc@amazon.com>
  • Loading branch information
ashwin-pc authored Feb 6, 2024
2 parents 78b4515 + bbd40e1 commit 0e0f08c
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [CVE-2023-45133] Bump all babel dependencies from `7.16.x` to `7.22.9` to fix upstream vulnerability ([#5428](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5428))
- [CVE-2023-45857] Bump `axios` from `0.27.2` to `1.6.1` ([#5470](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5470))
- [CVE-2023-26159] Bump `follow-redirects` from `1.15.2` to `1.15.4` ([#5669](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5669))
- [CVE-2023-52079] Bump `msgpackr` from `1.9.7` to `1.10.1` ([#5803](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5803))
- [CVE-2020-8203] Bump `cheerio` from `0.22.0` to `1.0.0-rc.1` to fix vulnerable `lodash` dependency ([#5797](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5797))

### 📈 Features/Enhancements
Expand Down Expand Up @@ -56,6 +57,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [BUG] Remove duplicate sample data as id 90943e30-9a47-11e8-b64d-95841ca0b247 ([5668](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5668))
- [BUG][Multiple Datasource] Fix datasource testing connection unexpectedly passed with wrong endpoint [#5663](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5663)
- [Table Visualization] Fix filter action buttons for split table aggregations ([#5619](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5619))
- [BUG][Multiple Datasource] Datasource id is required if multiple datasource is enabled and no default cluster supported [#5751](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5751)

### 🚞 Infrastructure

Expand Down
2 changes: 2 additions & 0 deletions config/opensearch_dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@

# Set the value of this setting to true to enable multiple data source feature.
#data_source.enabled: false
# Set the value of this setting to false to disable default cluster in data source feature.
#data_source.defaultCluster: true
# Set the value of these settings to customize crypto materials to encryption saved credentials
# in data sources.
#data_source.encryption.wrappingKeyName: 'changeme'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import { IOpenSearchSearchRequest } from '..';
export const decideClient = async (
context: RequestHandlerContext,
request: IOpenSearchSearchRequest,
withDataSourceEnabled: boolean = false,
withLongNumeralsSupport: boolean = false
): Promise<OpenSearchClient> => {
// if data source feature is disabled, return default opensearch client of current user
const client =
request.dataSourceId && context.dataSource
? await context.dataSource.opensearch.getClient(request.dataSourceId)
: withLongNumeralsSupport
? context.core.opensearch.client.asCurrentUserWithLongNumeralsSupport
: context.core.opensearch.client.asCurrentUser;
return client;
const defaultOpenSearchClient = withLongNumeralsSupport
? context.core.opensearch.client.asCurrentUserWithLongNumeralsSupport
: context.core.opensearch.client.asCurrentUser;

return withDataSourceEnabled && request.dataSourceId && context.dataSource
? await context.dataSource.opensearch.getClient(request.dataSourceId)
: defaultOpenSearchClient;
};
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,22 @@
import { RequestHandlerContext } from '../../../../../core/server';
import { pluginInitializerContextConfigMock } from '../../../../../core/server/mocks';
import { opensearchSearchStrategyProvider } from './opensearch_search_strategy';
import { DataSourceError } from '../../../../data_source/server/lib/error';
import { DataSourcePluginSetup } from '../../../../data_source/server';
import { SearchUsage } from '../collectors';

describe('OpenSearch search strategy', () => {
const mockLogger: any = {
debug: () => {},
};
const mockSearchUsage: SearchUsage = {
trackError(): Promise<void> {
return Promise.resolve(undefined);
},
trackSuccess(duration: number): Promise<void> {
return Promise.resolve(undefined);
},
};
const body = {
body: {
_shards: {
Expand Down Expand Up @@ -129,8 +140,21 @@ describe('OpenSearch search strategy', () => {
expect(response).toHaveProperty('rawResponse');
});

it('dataSource enabled, send request with dataSourceId get data source client', async () => {
const opensearchSearch = await opensearchSearchStrategyProvider(mockConfig$, mockLogger);
it('dataSource enabled and default cluster disabled, send request with dataSourceId get data source client', async () => {
const mockDataSourcePluginSetupWithDataSourceEnabled: DataSourcePluginSetup = {
createDataSourceError(err: any): DataSourceError {
return new DataSourceError({});
},
dataSourceEnabled: jest.fn(() => true),
defaultClusterEnabled: jest.fn(() => false),
};

const opensearchSearch = await opensearchSearchStrategyProvider(
mockConfig$,
mockLogger,
mockSearchUsage,
mockDataSourcePluginSetupWithDataSourceEnabled
);

await opensearchSearch.search(
(mockDataSourceEnabledContext as unknown) as RequestHandlerContext,
Expand All @@ -142,6 +166,35 @@ describe('OpenSearch search strategy', () => {
expect(mockOpenSearchApiCaller).not.toBeCalled();
});

it('dataSource enabled and default cluster disabled, send request with empty dataSourceId should throw exception', async () => {
const mockDataSourcePluginSetupWithDataSourceEnabled: DataSourcePluginSetup = {
createDataSourceError(err: any): DataSourceError {
return new DataSourceError({});
},
dataSourceEnabled: jest.fn(() => true),
defaultClusterEnabled: jest.fn(() => false),
};

try {
const opensearchSearch = opensearchSearchStrategyProvider(
mockConfig$,
mockLogger,
mockSearchUsage,
mockDataSourcePluginSetupWithDataSourceEnabled
);

await opensearchSearch.search(
(mockDataSourceEnabledContext as unknown) as RequestHandlerContext,
{
dataSourceId: '',
}
);
} catch (e) {
expect(e).toBeTruthy();
expect(e).toBeInstanceOf(DataSourceError);
}
});

it('dataSource disabled, send request with dataSourceId get default client', async () => {
const opensearchSearch = await opensearchSearchStrategyProvider(mockConfig$, mockLogger);

Expand All @@ -152,8 +205,47 @@ describe('OpenSearch search strategy', () => {
expect(mockDataSourceApiCaller).not.toBeCalled();
});

it('dataSource enabled, send request without dataSourceId get default client', async () => {
const opensearchSearch = await opensearchSearchStrategyProvider(mockConfig$, mockLogger);
it('dataSource enabled and default cluster enabled, send request with dataSourceId get datasource client', async () => {
const mockDataSourcePluginSetupWithDataSourceEnabled: DataSourcePluginSetup = {
createDataSourceError(err: any): DataSourceError {
return new DataSourceError({});
},
dataSourceEnabled: jest.fn(() => true),
defaultClusterEnabled: jest.fn(() => true),
};

const opensearchSearch = await opensearchSearchStrategyProvider(
mockConfig$,
mockLogger,
mockSearchUsage,
mockDataSourcePluginSetupWithDataSourceEnabled
);

await opensearchSearch.search(
(mockDataSourceEnabledContext as unknown) as RequestHandlerContext,
{
dataSourceId,
}
);
expect(mockDataSourceApiCaller).toBeCalled();
expect(mockOpenSearchApiCaller).not.toBeCalled();
});

it('dataSource enabled and default cluster enabled, send request without dataSourceId get default client', async () => {
const mockDataSourcePluginSetupWithDataSourceEnabled: DataSourcePluginSetup = {
createDataSourceError(err: any): DataSourceError {
return new DataSourceError({});
},
dataSourceEnabled: jest.fn(() => true),
defaultClusterEnabled: jest.fn(() => true),
};

const opensearchSearch = await opensearchSearchStrategyProvider(
mockConfig$,
mockLogger,
mockSearchUsage,
mockDataSourcePluginSetupWithDataSourceEnabled
);

await opensearchSearch.search((mockContext as unknown) as RequestHandlerContext, {});
expect(mockOpenSearchApiCaller).toBeCalled();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,20 @@ export const opensearchSearchStrategyProvider = (
});

try {
const client = await decideClient(context, request, withLongNumeralsSupport);
if (
dataSource?.dataSourceEnabled() &&
!dataSource?.defaultClusterEnabled() &&
!request.dataSourceId
) {
throw new Error(`Data source id is required when no openseach hosts config provided`);
}

const client = await decideClient(
context,
request,
dataSource?.dataSourceEnabled(),
withLongNumeralsSupport
);
const promise = shimAbortSignal(client.search(params), options?.abortSignal);

const { body: rawResponse } = (await promise) as ApiResponse<SearchResponse<any>>;
Expand All @@ -92,7 +105,7 @@ export const opensearchSearchStrategyProvider = (
} catch (e) {
if (usage) usage.trackError();

if (dataSource && request.dataSourceId) {
if (dataSource?.dataSourceEnabled()) {
throw dataSource.createDataSourceError(e);
}
throw e;
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data_source/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const WRAPPING_KEY_SIZE: number = 32;

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: false }),
defaultCluster: schema.boolean({ defaultValue: false }),
encryption: schema.object({
wrappingKeyName: schema.string({
minLength: KEY_NAME_MIN_LENGTH,
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/data_source/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ export class DataSourcePlugin implements Plugin<DataSourcePluginSetup, DataSourc

return {
createDataSourceError: (e: any) => createDataSourceError(e),
dataSourceEnabled: () => config.enabled,
defaultClusterEnabled: () => config.defaultCluster,
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/plugins/data_source/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ declare module 'src/core/server' {

export interface DataSourcePluginSetup {
createDataSourceError: (err: any) => DataSourceError;
dataSourceEnabled: () => boolean;
defaultClusterEnabled: () => boolean;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataSourcePluginStart {}
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13035,9 +13035,9 @@ msgpackr-extract@^3.0.2:
"@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2"

msgpackr@^1.9.5:
version "1.9.7"
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.9.7.tgz#8f13c06d7a22946a6d8351804ce39a6a9e74ca83"
integrity sha512-baUNaLvKQvVhzfWTNO07njwbZK1Lxjtb0P1JL6/EhXdLTHzR57/mZqqJC39TtQKvOmkJA4pcejS4dbk7BDgLLA==
version "1.10.1"
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555"
integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==
optionalDependencies:
msgpackr-extract "^3.0.2"

Expand Down

0 comments on commit 0e0f08c

Please sign in to comment.