diff --git a/opensearch_dashboards.json b/opensearch_dashboards.json index 5c9b4c398..43a57319c 100644 --- a/opensearch_dashboards.json +++ b/opensearch_dashboards.json @@ -15,5 +15,7 @@ "dataSourceManagement" ], "server": true, - "ui": true + "ui": true, + "supportedOSDataSourceVersions": ">=1.0.0", + "requiredOSDataSourcePlugins": ["opensearch-security"] } \ No newline at end of file diff --git a/package.json b/package.json index f1d9e3bf8..196879818 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "@hapi/wreck": "^17.1.0", "html-entities": "1.3.1", "proxy-agent": "^6.4.0", - "zxcvbn": "^4.4.2" + "zxcvbn": "^4.4.2", + "semver": "^7.5.3" }, "resolutions": { "selenium-webdriver": "4.10.0", @@ -55,4 +56,4 @@ "express": "^4.19.2", "braces": "^3.0.3" } -} \ No newline at end of file +} diff --git a/public/apps/configuration/top-nav-menu.tsx b/public/apps/configuration/top-nav-menu.tsx index 20197d69a..8eca6df4b 100644 --- a/public/apps/configuration/top-nav-menu.tsx +++ b/public/apps/configuration/top-nav-menu.tsx @@ -20,6 +20,7 @@ import { AppDependencies } from '../types'; import { setDataSourceInUrl, setDataSource as setDataSourceInSubscription, + isDataSourceCompatible, } from '../../utils/datasource-utils'; export interface TopNavMenuProps extends AppDependencies { @@ -63,6 +64,7 @@ export const SecurityPluginTopNavMenu = React.memo( : undefined, onSelectedDataSources: wrapSetDataSourceWithUpdateUrl, fullWidth: true, + dataSourceFilter: isDataSourceCompatible, }} /> ) : null; diff --git a/public/utils/datasource-utils.ts b/public/utils/datasource-utils.ts index 508a72a78..0cc673bab 100644 --- a/public/utils/datasource-utils.ts +++ b/public/utils/datasource-utils.ts @@ -12,9 +12,12 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - +import semver from 'semver'; import { BehaviorSubject } from 'rxjs'; import { DataSourceOption } from 'src/plugins/data_source_management/public/components/data_source_menu/types'; +import pluginManifest from '../../opensearch_dashboards.json'; +import type { SavedObject } from '../../../../src/core/public'; +import type { DataSourceAttributes } from '../../../../src/plugins/data_source/common/data_sources'; const DATASOURCEURLKEY = 'dataSource'; @@ -55,3 +58,26 @@ export const dataSource$ = new BehaviorSubject( export function setDataSource(dataSource: DataSourceOption) { dataSource$.next(dataSource); } + +export const isDataSourceCompatible = (dataSource: SavedObject) => { + if ( + 'requiredOSDataSourcePlugins' in pluginManifest && + !pluginManifest.requiredOSDataSourcePlugins.every((plugin) => + dataSource.attributes.installedPlugins?.includes(plugin) + ) + ) { + return false; + } + + // filter out data sources which is NOT in the support range of plugin + if ( + 'supportedOSDataSourceVersions' in pluginManifest && + !semver.satisfies( + dataSource.attributes.dataSourceVersion, + pluginManifest.supportedOSDataSourceVersions + ) + ) { + return false; + } + return true; +}; diff --git a/public/utils/test/datasource-utils.test.ts b/public/utils/test/datasource-utils.test.ts index 33aef7905..c6f58fc1b 100644 --- a/public/utils/test/datasource-utils.test.ts +++ b/public/utils/test/datasource-utils.test.ts @@ -13,7 +13,12 @@ * permissions and limitations under the License. */ -import { getClusterInfo, getDataSourceFromUrl, setDataSourceInUrl } from '../datasource-utils'; +import { + getClusterInfo, + getDataSourceFromUrl, + setDataSourceInUrl, + isDataSourceCompatible, +} from '../datasource-utils'; describe('Tests datasource utils', () => { it('Tests the GetClusterDescription helper function', () => { @@ -78,4 +83,130 @@ describe('Tests datasource utils', () => { }); expect(getDataSourceFromUrl()).toEqual({}); }); + + describe('isDataSourceCompatible', () => { + it('should return true for compatible data sources', () => { + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: ['opensearch-security'], + dataSourceVersion: '2.9.0', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(true); + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: ['opensearch-security'], + dataSourceVersion: '2.11.0', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(true); + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: ['opensearch-security'], + dataSourceVersion: '2.13.0', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(true); + }); + + it('should return false for un-compatible data sources', () => { + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: [], + dataSourceVersion: '2.13.0', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(false); + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: ['opensearch-ml'], + dataSourceVersion: '2.13.0', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(false); + expect( + isDataSourceCompatible({ + attributes: { + title: '', + endpoint: '', + dataSourceVersion: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(false); + expect( + isDataSourceCompatible({ + attributes: { + installedPlugins: ['opensearch-security'], + dataSourceVersion: '1.0.0-beta1', + title: '', + endpoint: '', + auth: { + type: '', + credentials: undefined, + }, + }, + id: '', + type: '', + references: [], + }) + ).toBe(false); + }); + }); }); diff --git a/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js b/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js index f850c6572..8b979838f 100644 --- a/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js +++ b/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js @@ -24,6 +24,8 @@ const createDataSource = () => { attributes: { title: Cypress.env('externalDataSourceLabel'), endpoint: Cypress.env('externalDataSourceEndpoint'), + installedPlugins: ['opensearch-security'], + dataSourceVersion: '2.15.0', auth: { type: 'username_password', credentials: {