diff --git a/changelogs/fragments/10798.yml b/changelogs/fragments/10798.yml new file mode 100644 index 000000000000..1156903b8bb0 --- /dev/null +++ b/changelogs/fragments/10798.yml @@ -0,0 +1,2 @@ +infra: +- Supply data source version to Datasets ([#10798](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/10798)) \ No newline at end of file diff --git a/src/plugins/data/common/data_views/data_views/data_view.ts b/src/plugins/data/common/data_views/data_views/data_view.ts index 004c21cfa12a..a36df74a674a 100644 --- a/src/plugins/data/common/data_views/data_views/data_view.ts +++ b/src/plugins/data/common/data_views/data_views/data_view.ts @@ -77,6 +77,7 @@ export class DataView extends IndexPattern implements IDataView { this.dataSourceRef = { id: this.dataSourceRef.id, type: attributes.dataSourceEngineType || this.dataSourceRef.type, + version: attributes.dataSourceVersion || this.dataSourceRef.version, name: attributes.title || this.dataSourceRef.name || this.dataSourceRef.id, }; } catch (error) { @@ -115,6 +116,7 @@ export class DataView extends IndexPattern implements IDataView { id: dataSourceReference.id, title: attributes.title || dataSourceReference.id, type: attributes.dataSourceEngineType || 'OpenSearch', + version: attributes.dataSourceVersion || '', }; } catch (error) { // If we can't fetch the data source, create a minimal version @@ -125,6 +127,7 @@ export class DataView extends IndexPattern implements IDataView { ? dataSourceReference.name : dataSourceReference.id, type: 'OpenSearch', + version: '', }; } } diff --git a/src/plugins/data/common/datasets/types.ts b/src/plugins/data/common/datasets/types.ts index 1474eae4e68e..de2c22f30d03 100644 --- a/src/plugins/data/common/datasets/types.ts +++ b/src/plugins/data/common/datasets/types.ts @@ -16,6 +16,8 @@ export interface DataSource { title: string; /** The engine type of the data source */ type: string; + /** Version of the data source */ + version: string; /** Optional metadata for the data source */ meta?: DataSourceMeta; } diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 72aa6ad0f31f..663abfe61b00 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -213,6 +213,7 @@ export interface SavedObjectReference { name?: string; id: string; type: string; + version: string; } export interface IndexPatternSpec { id?: string; diff --git a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts index b2e2e088dc56..d78ba33bd18f 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts @@ -120,6 +120,7 @@ export class DatasetService { id: dataset.dataSource.id!, name: dataset.dataSource.title, type: dataset.dataSource.type, + version: dataset.dataSource.version, } : undefined, } as IndexPatternSpec; @@ -201,6 +202,7 @@ export class DatasetService { id: dataset.dataSource.id!, name: dataset.dataSource.title, type: dataset.dataSource.type, + version: dataset.dataSource.version, } : undefined, } as IndexPatternSpec; diff --git a/src/plugins/explore/public/components/chart/utils/breakdown_utils.test.ts b/src/plugins/explore/public/components/chart/utils/breakdown_utils.test.ts index 3fee3647c6a2..5feb9cdeb77f 100644 --- a/src/plugins/explore/public/components/chart/utils/breakdown_utils.test.ts +++ b/src/plugins/explore/public/components/chart/utils/breakdown_utils.test.ts @@ -11,7 +11,13 @@ describe('shouldShowBreakdownSelector', () => { timeFieldName: '@timestamp', } as DataView; - it('should return false when dataView is undefined', () => { + const mockServices = { + uiSettings: { + get: jest.fn().mockReturnValue(true), + }, + }; + + it('should return false when dataset is undefined', () => { expect(shouldShowBreakdownSelector(undefined)).toBe(false); }); @@ -20,22 +26,174 @@ describe('shouldShowBreakdownSelector', () => { }); it('should return false when experimental setting is disabled', () => { - const mockServices = { + const mockDisabledServices = { uiSettings: { get: jest.fn().mockReturnValue(false), }, }; + expect(shouldShowBreakdownSelector(mockDataView, mockDisabledServices)).toBe(false); + }); - expect(shouldShowBreakdownSelector(mockDataView, mockServices)).toBe(false); + it('should return true when dataSourceRef does not exist (default behavior)', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + } as DataView, + mockServices + ) + ).toBe(true); }); - it('should return true when dataView exists and experimental setting is enabled', () => { - const mockServices = { - uiSettings: { - get: jest.fn().mockReturnValue(true), - }, - }; + it('should return true when dataSourceRef exists but type is missing', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + version: '3.3.0', + }, + } as any, + mockServices + ) + ).toBe(true); + }); + + it('should return true when dataSourceRef exists but version is missing', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + }, + } as any, + mockServices + ) + ).toBe(true); + }); + + it('should return true for OpenSearch version 3.3.0', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '3.3.0', + }, + } as any, + mockServices + ) + ).toBe(true); + }); + + it('should return true for OpenSearch version greater than 3.3.0', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '3.4.0', + }, + } as any, + mockServices + ) + ).toBe(true); + + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '4.0.0', + }, + } as any, + mockServices + ) + ).toBe(true); + }); + + it('should return false for OpenSearch version less than 3.3.0', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '3.2.0', + }, + } as any, + mockServices + ) + ).toBe(false); + + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '2.5.0', + }, + } as any, + mockServices + ) + ).toBe(false); + }); + + it('should return false for non-OpenSearch data sources', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'S3', + version: '8.0.0', + }, + } as any, + mockServices + ) + ).toBe(false); + }); + + it('should handle version strings without patch version', () => { + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '3.3', + }, + } as any, + mockServices + ) + ).toBe(true); - expect(shouldShowBreakdownSelector(mockDataView, mockServices)).toBe(true); + expect( + shouldShowBreakdownSelector( + { + timeFieldName: '@timestamp', + dataSourceRef: { + id: 'test-id', + type: 'OpenSearch', + version: '3.2', + }, + } as any, + mockServices + ) + ).toBe(false); }); }); diff --git a/src/plugins/explore/public/components/chart/utils/breakdown_utils.ts b/src/plugins/explore/public/components/chart/utils/breakdown_utils.ts index ae6339225a29..724f99a0f00d 100644 --- a/src/plugins/explore/public/components/chart/utils/breakdown_utils.ts +++ b/src/plugins/explore/public/components/chart/utils/breakdown_utils.ts @@ -3,21 +3,22 @@ * SPDX-License-Identifier: Apache-2.0 */ +import semver from 'semver'; import { DataView } from '../../../../../data/common'; import { ENABLE_EXPERIMENTAL_SETTING } from '../../../../common'; /** * Determines whether the breakdown selector should be shown. * - * @param dataView - The current data view + * @param dataset - The current data view * @param services - Services object containing uiSettings * @returns true if breakdown selector should be shown, false otherwise */ export const shouldShowBreakdownSelector = ( - dataView: DataView | undefined, + dataset: DataView | undefined, services?: any ): boolean => { - if (!dataView) { + if (!dataset) { return false; } @@ -27,5 +28,21 @@ export const shouldShowBreakdownSelector = ( return false; } - return true; + // Check for dataSourceRef - if it doesn't exist, default to true (show) + const dataSourceRef = (dataset as any).dataSourceRef; + if (!dataSourceRef) { + return true; + } + + // If type or version is missing, default to true (show) + if (!dataSourceRef.type || !dataSourceRef.version) { + return true; + } + + // Check if it's OpenSearch and version is 3.3 or greater + const isOpenSearch = dataSourceRef.type === 'OpenSearch'; + const isCompatibleVersion = semver.gte(semver.coerce(dataSourceRef.version) || '0.0.0', '3.3.0'); + + // Show breakdown selector only if it's OpenSearch 3.3+ + return isOpenSearch && isCompatibleVersion; };