diff --git a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json index 95ccd8746..d54d72235 100644 --- a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json +++ b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json @@ -211,6 +211,7 @@ "Migrate": "Migrate", "Migrate without validating a CA certificate": "Migrate without validating a CA certificate", "Migration": "Migration", + "Migration hook": "Migration hook", "Migration networks maps are used to map network interfaces between source and target workloads.": "Migration networks maps are used to map network interfaces between source and target workloads.", "Migration plan state information and progress": "Migration plan state information and progress", "Migration plans are used to plan migration or virtualization workloads from source providers to target providers.": "Migration plans are used to plan migration or virtualization workloads from source providers to target providers.", diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css index d82fb4e45..995d8fb2f 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css @@ -124,3 +124,12 @@ margin-bottom: var(--pf-global--spacer--xs); margin-top: var(--pf-global--spacer--md); } + +.forklift-page-plan-details-vm-status__section-actions { + padding-bottom: 0; +} + +.forklift-page-plan-details-vm-status__actions { + margin-bottom: var(--pf-global--spacer--md); + margin-top: var(--pf-global--spacer--xs); +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/SimpleHooks.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/SimpleHooks.tsx index 255648c66..99cc96529 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/SimpleHooks.tsx +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/SimpleHooks.tsx @@ -2,19 +2,13 @@ import React, { useEffect, useReducer } from 'react'; import { Base64 } from 'js-base64'; import SectionHeading from 'src/components/headers/SectionHeading'; import { deepCopy } from 'src/modules/Plans/utils'; -import { AlertMessageForModals } from 'src/modules/Providers/modals'; import { useForkliftTranslation } from 'src/utils/i18n'; -import { - HookModelGroupVersionKind, - PlanModelGroupVersionKind, - V1beta1Hook, - V1beta1Plan, - V1beta1PlanSpecVmsHooks, -} from '@kubev2v/types'; -import { CodeEditor, useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; +import { V1beta1Hook, V1beta1Plan } from '@kubev2v/types'; +import { CodeEditor } from '@openshift-console/dynamic-plugin-sdk'; import { Button, + Divider, Flex, FlexItem, Form, @@ -28,8 +22,9 @@ import { import { Suspend } from '../../components'; +import { usePlanHooks } from './hooks'; import { formReducer, FormState } from './state'; -import { createHook, deleteHook, updateHook } from './utils'; +import { onUpdatePlanHooks } from './utils'; const preHookTemplate = (plan: V1beta1Plan) => ({ spec: { image: 'quay.io/konveyor/hook-runner', playbook: '' }, @@ -62,25 +57,10 @@ const initialState = ( export const SimpleHooks: React.FC<{ name: string; namespace: string }> = ({ name, namespace }) => { const { t } = useForkliftTranslation(); - const [plan, loaded, loadError] = useK8sWatchResource({ - groupVersionKind: PlanModelGroupVersionKind, - namespaced: true, + const [plan, preHookResource, postHookResource, loaded, loadError] = usePlanHooks( name, namespace, - }); - const hooks: V1beta1PlanSpecVmsHooks[] = plan?.spec?.vms?.[0]?.hooks || []; - const postHook = hooks.find((h) => h.step === 'PostHook'); - const preHook = hooks.find((h) => h.step === 'PreHook'); - - const [hookRecourses] = useK8sWatchResource({ - groupVersionKind: HookModelGroupVersionKind, - namespaced: true, - isList: true, - namespace: plan?.metadata?.namespace, - }); - - const postHookResource = hookRecourses.find((h) => h.metadata.name === postHook?.hook?.name); - const preHookResource = hookRecourses.find((h) => h.metadata.name === preHook?.hook?.name); + ); const [state, dispatch] = useReducer( formReducer, @@ -97,86 +77,52 @@ export const SimpleHooks: React.FC<{ name: string; namespace: string }> = ({ nam // Handle user clicking "save" async function onUpdate() { - dispatch({ type: 'SET_LOADING', payload: true }); - - let newPlan = deepCopy(plan); - - try { - if (state.preHookSet) { - if (preHookResource) { - // Patch new hook - await updateHook(state.preHook); - } else { - // Create hook - newPlan = await createHook(newPlan, state.preHook, 'PreHook'); - } - } else { - if (preHookResource) { - // Delete hook - newPlan = await deleteHook(newPlan, preHookResource, 'PreHook'); - } - } - - if (state.postHookSet) { - if (postHookResource) { - // Patch new hook - await updateHook(state.postHook); - } else { - // Create hook - await createHook(newPlan, state.postHook, 'PostHook'); - } - } else { - if (postHookResource) { - // Delete hook - await deleteHook(newPlan, postHookResource, 'PostHook'); - } - } - - dispatch({ type: 'SET_LOADING', payload: false }); - } catch (err) { - dispatch({ - type: 'SET_ALERT_MESSAGE', - payload: ( - - ), - }); - - dispatch({ type: 'SET_LOADING', payload: false }); - } + onUpdatePlanHooks({ plan, preHookResource, postHookResource, dispatch, state }); } + const HooksTabAction = ( + + + + + + + + + + ); + return ( - - - - - - - - - - - {state.alertMessage} + {state.alertMessage && {state.alertMessage}} + + + + {HooksTabAction} + +
diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/index.ts new file mode 100644 index 000000000..b6a35b584 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './usePlanHooks'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/usePlanHooks.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/usePlanHooks.ts new file mode 100644 index 000000000..a669f570e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/hooks/usePlanHooks.ts @@ -0,0 +1,32 @@ +import { + HookModelGroupVersionKind, + PlanModelGroupVersionKind, + V1beta1Hook, + V1beta1Plan, + V1beta1PlanSpecVmsHooks, +} from '@kubev2v/types'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; + +export const usePlanHooks = (name: string, namespace: string) => { + const [plan, loaded, loadError] = useK8sWatchResource({ + groupVersionKind: PlanModelGroupVersionKind, + namespaced: true, + name, + namespace, + }); + const hooks: V1beta1PlanSpecVmsHooks[] = plan?.spec?.vms?.[0]?.hooks || []; + const postHook = hooks.find((h) => h.step === 'PostHook'); + const preHook = hooks.find((h) => h.step === 'PreHook'); + + const [hookRecourses] = useK8sWatchResource({ + groupVersionKind: HookModelGroupVersionKind, + namespaced: true, + isList: true, + namespace: plan?.metadata?.namespace, + }); + + const postHookResource = hookRecourses.find((h) => h.metadata.name === postHook?.hook?.name); + const preHookResource = hookRecourses.find((h) => h.metadata.name === preHook?.hook?.name); + + return [plan, preHookResource, postHookResource, loaded, loadError]; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/index.ts index 199fdb86c..6e664b003 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/index.ts +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/index.ts @@ -1,5 +1,6 @@ // @index(['./*', /style/g], f => `export * from '${f.path}';`) export * from './createHook'; export * from './deleteHook'; +export * from './onUpdatePlanHooks'; export * from './updateHook'; // @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/onUpdatePlanHooks.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/onUpdatePlanHooks.tsx new file mode 100644 index 000000000..4e7661fad --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/SimpleHooks/utils/onUpdatePlanHooks.tsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { deepCopy } from 'src/modules/Plans/utils'; +import { AlertMessageForModals } from 'src/modules/Providers/modals'; + +import { V1beta1Hook, V1beta1Plan } from '@kubev2v/types'; + +import { FormAction, FormState } from '../state'; + +import { createHook } from './createHook'; +import { deleteHook } from './deleteHook'; +import { updateHook } from './updateHook'; + +type onUpdatePlanHooksProps = { + plan: V1beta1Plan; + preHookResource: V1beta1Hook; + postHookResource: V1beta1Hook; + dispatch: (value: FormAction) => void; + state: FormState; +}; + +// Handle user clicking "save" +export async function onUpdatePlanHooks(props: onUpdatePlanHooksProps) { + const { plan, preHookResource, postHookResource, dispatch, state } = props; + + dispatch({ type: 'SET_LOADING', payload: true }); + + let newPlan = deepCopy(plan); + + try { + if (state.preHookSet) { + if (preHookResource) { + // Patch new hook + await updateHook(state.preHook); + } else { + // Create hook + newPlan = await createHook(newPlan, state.preHook, 'PreHook'); + } + } else { + if (preHookResource) { + // Delete hook + newPlan = await deleteHook(newPlan, preHookResource, 'PreHook'); + } + } + + if (state.postHookSet) { + if (postHookResource) { + // Patch new hook + await updateHook(state.postHook); + } else { + // Create hook + await createHook(newPlan, state.postHook, 'PostHook'); + } + } else { + if (postHookResource) { + // Delete hook + await deleteHook(newPlan, postHookResource, 'PostHook'); + } + } + + dispatch({ type: 'SET_LOADING', payload: false }); + } catch (err) { + dispatch({ + type: 'SET_ALERT_MESSAGE', + payload: , + }); + + dispatch({ type: 'SET_LOADING', payload: false }); + } +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/VirtualMachines/Migration/MigrationVirtualMachinesRowExtended.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/VirtualMachines/Migration/MigrationVirtualMachinesRowExtended.tsx index bc23e0565..2aafdded6 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/VirtualMachines/Migration/MigrationVirtualMachinesRowExtended.tsx +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/VirtualMachines/Migration/MigrationVirtualMachinesRowExtended.tsx @@ -22,7 +22,9 @@ export const MigrationVirtualMachinesRowExtended: React.FC> = ( const conditions = props.resourceData.statusVM?.conditions; const pods = props.resourceData.pods; const jobs = props.resourceData.jobs; - const success = conditions?.find((c) => c.type === 'Succeeded' && c.status === 'True'); + const vmCreated = pipeline.find( + (p) => p?.name === 'VirtualMachineCreation' && p?.phase === 'Completed', + ); const getStatusLabel = (status: string) => { switch (status) { @@ -37,7 +39,7 @@ export const MigrationVirtualMachinesRowExtended: React.FC> = ( return ( - {success && ( + {vmCreated && ( <>