From 0d330dad7b9212520ad4d019b798041cedf8e1e9 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Fri, 28 Feb 2025 12:40:10 -0800 Subject: [PATCH 1/5] Block simulate on ingest if version not foundg Signed-off-by: Tyler Ohlsen --- .../workflow_inputs/workflow_inputs.tsx | 10 +++- public/utils/utils.tsx | 58 +++++++++++++------ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx index 35252a21..16be17e2 100644 --- a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx @@ -60,6 +60,7 @@ import { sleep, useDataSourceVersion, getIsPreV219, + useMissingDataSourceVersion, } from '../../../utils'; import { BooleanField } from './input_fields'; import '../workspace/workspace-styles.scss'; @@ -104,6 +105,10 @@ export function WorkflowInputs(props: WorkflowInputsProps) { const dataSourceId = getDataSourceId(); const dataSourceVersion = useDataSourceVersion(dataSourceId); const isPreV219 = getIsPreV219(dataSourceVersion); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); // transient running states const [isUpdatingSearchPipeline, setIsUpdatingSearchPipeline] = useState< @@ -610,7 +615,10 @@ export function WorkflowInputs(props: WorkflowInputsProps) { if ( !isEmpty(values?.ingest?.enrich) && values?.ingest?.pipelineName !== undefined && - values?.ingest?.pipelineName !== '' + values?.ingest?.pipelineName !== '' && + // if the data source version is missing/undefined, we cannot + // guarantee that the simulate API will be available + !missingDataSourceVersion ) { const curDocs = prepareDocsForSimulate( values?.ingest?.docs, diff --git a/public/utils/utils.tsx b/public/utils/utils.tsx index 30613db8..c1df2603 100644 --- a/public/utils/utils.tsx +++ b/public/utils/utils.tsx @@ -160,27 +160,38 @@ export function isValidWorkflow(workflowObj: any): boolean { // Determines if a file used for import workflow is compatible with the current data source version. export async function isCompatibleWorkflow( - workflowObj: any, + workflowObj: any, dataSourceId?: string | undefined ): Promise { const compatibility = workflowObj?.version?.compatibility; // Default to true when compatibility cannot be assessed (empty/invalid compatibility array or MDS disabled.) - if (!Array.isArray(compatibility) || compatibility.length === 0 || dataSourceId === undefined) { + if ( + !Array.isArray(compatibility) || + compatibility.length === 0 || + dataSourceId === undefined + ) { return true; } - const dataSourceVersion = await getEffectiveVersion(dataSourceId); - const [effectiveMajorVersion, effectiveMinorVersion] = dataSourceVersion.split('.').map(Number); - + const dataSourceVersion = await getEffectiveVersion(dataSourceId); + const [ + effectiveMajorVersion, + effectiveMinorVersion, + ] = dataSourceVersion.split('.').map(Number); + // Checks if any version in compatibility array matches the current dataSourceVersion (major.minor) - return compatibility.some(compatibleVersion => { - const [compatibleMajor, compatibleMinor] = compatibleVersion.split('.').map(Number); - return effectiveMajorVersion === compatibleMajor && effectiveMinorVersion === compatibleMinor; + return compatibility.some((compatibleVersion) => { + const [compatibleMajor, compatibleMinor] = compatibleVersion + .split('.') + .map(Number); + return ( + effectiveMajorVersion === compatibleMajor && + effectiveMinorVersion === compatibleMinor + ); }); } - export function isValidUiWorkflow(workflowObj: any): boolean { return ( isValidWorkflow(workflowObj) && @@ -933,13 +944,13 @@ export function getFieldValue(jsonObj: {}, fieldName: string): any | undefined { return undefined; } -// Get the version from the selected data source +// Get the version from the selected data source, if found export const getEffectiveVersion = async ( dataSourceId: string | undefined -): Promise => { +): Promise => { try { if (dataSourceId === undefined) { - throw new Error('Data source is required'); + throw new Error(); } if (dataSourceId === '') { @@ -951,16 +962,26 @@ export const getEffectiveVersion = async ( 'data-source', dataSourceId ); - const version = - dataSource?.attributes?.dataSourceVersion || MIN_SUPPORTED_VERSION; - return version; + return dataSource?.attributes?.dataSourceVersion; } catch (error) { - console.error('Error getting version:', error); - return MIN_SUPPORTED_VERSION; + console.error('Error getting version: ', error); + return undefined; } }; - +export function useMissingDataSourceVersion( + dataSourceId: string | undefined, + dataSourceVersion: string | undefined +): boolean { + const [missingVersion, setMissingVersion] = useState(false); + useEffect(() => { + setMissingVersion( + dataSourceId !== undefined && dataSourceVersion === undefined + ); + }, [dataSourceId, dataSourceVersion]); + return missingVersion; +} + /** * Formats version string to show only major.minor numbers * Example: "3.0.0-alpha1" -> "3.0" @@ -970,4 +991,3 @@ export function formatDisplayVersion(version: string): string { const [major, minor] = version.split('.'); return `${major}.${minor}`; } - From 7f8d7fd5857ab25c45f93ea29b50777e2452d21b Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 3 Mar 2025 10:18:01 -0800 Subject: [PATCH 2/5] more cleanup after rebase Signed-off-by: Tyler Ohlsen --- .../import_workflow/import_workflow_modal.tsx | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/public/pages/workflows/import_workflow/import_workflow_modal.tsx b/public/pages/workflows/import_workflow/import_workflow_modal.tsx index 8fcef547..d6e11b04 100644 --- a/public/pages/workflows/import_workflow/import_workflow_modal.tsx +++ b/public/pages/workflows/import_workflow/import_workflow_modal.tsx @@ -44,7 +44,11 @@ import { WORKFLOW_NAME_RESTRICTIONS, } from '../../../../common'; import { WORKFLOWS_TAB } from '../workflows'; -import { getDataSourceId, getEffectiveVersion, formatDisplayVersion } from '../../../utils/utils'; +import { + getDataSourceId, + formatDisplayVersion, + useDataSourceVersion, +} from '../../../utils/utils'; interface ImportWorkflowModalProps { isImportModalOpen: boolean; @@ -62,17 +66,7 @@ interface ImportWorkflowModalProps { export function ImportWorkflowModal(props: ImportWorkflowModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); - const [dataSourceVersion, setDataSourceVersion] = useState< - string | undefined - >(undefined); - useEffect(() => { - async function getVersion() { - if (dataSourceId !== undefined) { - setDataSourceVersion(await getEffectiveVersion(dataSourceId)); - } - } - getVersion(); - }, [dataSourceId]); + const dataSourceVersion = useDataSourceVersion(dataSourceId); const { workflows } = useSelector((state: AppState) => state.workflows); // workflow name state @@ -171,7 +165,9 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) { <> From 9c3922941e36ff0c9387c21f921dba7b2e65512f Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 3 Mar 2025 11:04:20 -0800 Subject: [PATCH 3/5] Add checks in all modals Signed-off-by: Tyler Ohlsen --- .../modals/configure_expression_modal.tsx | 9 +++++++++ .../modals/configure_multi_expression_modal.tsx | 9 +++++++++ .../modals/configure_template_modal.tsx | 9 +++++++++ .../workflows/new_workflow/quick_configure_modal.tsx | 6 +++--- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx index 45f0385d..6561e9e5 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx @@ -53,6 +53,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -94,6 +96,11 @@ const MAX_INPUT_DOCS = 10; export function ConfigureExpressionModal(props: ConfigureExpressionModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -407,6 +414,8 @@ export function ConfigureExpressionModal(props: ConfigureExpressionModalProps) { style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx index 3d3116fe..45b336a4 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx @@ -51,6 +51,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -91,6 +93,11 @@ export function ConfigureMultiExpressionModal( ) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -433,6 +440,8 @@ export function ConfigureMultiExpressionModal( style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx index f12c9eda..680cfb37 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx @@ -57,6 +57,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -102,6 +104,11 @@ const PROMPT_EDITOR_ID = 'promptEditor'; export function ConfigureTemplateModal(props: ConfigureTemplateModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -638,6 +645,8 @@ export function ConfigureTemplateModal(props: ConfigureTemplateModalProps) { style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflows/new_workflow/quick_configure_modal.tsx b/public/pages/workflows/new_workflow/quick_configure_modal.tsx index 1f158742..9515f415 100644 --- a/public/pages/workflows/new_workflow/quick_configure_modal.tsx +++ b/public/pages/workflows/new_workflow/quick_configure_modal.tsx @@ -260,7 +260,7 @@ export function QuickConfigureModal(props: QuickConfigureModalProps) { Date: Mon, 3 Mar 2025 11:19:25 -0800 Subject: [PATCH 4/5] Set defaults for calls of getEffectiveVesion Signed-off-by: Tyler Ohlsen --- .../workflow_detail/workflow_inputs/processors_list.tsx | 2 +- .../workflow_inputs/search_inputs/search_inputs.tsx | 6 ++++-- public/pages/workflows/new_workflow/new_workflow.tsx | 6 ++++-- public/utils/utils.tsx | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx index 4668d28d..2109b776 100644 --- a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx @@ -122,7 +122,7 @@ export function ProcessorsList(props: ProcessorsListProps) { if (dataSourceId !== undefined) { getEffectiveVersion(dataSourceId) .then((ver) => { - setVersion(ver); + setVersion(ver || MIN_SUPPORTED_VERSION); }) .catch(console.error); } diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx index 8f529b0b..2582655e 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx @@ -11,6 +11,7 @@ import { EnrichSearchRequest } from './enrich_search_request'; import { EnrichSearchResponse } from './enrich_search_response'; import { CachedFormikState, + MIN_SUPPORTED_VERSION, OMIT_SYSTEM_INDEX_PATTERN, WorkflowConfig, } from '../../../../../common'; @@ -42,10 +43,11 @@ export function SearchInputs(props: SearchInputsProps) { const checkVersion = async () => { try { if (dataSourceId !== undefined) { - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; setShowTransformQuery(semver.gte(version, '2.19.0')); } else { - setShowTransformQuery(true); + setShowTransformQuery(true); } } catch (error) { console.error('Error checking version:', error); diff --git a/public/pages/workflows/new_workflow/new_workflow.tsx b/public/pages/workflows/new_workflow/new_workflow.tsx index cf5fb25b..13aeacd8 100644 --- a/public/pages/workflows/new_workflow/new_workflow.tsx +++ b/public/pages/workflows/new_workflow/new_workflow.tsx @@ -64,7 +64,8 @@ const filterPresetsByVersion = async ( WORKFLOW_TYPE.CUSTOM, ]; - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; if (semver.lt(version, MIN_SUPPORTED_VERSION)) { return []; @@ -159,7 +160,8 @@ export function NewWorkflow(props: NewWorkflowProps) { return; } - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; const enrichedWorkflows = presetWorkflows.map((presetWorkflow) => enrichPresetWorkflowWithUiMetadata(presetWorkflow, version) diff --git a/public/utils/utils.tsx b/public/utils/utils.tsx index c1df2603..fbca81b2 100644 --- a/public/utils/utils.tsx +++ b/public/utils/utils.tsx @@ -174,7 +174,8 @@ export async function isCompatibleWorkflow( return true; } - const dataSourceVersion = await getEffectiveVersion(dataSourceId); + const dataSourceVersion = + (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; const [ effectiveMajorVersion, effectiveMinorVersion, From f75d3975d9f76e6cd18f1645be4b8124c84a26c6 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 3 Mar 2025 11:26:36 -0800 Subject: [PATCH 5/5] rename fn Signed-off-by: Tyler Ohlsen --- .../workflow_detail/workflow_inputs/processors_list.tsx | 4 ++-- .../workflow_inputs/search_inputs/search_inputs.tsx | 4 ++-- public/pages/workflows/new_workflow/new_workflow.tsx | 6 +++--- public/utils/utils.tsx | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx index 2109b776..88cc6b73 100644 --- a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx @@ -32,7 +32,7 @@ import { import { formikToUiConfig, getDataSourceFromURL, - getEffectiveVersion, + getDataSourceVersion, } from '../../../utils'; import { CollapseProcessor, @@ -120,7 +120,7 @@ export function ProcessorsList(props: ProcessorsListProps) { } if (dataSourceId !== undefined) { - getEffectiveVersion(dataSourceId) + getDataSourceVersion(dataSourceId) .then((ver) => { setVersion(ver || MIN_SUPPORTED_VERSION); }) diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx index 2582655e..2fcfafd2 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx @@ -16,7 +16,7 @@ import { WorkflowConfig, } from '../../../../../common'; import { catIndices, useAppDispatch } from '../../../../store'; -import { getDataSourceId, getEffectiveVersion } from '../../../../utils'; +import { getDataSourceId, getDataSourceVersion } from '../../../../utils'; interface SearchInputsProps { uiConfig: WorkflowConfig; @@ -44,7 +44,7 @@ export function SearchInputs(props: SearchInputsProps) { try { if (dataSourceId !== undefined) { const version = - (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; setShowTransformQuery(semver.gte(version, '2.19.0')); } else { setShowTransformQuery(true); diff --git a/public/pages/workflows/new_workflow/new_workflow.tsx b/public/pages/workflows/new_workflow/new_workflow.tsx index 13aeacd8..aed2d0c3 100644 --- a/public/pages/workflows/new_workflow/new_workflow.tsx +++ b/public/pages/workflows/new_workflow/new_workflow.tsx @@ -30,7 +30,7 @@ import { enrichPresetWorkflowWithUiMetadata } from './utils'; import { getDataSourceId, isDataSourceReady, - getEffectiveVersion, + getDataSourceVersion, } from '../../../utils'; import { getDataSourceEnabled } from '../../../services'; import semver from 'semver'; @@ -65,7 +65,7 @@ const filterPresetsByVersion = async ( ]; const version = - (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; if (semver.lt(version, MIN_SUPPORTED_VERSION)) { return []; @@ -161,7 +161,7 @@ export function NewWorkflow(props: NewWorkflowProps) { } const version = - (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; const enrichedWorkflows = presetWorkflows.map((presetWorkflow) => enrichPresetWorkflowWithUiMetadata(presetWorkflow, version) diff --git a/public/utils/utils.tsx b/public/utils/utils.tsx index fbca81b2..f176e422 100644 --- a/public/utils/utils.tsx +++ b/public/utils/utils.tsx @@ -175,7 +175,7 @@ export async function isCompatibleWorkflow( } const dataSourceVersion = - (await getEffectiveVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; const [ effectiveMajorVersion, effectiveMinorVersion, @@ -573,7 +573,7 @@ export function useDataSourceVersion( useEffect(() => { async function getVersion() { if (dataSourceId !== undefined) { - setDataSourceVersion(await getEffectiveVersion(dataSourceId)); + setDataSourceVersion(await getDataSourceVersion(dataSourceId)); } } getVersion(); @@ -946,7 +946,7 @@ export function getFieldValue(jsonObj: {}, fieldName: string): any | undefined { } // Get the version from the selected data source, if found -export const getEffectiveVersion = async ( +export const getDataSourceVersion = async ( dataSourceId: string | undefined ): Promise => { try {