Skip to content

Commit dcd8b58

Browse files
Fixed local cluster bug and added datasource version compatibility check before importing workflows (#646) (#650)
* Fixed local cluster bug and added datasource version compatibility check before importing workflows * Fixed local cluster bug and added datasource version compatibility check before importing workflows --------- (cherry picked from commit 45968d5) Signed-off-by: saimedhi <saimedhi@amazon.com> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 3e2f153 commit dcd8b58

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

public/pages/workflows/import_workflow/import_workflow_modal.tsx

+39-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
getObjFromJsonOrYamlString,
2828
isValidUiWorkflow,
2929
isValidWorkflow,
30+
isCompatibleWorkflow,
3031
} from '../../../utils';
3132
import { getCore } from '../../../services';
3233
import {
@@ -43,7 +44,7 @@ import {
4344
WORKFLOW_NAME_RESTRICTIONS,
4445
} from '../../../../common';
4546
import { WORKFLOWS_TAB } from '../workflows';
46-
import { getDataSourceId } from '../../../utils/utils';
47+
import { getDataSourceId, getEffectiveVersion, formatDisplayVersion } from '../../../utils/utils';
4748

4849
interface ImportWorkflowModalProps {
4950
isImportModalOpen: boolean;
@@ -61,6 +62,17 @@ interface ImportWorkflowModalProps {
6162
export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
6263
const dispatch = useAppDispatch();
6364
const dataSourceId = getDataSourceId();
65+
const [dataSourceVersion, setDataSourceVersion] = useState<
66+
string | undefined
67+
>(undefined);
68+
useEffect(() => {
69+
async function getVersion() {
70+
if (dataSourceId !== undefined) {
71+
setDataSourceVersion(await getEffectiveVersion(dataSourceId));
72+
}
73+
}
74+
getVersion();
75+
}, [dataSourceId]);
6476
const { workflows } = useSelector((state: AppState) => state.workflows);
6577

6678
// workflow name state
@@ -86,6 +98,9 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
8698
return description.length > MAX_DESCRIPTION_LENGTH;
8799
}
88100

101+
// State for tracking workflow template compatibility with current data source version
102+
const [isCompatible, setIsCompatible] = useState<boolean>(true);
103+
89104
// transient importing state for button state
90105
const [isImporting, setIsImporting] = useState<boolean>(false);
91106

@@ -115,6 +130,16 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
115130
}
116131
}, [fileObj]);
117132

133+
useEffect(() => {
134+
async function checkCompatibility() {
135+
if (isValidWorkflow(fileObj)) {
136+
const isCompatible = await isCompatibleWorkflow(fileObj, dataSourceId);
137+
setIsCompatible(isCompatible);
138+
}
139+
}
140+
checkCompatibility();
141+
}, [fileObj, dataSourceId]);
142+
118143
function onModalClose(): void {
119144
props.setIsImportModalOpen(false);
120145
setFileContents(undefined);
@@ -142,6 +167,18 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
142167
<EuiSpacer size="m" />
143168
</>
144169
)}
170+
{isValidWorkflow(fileObj) && !isCompatible && dataSourceVersion && (
171+
<>
172+
<EuiFlexItem>
173+
<EuiCallOut
174+
title={`The uploaded file is not compatible with the current data source version ${formatDisplayVersion(dataSourceVersion)}. Upload a compatible file or switch to another data source.`}
175+
iconType={'alert'}
176+
color="danger"
177+
/>
178+
</EuiFlexItem>
179+
<EuiSpacer size="m" />
180+
</>
181+
)}
145182
{isValidWorkflow(fileObj) && !isValidUiWorkflow(fileObj) && (
146183
<>
147184
<EuiFlexItem>
@@ -230,6 +267,7 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
230267
<EuiSmallButton
231268
disabled={
232269
!isValidWorkflow(fileObj) ||
270+
!isCompatible ||
233271
isImporting ||
234272
isInvalidName(workflowName) ||
235273
isInvalidDescription(workflowDescription)

public/route_service.ts

-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ export function configureRoutes(core: CoreStart): RouteService {
334334
return e as HttpFetchError;
335335
}
336336
},
337-
338337
getIndex: async (index: string, dataSourceId?: string) => {
339338
try {
340339
const url = dataSourceId

public/utils/utils.tsx

+36-1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,29 @@ export function isValidWorkflow(workflowObj: any): boolean {
157157
return workflowObj?.name !== undefined;
158158
}
159159

160+
// Determines if a file used for import workflow is compatible with the current data source version.
161+
export async function isCompatibleWorkflow(
162+
workflowObj: any,
163+
dataSourceId?: string | undefined
164+
): Promise<boolean> {
165+
const compatibility = workflowObj?.version?.compatibility;
166+
167+
// Default to true when compatibility cannot be assessed (empty/invalid compatibility array or MDS disabled.)
168+
if (!Array.isArray(compatibility) || compatibility.length === 0 || dataSourceId === undefined) {
169+
return true;
170+
}
171+
172+
const dataSourceVersion = await getEffectiveVersion(dataSourceId);
173+
const [effectiveMajorVersion, effectiveMinorVersion] = dataSourceVersion.split('.').map(Number);
174+
175+
// Checks if any version in compatibility array matches the current dataSourceVersion (major.minor)
176+
return compatibility.some(compatibleVersion => {
177+
const [compatibleMajor, compatibleMinor] = compatibleVersion.split('.').map(Number);
178+
return effectiveMajorVersion === compatibleMajor && effectiveMinorVersion === compatibleMinor;
179+
});
180+
}
181+
182+
160183
export function isValidUiWorkflow(workflowObj: any): boolean {
161184
return (
162185
isValidWorkflow(workflowObj) &&
@@ -530,7 +553,7 @@ export const getDataSourceId = () => {
530553

531554
export const isDataSourceReady = (dataSourceId?: string) => {
532555
const dataSourceEnabled = getDataSourceEnabled().enabled;
533-
return !dataSourceEnabled || (dataSourceId && dataSourceId !== '');
556+
return !dataSourceEnabled || dataSourceId !== undefined;
534557
};
535558

536559
// converts camelCase to a space-delimited string with the first word capitalized.
@@ -912,3 +935,15 @@ export const getEffectiveVersion = async (
912935
return MIN_SUPPORTED_VERSION;
913936
}
914937
};
938+
939+
940+
/**
941+
* Formats version string to show only major.minor numbers
942+
* Example: "3.0.0-alpha1" -> "3.0"
943+
*/
944+
export function formatDisplayVersion(version: string): string {
945+
// Take first two parts of version number (major.minor)
946+
const [major, minor] = version.split('.');
947+
return `${major}.${minor}`;
948+
}
949+

0 commit comments

Comments
 (0)