Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions locales/en/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
"{{count}} Node Field_other": "{{count}} Node Fields",
"{{count}} successful checks_one": "{{count}} successful check",
"{{count}} successful checks_other": "{{count}} successful checks",
"{{count}} uploads were aborted_one": "{{count}} uploads were aborted",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborteds",
"{{count}} VirtualMachine_one": "{{count}} VirtualMachine",
"{{count}} VirtualMachine_other": "{{count}} VirtualMachines",
"{{count}} Volumes_one": "{{count}} Volume",
Expand Down Expand Up @@ -2210,6 +2212,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "Upload PVC image",
"Upload to registry": "Upload to registry",
Expand Down
4 changes: 4 additions & 0 deletions locales/es/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
"{{count}} successful checks_one": "{{count}} comprobaciones exitosas_one",
"{{count}} successful checks_many": "{{count}} successful checks",
"{{count}} successful checks_other": "{{count}} comprobaciones exitosas_other",
"{{count}} uploads were aborted_one": "{{count}} uploads were aborted",
"{{count}} uploads were aborted_many": "{{count}} uploads were aborted",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborted",
"{{count}} VirtualMachine_one": "{{count}} VirtualMachine_one",
"{{count}} VirtualMachine_many": "{{count}} VirtualMachine",
"{{count}} VirtualMachine_other": "{{count}} VirtualMachine_other",
Expand Down Expand Up @@ -2231,6 +2234,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "Cargar imagen de PVC",
"Upload to registry": "Cargar al registro",
Expand Down
4 changes: 4 additions & 0 deletions locales/fr/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
"{{count}} successful checks_one": "{{count}} vérifications réussies_une",
"{{count}} successful checks_many": "{{count}} successful checks",
"{{count}} successful checks_other": "{{count}} vérifications réussies_autres",
"{{count}} uploads were aborted_one": "{{count}} uploads were aborted",
"{{count}} uploads were aborted_many": "{{count}} uploads were aborted",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborted",
"{{count}} VirtualMachine_one": "{{count}} Machine virtuelle_une",
"{{count}} VirtualMachine_many": "{{count}} VirtualMachine",
"{{count}} VirtualMachine_other": "{{count}} Machine virtuelle_autre",
Expand Down Expand Up @@ -2231,6 +2234,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "Télécharger l'image PVC",
"Upload to registry": "Télécharger dans le registre",
Expand Down
2 changes: 2 additions & 0 deletions locales/ja/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"{{count}} Node Field_other": "{{count}} ノードフィールド",
"{{count}} successful checks_one": "{{count}} 件のチェックが成功しました",
"{{count}} successful checks_other": "{{count}} 件のチェックが成功しました",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborted",
"{{count}} VirtualMachine_one": "{{count}} VirtualMachine",
"{{count}} VirtualMachine_other": "{{count}} VirtualMachine",
"{{count}} Volumes_one": "{{count}} 台のボリューム",
Expand Down Expand Up @@ -2209,6 +2210,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "PVC イメージのアップロード",
"Upload to registry": "レジストリーへのアップロード",
Expand Down
2 changes: 2 additions & 0 deletions locales/ko/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"{{count}} Node Field_other": "{{count}} 노드 필드",
"{{count}} successful checks_one": "{{count}} 검사 성공",
"{{count}} successful checks_other": "{{count}} 검사 성공",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborted",
"{{count}} VirtualMachine_one": "{{count}} VirtualMachine",
"{{count}} VirtualMachine_other": "{{count}} VirtualMachine",
"{{count}} Volumes_one": "{{count}} 볼륨",
Expand Down Expand Up @@ -2209,6 +2210,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "PVC 이미지 업로드",
"Upload to registry": "레지스트리에 업로드",
Expand Down
2 changes: 2 additions & 0 deletions locales/zh/plugin__kubevirt-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"{{count}} Node Field_other": "{{count}} 节点字段",
"{{count}} successful checks_one": "{{count}} 个成功的检查",
"{{count}} successful checks_other": "{{count}} 个成功的检查",
"{{count}} uploads were aborted_other": "{{count}} uploads were aborted",
"{{count}} VirtualMachine_one": "{{count}} 个虚拟机",
"{{count}} VirtualMachine_other": "{{count}} 个虚拟机",
"{{count}} Volumes_one": "{{count}} 个卷_one",
Expand Down Expand Up @@ -2209,6 +2210,7 @@
"Upload of {{fileName}} aborted": "Upload of {{fileName}} aborted",
"Upload of {{fileName}} completed": "Upload of {{fileName}} completed",
"Upload of {{fileName}} failed": "Upload of {{fileName}} failed",
"Upload of {{fileName}} was aborted": "Upload of {{fileName}} was aborted",
"Upload progress for {{fileName}}": "Upload progress for {{fileName}}",
"Upload PVC image": "上传 PVC 镜像",
"Upload to registry": "上传到 registry",
Expand Down
9 changes: 6 additions & 3 deletions src/utils/components/DiskModal/UploadDiskModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { useCDIUpload } from '@kubevirt-utils/hooks/useCDIUpload/useCDIUpload';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { cancelTrackedUploadOnModalClose } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/modalUploadCancel';
import { completeVmDiskUpload } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/uploadCompletion';
import { getVmDiskUploadKey } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/uploadKeys';
import {
getUploadClusterForVm,
getVmDiskUploadKey,
} from '@kubevirt-utils/hooks/useUploadProgressToast/utils/uploadKeys';
import { getName, getNamespace } from '@kubevirt-utils/resources/shared';
import { getCluster } from '@multicluster/helpers/selectors';
import { isRunning } from '@virtualmachines/utils';
Expand Down Expand Up @@ -57,7 +60,7 @@ const UploadDiskModal: FC<V1SubDiskModalProps> = ({
onClose={() => {
const diskName = getValues('disk.name');
const uploadKey = diskName
? getVmDiskUploadKey(getCluster(vm), getNamespace(vm), getName(vm), diskName)
? getVmDiskUploadKey(getUploadClusterForVm(vm), getNamespace(vm), getName(vm), diskName)
: undefined;

cancelTrackedUploadOnModalClose({ upload, uploadKey });
Expand All @@ -66,7 +69,7 @@ const UploadDiskModal: FC<V1SubDiskModalProps> = ({
onSubmit={() =>
handleSubmit(async (data) => {
const uploadKey = getVmDiskUploadKey(
getCluster(vm),
getUploadClusterForVm(vm),
getNamespace(vm),
getName(vm),
data.disk.name,
Expand Down
34 changes: 33 additions & 1 deletion src/utils/components/DiskModal/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import {
V1Volume,
} from '@kubevirt-ui-ext/kubevirt-api/kubevirt';
import { t } from '@kubevirt-utils/hooks/useKubevirtTranslation';
import { CdiUploadTrackMetadata } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/types';
import { getVmDiskUploadSuccessLinks } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/uploadLinks';
import {
buildOwnerReference,
getAnnotation,
getName,
getNamespace,
getUID,
} from '@kubevirt-utils/resources/shared';
import { ANNOTATIONS } from '@kubevirt-utils/resources/template';
import { getBootDisk, getDataVolumeTemplates, getVolumes } from '@kubevirt-utils/resources/vm';
Expand All @@ -30,7 +33,7 @@ import { addPersistentVolume, removeVolume } from '@virtualmachines/actions/acti
import { updateDisks } from '@virtualmachines/details/tabs/configuration/details/utils/utils';

import { HotPlugFeatures } from './constants';
import { SourceTypes, V1DiskFormState } from './types';
import { BuildUploadTrackMetadataParams, SourceTypes, V1DiskFormState } from './types';

export const getEmptyVMDataVolumeResource = (
vm: V1VirtualMachine,
Expand Down Expand Up @@ -472,3 +475,32 @@ export const convertDataVolumeToTemplate = (
},
},
});

export const buildUploadTrackMetadata = ({
abortTooltip,
data,
dataVolume,
file,
isCDROM,
onCancelCleanup,
t: translate,
uploadKey,
vm,
}: BuildUploadTrackMetadataParams): CdiUploadTrackMetadata | undefined => {
if (!uploadKey || !file) return undefined;

const dvName = getName(dataVolume);
const diskName = data.disk?.name;

return {
abortTooltip,
contextLinks: getUID(vm)
? getVmDiskUploadSuccessLinks(translate, vm, diskName, dvName, isCDROM)
: undefined,
dvCluster: getCluster(vm),
dvName,
dvNamespace: getNamespace(dataVolume),
onCancelCleanup,
resourceName: diskName,
};
};
35 changes: 13 additions & 22 deletions src/utils/components/DiskModal/utils/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {
logVMDiskHotplug,
} from '@kubevirt-utils/extensions/telemetry/vm-storage';
import { UploadDataProps } from '@kubevirt-utils/hooks/useCDIUpload/types';
import { getVmDiskUploadSuccessLinks } from '@kubevirt-utils/hooks/useUploadProgressToast/utils/uploadLinks';
import { PersistentVolumeClaimModel } from '@kubevirt-utils/models';
import { getName, getNamespace } from '@kubevirt-utils/resources/shared';
import { getName } from '@kubevirt-utils/resources/shared';
import {
getBootDisk,
getDataVolumeTemplates,
Expand All @@ -28,6 +27,7 @@ import { getDataVolumeTemplateSize } from '../components/utils/selectors';
import { reorderBootDisk } from './bootDiskUtils';
import { DEFAULT_CDROM_DISK_SIZE, DEFAULT_DISK_SIZE, UPLOAD_SUFFIX } from './constants';
import {
buildUploadTrackMetadata,
createDataVolumeName,
getEmptyVMDataVolumeResource,
hotplugPromise,
Expand Down Expand Up @@ -59,26 +59,17 @@ export const uploadDataVolume = async (
dataVolume,
file,
uploadKey,
uploadTrackMetadata:
uploadKey && file
? {
abortTooltip,
contextLinks: t
? getVmDiskUploadSuccessLinks(
t,
vm,
data.disk?.name,
dataVolume.metadata.name,
isCDROM,
)
: undefined,
dvCluster: getCluster(vm),
dvName: dataVolume.metadata.name,
dvNamespace: getNamespace(dataVolume),
onCancelCleanup,
resourceName: data.disk?.name,
}
: undefined,
uploadTrackMetadata: buildUploadTrackMetadata({
abortTooltip,
data,
dataVolume,
file,
isCDROM,
onCancelCleanup,
t,
uploadKey,
vm,
}),
});

if (data?.dataVolumeTemplate?.spec?.source?.upload) {
Expand Down
12 changes: 12 additions & 0 deletions src/utils/components/DiskModal/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ export type UploadDataVolumeOptions = {
onCancelCleanup?: () => Promise<void>;
};

export type BuildUploadTrackMetadataParams = {
abortTooltip: UploadDataVolumeOptions['abortTooltip'];
data: V1DiskFormState;
dataVolume: V1beta1DataVolume;
file: File;
isCDROM: boolean;
onCancelCleanup: UploadDataVolumeOptions['onCancelCleanup'];
t: TFunction;
uploadKey: string | undefined;
vm: V1VirtualMachine;
};
Comment on lines +88 to +98

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== TypeScript compiler options =="
fd -i 'tsconfig*.json' | while read -r file; do
  echo "--- ${file} ---"
  jq '.compilerOptions | {strict, strictNullChecks}' "${file}"
done

echo
echo "== uploadDataVolume declarations and usages =="
rg -n --type=ts --type=tsx -C3 '\buploadDataVolume\s*\('

echo
echo "== buildUploadTrackMetadata usages =="
rg -n --type=ts --type=tsx -C3 '\bbuildUploadTrackMetadata\s*\('

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 352


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check tsconfig for strict mode =="
if [ -f tsconfig.json ]; then
  jq -r '.compilerOptions | "\(.strict // "not set") strict, \(.strictNullChecks // "not set") strictNullChecks"' tsconfig.json
fi

echo
echo "== Current BuildUploadTrackMetadataParams definition =="
cat src/utils/components/DiskModal/utils/types.ts

echo
echo "== Search for uploadDataVolume with correct syntax =="
rg -n 'uploadDataVolume' --glob='**/*.ts' --glob='**/*.tsx' -C 3

echo
echo "== Search for buildUploadTrackMetadata calls =="
rg -n 'buildUploadTrackMetadata' --glob='**/*.ts' --glob='**/*.tsx' -C 3

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 12412


🏁 Script executed:

#!/bin/bash

echo "== uploadDataVolume full signature and buildUploadTrackMetadata call =="
sed -n '38,75p' src/utils/components/DiskModal/utils/submit.ts

echo
echo "== buildUploadTrackMetadata implementation =="
sed -n '479,510p' src/utils/components/DiskModal/utils/helpers.ts

echo
echo "== UploadDiskModal uploadDataVolume call context =="
sed -n '75,95p' src/utils/components/DiskModal/UploadDiskModal.tsx

echo
echo "== vmCdromBackgroundUpload uploadDataVolume call =="
sed -n '45,55p' src/utils/components/DiskModal/utils/vmCdromBackgroundUpload.ts

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 2921


🏁 Script executed:

#!/bin/bash

echo "== getVmDiskUploadSuccessLinks implementation =="
rg -n 'getVmDiskUploadSuccessLinks' --glob='**/*.ts' --glob='**/*.tsx' -A 8 -B 2 | head -50

echo
echo "== Check UploadDataProps type =="
rg -n 'UploadDataProps' --glob='**/*.ts' --glob='**/*.tsx' -A 5 -B 2

Repository: kubevirt-ui/kubevirt-plugin

Length of output: 20454


Align BuildUploadTrackMetadataParams optionality with actual caller contract

file and t are required in BuildUploadTrackMetadataParams, but uploadDataVolume accepts both as optional (t?: TFunction and file = data?.uploadFile?.file). The type mismatch creates a runtime risk: buildUploadTrackMetadata guards against undefined file but not translate, so calling getVmDiskUploadSuccessLinks(translate, ...) with undefined translate could fail.

Suggested contract fix
 export type BuildUploadTrackMetadataParams = {
   abortTooltip: UploadDataVolumeOptions['abortTooltip'];
   data: V1DiskFormState;
   dataVolume: V1beta1DataVolume;
-  file: File;
+  file?: File;
   isCDROM: boolean;
   onCancelCleanup: UploadDataVolumeOptions['onCancelCleanup'];
-  t: TFunction;
-  uploadKey: string | undefined;
+  t?: TFunction;
+  uploadKey?: string;
   vm: V1VirtualMachine;
 };
// In buildUploadTrackMetadata (helpers.ts), gate link construction:
contextLinks:
  translate && getUID(vm)
    ? getVmDiskUploadSuccessLinks(translate, vm, diskName, dvName, isCDROM)
    : undefined;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export type BuildUploadTrackMetadataParams = {
abortTooltip: UploadDataVolumeOptions['abortTooltip'];
data: V1DiskFormState;
dataVolume: V1beta1DataVolume;
file: File;
isCDROM: boolean;
onCancelCleanup: UploadDataVolumeOptions['onCancelCleanup'];
t: TFunction;
uploadKey: string | undefined;
vm: V1VirtualMachine;
};
export type BuildUploadTrackMetadataParams = {
abortTooltip: UploadDataVolumeOptions['abortTooltip'];
data: V1DiskFormState;
dataVolume: V1beta1DataVolume;
file?: File;
isCDROM: boolean;
onCancelCleanup: UploadDataVolumeOptions['onCancelCleanup'];
t?: TFunction;
uploadKey?: string;
vm: V1VirtualMachine;
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/components/DiskModal/utils/types.ts` around lines 88 - 98, The
BuildUploadTrackMetadataParams type declares file and t as required properties,
but the actual caller uploadDataVolume treats them as optional, creating a
runtime risk. In the buildUploadTrackMetadata function, add a conditional guard
for the translate parameter (the t parameter) before calling
getVmDiskUploadSuccessLinks, ensuring contextLinks is only constructed when
translate is defined, similar to how file is already guarded against undefined
values.


export type SubmitInput = {
data: V1DiskFormState;
editDiskName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { FC, useEffect } from 'react';
import { FC, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router';

import useKubevirtToast from '@kubevirt-utils/hooks/useKubevirtToast';
import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation';

import { cleanupRemovedUploads } from './utils/cleanupRemovedUploads';
import { useUploadProgressStore } from './uploadProgressStore';
import { syncUploadToasts } from './uploadToastSync';

Expand All @@ -18,8 +19,17 @@ const UploadProgressToastListener: FC = () => {
);
const trySetToastId = useUploadProgressStore((state) => state.trySetToastId);
const removeUpload = useUploadProgressStore((state) => state.removeUpload);
const prevUploadsRef = useRef(useUploadProgressStore.getState().uploads);

useEffect(() => {
cleanupRemovedUploads({
addWarningToast,
currentUploads: uploads,
previousUploads: prevUploadsRef.current,
removeToast,
t,
});

syncUploadToasts(uploads, {
addDangerToast,
addInfoToast,
Expand All @@ -32,6 +42,8 @@ const UploadProgressToastListener: FC = () => {
tryMarkTerminalToastShown,
trySetToastId,
});

prevUploadsRef.current = uploads;
}, [
addDangerToast,
addInfoToast,
Expand Down
Loading