diff --git a/src/views/templates/details/tabs/details/components/WorkloadProfileModal.tsx b/src/utils/components/WorkloadProfileModal/WorkloadProfileModal.tsx similarity index 82% rename from src/views/templates/details/tabs/details/components/WorkloadProfileModal.tsx rename to src/utils/components/WorkloadProfileModal/WorkloadProfileModal.tsx index 31b21afd3..b04980869 100644 --- a/src/views/templates/details/tabs/details/components/WorkloadProfileModal.tsx +++ b/src/utils/components/WorkloadProfileModal/WorkloadProfileModal.tsx @@ -1,29 +1,23 @@ import * as React from 'react'; -import { getTemplateWorkload } from 'src/views/templates/utils/selectors'; -import { V1Template } from '@kubevirt-ui/kubevirt-api/console'; import TabModal from '@kubevirt-utils/components/TabModal/TabModal'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; import { WORKLOADS, WORKLOADS_LABELS } from '@kubevirt-utils/resources/template'; import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; import { Form, FormGroup, Select, SelectOption } from '@patternfly/react-core'; -import './cpu-memory-modal.scss'; - type WorkloadProfileModalProps = { - obj: V1Template; + initialWorkload: string; isOpen: boolean; onClose: () => void; onSubmit: (workload: string) => Promise; }; const WorkloadProfileModal: React.FC = React.memo( - ({ obj, isOpen, onClose, onSubmit }) => { + ({ initialWorkload, isOpen, onClose, onSubmit }) => { const { t } = useKubevirtTranslation(); const [isDropdownOpen, setIsDropdownOpen] = React.useState(false); - const [workload, setWorkload] = React.useState( - getTemplateWorkload(obj) || WORKLOADS.desktop, - ); + const [workload, setWorkload] = React.useState(initialWorkload || WORKLOADS.desktop); const handleChange = (event: React.ChangeEvent, value: WORKLOADS) => { event.preventDefault(); @@ -35,7 +29,6 @@ const WorkloadProfileModal: React.FC = React.memo( onSubmit(workload)} > diff --git a/src/utils/resources/vm/utils/selectors.ts b/src/utils/resources/vm/utils/selectors.ts index d456eec4c..f3004c4b2 100644 --- a/src/utils/resources/vm/utils/selectors.ts +++ b/src/utils/resources/vm/utils/selectors.ts @@ -1,4 +1,7 @@ import { V1Disk, V1VirtualMachine } from '@kubevirt-ui/kubevirt-api/kubevirt'; +import { getAnnotation } from '@kubevirt-utils/resources/shared'; + +import { VM_WORKLOAD_ANNOTATION } from './annotations'; /** * A selector for the virtual machine's networks @@ -126,3 +129,10 @@ export const getBootDisk = (vm: V1VirtualMachine): V1Disk => */ export const getMachineType = (vm: V1VirtualMachine): string => vm?.spec?.template?.spec?.domain?.machine?.type; + +/** + * A selector that returns the workload of a given virtual machine + * @param {V1VirtualMachine} vm the virtual machine + */ +export const getWorkload = (vm: V1VirtualMachine): string => + getAnnotation(vm?.spec?.template, VM_WORKLOAD_ANNOTATION); diff --git a/src/views/catalog/wizard/tabs/overview/WizardOverviewTab.tsx b/src/views/catalog/wizard/tabs/overview/WizardOverviewTab.tsx index 10164247f..f2fca1403 100644 --- a/src/views/catalog/wizard/tabs/overview/WizardOverviewTab.tsx +++ b/src/views/catalog/wizard/tabs/overview/WizardOverviewTab.tsx @@ -8,10 +8,17 @@ import FirmwareBootloaderModal from '@kubevirt-utils/components/FirmwareBootload import { getBootloaderTitleFromVM } from '@kubevirt-utils/components/FirmwareBootloaderModal/utils/utils'; import HardwareDevices from '@kubevirt-utils/components/HardwareDevices/HardwareDevices'; import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider'; +import WorkloadProfileModal from '@kubevirt-utils/components/WorkloadProfileModal/WorkloadProfileModal'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; import { getAnnotation } from '@kubevirt-utils/resources/shared'; import { getVmCPUMemory, WORKLOADS_LABELS } from '@kubevirt-utils/resources/template'; -import { getGPUDevices, getHostDevices, getMachineType } from '@kubevirt-utils/resources/vm'; +import { + getGPUDevices, + getHostDevices, + getMachineType, + getWorkload, + VM_WORKLOAD_ANNOTATION, +} from '@kubevirt-utils/resources/vm'; import { readableSizeUnit } from '@kubevirt-utils/utils/units'; import { DescriptionList, Grid, GridItem } from '@patternfly/react-core'; @@ -30,7 +37,7 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => { const { cpuCount, memory } = getVmCPUMemory(vm); const description = getAnnotation(vm, 'description'); - const workloadAnnotation = vm?.spec?.template?.metadata?.annotations?.['vm.kubevirt.io/workload']; + const workloadAnnotation = getWorkload(vm); const networks = vm?.spec?.template?.spec?.networks; const interfaces = vm?.spec?.template?.spec?.domain?.devices?.interfaces; const disks = vm?.spec?.template?.spec?.domain?.devices?.disks; @@ -40,6 +47,15 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => { const gpusCount = getGPUDevices(vm)?.length || 0; const nDevices = hostDevicesCount + gpusCount; + const updateWorkload = async (newWorkload: string) => { + return updateVM((draftVM) => { + if (!draftVM.spec.template.metadata?.annotations) + draftVM.spec.template.metadata.annotations = {}; + + draftVM.spec.template.metadata.annotations[VM_WORKLOAD_ANNOTATION] = newWorkload; + }); + }; + return (
@@ -141,6 +157,17 @@ const WizardOverviewTab: WizardTab = ({ vm, tabsData, updateVM }) => { + createModal(({ isOpen, onClose }) => ( + + )) + } description={WORKLOADS_LABELS?.[workloadAnnotation] ?? t('Other')} testId="wizard-overview-workload-profile" /> diff --git a/src/views/templates/details/tabs/details/components/WorkloadProfile.tsx b/src/views/templates/details/tabs/details/components/WorkloadProfile.tsx index 39e0b0623..747be148b 100644 --- a/src/views/templates/details/tabs/details/components/WorkloadProfile.tsx +++ b/src/views/templates/details/tabs/details/components/WorkloadProfile.tsx @@ -4,12 +4,14 @@ import { getWorkloadProfile } from 'src/views/templates/utils/selectors'; import { TemplateModel } from '@kubevirt-ui/kubevirt-api/console'; import VirtualMachineModel from '@kubevirt-ui/kubevirt-api/console/models/VirtualMachineModel'; import { useModal } from '@kubevirt-utils/components/ModalProvider/ModalProvider'; +import WorkloadProfileModal from '@kubevirt-utils/components/WorkloadProfileModal/WorkloadProfileModal'; import { useKubevirtTranslation } from '@kubevirt-utils/hooks/useKubevirtTranslation'; import { getTemplateWorkload, TEMPLATE_WORKLOAD_LABEL, WORKLOADS, } from '@kubevirt-utils/resources/template'; +import { getWorkload } from '@kubevirt-utils/resources/vm'; import { k8sPatch } from '@openshift-console/dynamic-plugin-sdk'; import { Button, @@ -21,8 +23,6 @@ import { PencilAltIcon } from '@patternfly/react-icons'; import { TemplateDetailsGridProps } from '../TemplateDetailsPage'; -import WorkloadProfileModal from './WorkloadProfileModal'; - const WorkloadProfile: React.FC = ({ template, editable }) => { const { createModal } = useModal(); const { t } = useKubevirtTranslation(); @@ -32,10 +32,7 @@ const WorkloadProfile: React.FC = ({ template, editabl const vmObjectIndex = template?.objects.findIndex( (obj) => obj.kind === VirtualMachineModel.kind, ); - const hasWorkload = - template?.objects?.[vmObjectIndex]?.spec?.template?.metadata?.annotations?.[ - 'vm.kubevirt.io/workload' - ]; + const hasWorkload = getWorkload(template?.objects?.[vmObjectIndex]); const workloadPath = `/objects/${vmObjectIndex}/spec/template/metadata/annotations/vm.kubevirt.io~1workload`; return k8sPatch({ @@ -63,7 +60,7 @@ const WorkloadProfile: React.FC = ({ template, editabl const onEditClick = () => createModal(({ isOpen, onClose }) => ( { + if (vmWorkload === newWorkload) return Promise.resolve(); + + const updateVM = produce(vm, (draftVM) => { + if (!draftVM.spec.template.metadata?.annotations) + draftVM.spec.template.metadata.annotations = {}; + + draftVM.spec.template.metadata.annotations[VM_WORKLOAD_ANNOTATION] = newWorkload; + }); + + return k8sUpdate({ + model: VirtualMachineModel, + data: updateVM, + ns: updateVM?.metadata?.namespace, + name: updateVM?.metadata?.name, + }); + }; + return ( @@ -103,10 +126,23 @@ const VirtualMachineDetailsRightGridLayout: React.FC ) } + isEdit + onEditClick={() => + createModal(({ isOpen, onClose }) => ( + + )) + } descriptionHeader={t('Workload Profile')} data-test-id={`${vm?.metadata?.name}-workload-profile`} />