Skip to content

Commit 9cfe78b

Browse files
avivturcursoragent
andauthored
MTV-2482 | Add Deep Inspection feature for VM pre-migration analysis (#2381)
* Add Conversion CR types, hooks, and inspection status components Foundation layer for the Deep Inspection feature (MTV-2482). Adds local Conversion CR type definitions, GVK/model constants, watch and status hooks, and UI components for displaying inspection status per VM. Resolves: MTV-2482 Made-with: Cursor Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add deep inspection submit flow, entry points, and VMs tab wiring Phase 2: Adds InspectVirtualMachinesModal with VM selection table, useCreateDeepInspections hook, buildConversionCR utility, and useCanInspectPlan hook for visibility/disabled logic. Wires "Inspect VMs" button into Plan page header and actions dropdown (visible for vSphere providers only). Phase 3: Adds InspectionStatus column to the Plan VMs tab spec view and InspectionExpandedSection to the expanded row alongside the existing concerns table. Resolves: MTV-2482 Made-with: Cursor Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Remove unused exports flagged by knip Un-export ConversionType, DiskRef, PodSettings (used internally only) and remove getConversionVmId, getConversionType, getConversionConditions selectors that have no consumers yet. Resolves: MTV-2482 Made-with: Cursor Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Address review comments - Replace non-functional link Button with plain text for conversion run names - Fix tie-breaking in shouldReplace when both conversions are active Resolves: MTV-2483 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Made-with: Cursor Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Update types for backend changes, add inspection results, fix review comments Update Conversion CR types to match evolved backend PR #5882: - Phase/Stage separation (CreatingPod is now a stage, not a phase) - New Canceled phase, removed provider from spec, renamed fields - Added InspectionResult, OSInfo, InspectionConcern types - Added completionTime, stage, snapshot to status Add InspectionResultsSection component displaying inspection findings (OS info, concerns, filesystems) in the expanded row. Address all CodeRabbit review comments: - Fix i18n plural forms (singular base + pluralOverrides) - Add concurrency limit (batches of 10) for k8sCreate calls - Fix hardcoded rowIndex in InspectionVmTable - Guard submit against watch loading/stale state - Fix generateName edge cases (collapse hyphens, fallback) - Move useCanInspectPlan to plans feature tree (module boundary) - Add i18n to disabledReason strings - Fix duplicate dropdown item values - Move watch out of InspectionStatusCell into parent - Stabilize callbacks with useCallback/useMemo Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * UI fixes: Tech Preview label, StandardPage table, expanded section styling - Rename createOne to createDeepInspection for clarity - Add TechPreviewLabel next to modal header title - Replace raw Table in InspectionVmTable with StandardPageWithSelection (adds pagination, filter by name, column management, bulk selection) - VM ID column hidden by default, available via column management - Add "Concerns" title above ConcernsAndConditionsTable in expanded row - Restyle InspectionExpandedSection as a compact Table matching concerns - Add bottom padding to deep inspection expanded section - Move timestamp into popover on InspectionStatusLabel, remove Flex wrapper - Verify InspectionStatus column stays before Actions in field order Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Redesign inspection expanded section as multi-row table Replace the single-row Label/Value layout with a proper table showing all inspection runs per VM. Each row has: Inspection name (ResourceLink to Conversion CR), Status, Pod (ResourceLink), and Created at columns. Rows are expandable to show InspectionResultsSection with results. Drop the "Previous inspections" expandable section entirely. Rename section title to "Inspections". Add top margin to Concerns title. Remove unused i18n override. Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Fix dark theme table background in modal, fix column order - Add transparent table background inside inspect VMs modal to fix dark theme color mismatch between modal body and table rows - Bump spec VMs table page ID to invalidate stale localStorage that was placing InspectionStatus after Actions column - New page ID ensures the correct field order from specVirtualMachineFields is used (InspectionStatus before Actions) Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Address CodeRabbit review comments - Type InspectionVmRow phase as ConversionPhase instead of string - Simplify chunk sequencing with for-loop instead of nested reducer Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Remove unused getConversionCompletionTime export Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Replace regex with string methods in sanitizeK8sName Remove all regex patterns from buildConversionCR to avoid SonarCloud security hotspot flags and follow project convention of preferring string methods over regex. Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Remove sanitizeK8sName helper, pass vmName directly Kubernetes generateName handles naming constraints server-side. Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * UI polish: modal, expanded section, and inspection table fixes - Refactor InspectVirtualMachinesModal to use ModalForm component - Add label prop to ModalForm for inline labels next to title - Use TechPreviewLabel via ModalForm label prop with baseline alignment - Restore K8s name sanitization for generateName (fix uppercase/underscore) - Restore PageSection wrapper on inspections table - Make all inspection rows expandable with "No results yet" fallback - Add empty state when no inspections exist - Remove bottom border on last inspection table row - Lift inspection expanded rows state to parent (fix collapse on watch update) - Fix expanded content: show errors only when failed, not "No results yet" - Move results pass/fail label inline with title using Flex - Remove unused SCSS class, clean up dark theme table background - Add ModalForm usage rule to react-components.mdc Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add Inspect VMs to Provider Details page (standalone flow) Add deep inspection capability to the Provider Details page without requiring a plan. Share components with the plan flow via normalizer utilities. - Add PROVIDER label to CONVERSION_LABELS for provider-scoped queries - Make buildConversionCR plan-optional (standalone uses provider namespace) - Make useCreateDeepInspections plan-optional - Create normalizeVmsForInspection utility (normalizePlanVms + normalizeInventoryVms) - Refactor InspectVirtualMachinesModal to work with or without plan (loads inventory VMs when plan is absent) - Create useCanInspectProvider hook (vSphere + Ready + VDDK checks) - Add Inspect VMs button to ProviderPageHeader (left of Create Plan) - Add Inspect VMs dropdown item to ProviderActionsDropdownItems - Extract InspectionVmRowData type to shared normalizer module Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add inspection column to provider VMs, fix modal and table styling - Add InspectionStatus column to vSphere tree table - Pass conversions watch through tree table to VM rows and concerns row - Add InspectionExpandedSection to provider VM expanded row - Show loading spinner in modal for inventory VMs - Fix dark theme backgrounds in modal (table headers, toolbar, pagination) - Fix inspection table last row border Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add inspection status filter across all three VM views - Add Enum filter to modal VM table (inspectionVmFields) - Add Enum filter to plan VMs tab (specVirtualMachineFields) - Add Checkbox attribute filter to vSphere tree table - Shared filter values: Not inspected, Pending, Running, Succeeded, Failed, Canceled - Add INSPECTION_STATUS_NOT_INSPECTED and INSPECTION_STATUS_FILTER_VALUES constants Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add E2E tests for Deep Inspection feature - Add InspectVirtualMachinesModal page object - Extend PlanDetailsPage with inspection button/action methods - Extend ProviderDetailsPage with inspection button/action methods - Add plan-deep-inspection.spec.ts downstream tests - Add provider-deep-inspection.spec.ts downstream tests - Add data-testid to InspectionExpandedSection and InspectionStatusCell - Version gated to V2_12_0 Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Code review fixes: imports, memoization, type safety - Fix React.ReactNode -> explicit ReactNode import in InspectionVmRow - Replace relative import with @utils alias in normalizeVmsForInspection - Memoize watchSelector in InspectVirtualMachinesModal to prevent unnecessary re-renders from new object reference on each render Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Add disk encryption support and fix provider standalone flow - Add VmConfigForm with NBDE/Clevis and LUKS passphrase configuration - Add per-VM disk encryption to standalone provider inspection flow - Fix passphrase input focus loss by using local state with onBlur sync - Fix modal background mismatch in dark theme - Pin spec.targetNamespace to CR namespace for standalone flow Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Fix SonarCloud reliability bug and hardcoded rowIndex - Move useVmInspectionStatus hook call from inline VmCells record to VmTreeRow component body (fixes Rules of Hooks violation) - Use map index for rowIndex in InspectionExpandedSection instead of hardcoding 0 - Use uid ?? name fallback for Tbody key in InspectionExpandedSection Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Redesign inspection status UX and fix backend snake_case bug - Show actual inspection result in status column: "Inspection passed" or "Issues found" instead of generic "Completed" - Add INSPECTION_STATUS enum as single source of truth for all status labels, filters, sorting, and popover content - Handle backend snake_case serialization bug (all_checks_passed vs allChecksPassed) with hasInspectionPassed selector - Add column header popover explaining each inspection status - Redesign expanded inspection results: 2-column detail layout with Issues found table (Issue | Severity | Description) - Use CR lifecycle phase labels in inspection table (Succeeded/Failed etc.) instead of derived inspection status - Enable sorting by inspection status severity in both plan and provider VM tables - Fix provider tree table: only show sort arrows on sortable columns, render info popovers on column headers Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Resolves: MTV-2482 | fix icon import Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Resolves: MTV-2482 * Address review comments: refactor structure, extract constants - Split InspectionExpandedSection into ConversionPhaseLabel, InspectionTableRow, and slim orchestrator - Consolidate types in utils/types.ts: VmOverrides, VmInspectionRef, DiskEncryptionParam, InspectionVmRowData - Extract getInspectionStatusConfig to utils file - Remove dead timestamp/showTimestamp code from InspectionStatusLabel - Use getCategoryStatus from shared Concerns utility instead of inline getConcernCategoryStatus - Extract resolveDiskEncryption from modal to utility function - Use ConversionModel for apiVersion/kind in buildConversionCR - Use CATEGORY_TYPES.READY and CONDITION_STATUS.TRUE constants - Extract TOOLTIP_TRIGGER_MANUAL constant - Add generic getLabels selector to common selectors - Rename inspectionVmFields.tsx to .ts (no JSX) Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Surface inspection concerns in plan critical alerts and severity badges - Add inspection concern severity badges: when a VM has inspection issues, show grouped count labels (Critical/Warning/etc.) with popovers listing individual concerns, mirroring inventory concerns - Merge inspection concerns into PlanConcernsPanel and PlanAlerts with latest-per-VM deduplication strategy - Add source discriminator to drawer navigation so inspection concerns filter by inspectionStatus and inventory concerns filter by type - Add InspectionConcernBadges component with grouping utility - Add CONCERN_SOURCE constants for condition/inventory/inspection Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Address self-review: selectors, constants, component extraction - Replace direct metadata/spec access with common selectors (getName, getNamespace, getUID, getLabels, getCreatedAt, getType) across all inspection files - Add getProviderSecretRef selector to common selectors - Add Advisory/Error to ConcernCategoryOptions and update all maps - Add CATEGORY_TYPES.ERROR constant - Move MAX_PASSPHRASES to conversion constants - Replace hardcoded strings with COLUMN_IDS, CATEGORY_TYPES, CONDITION_STATUS - Add cspell words: moref, mountpoint, mountpoints - Refactor sanitizeForK8sName to use reduce instead of let variables - Extract chunked loop from useCreateDeepInspections to avoid eslint-disable - Merge normalizePlanVms and normalizeInventoryVms into single function - DRY useCanInspectPlan and useCanInspectProvider with disabled() helper - Extract InspectionPassedLabel, InspectionOsInfo, InspectionIssuesTable from InspectionResultsSection - Extract InspectionRowExpandedContent from InspectionTableRow - Extract useInspectionData hook from PlanSpecVirtualMachinesList - Create InspectVirtualMachinesButton reusable component - Move inspect button from PlanPageHeader to VM table toolbar actions - Remove Inspect VMs from plan and provider dropdown menus - Refactor InspectionStatusColumnPopover: extract descriptions to constants, render with t() instead of per-item ForkliftTrans - Add cursor rule for selector usage (.cursor/rules/selectors.mdc) Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Relocate provider Inspect VMs button to VM table toolbar - Move inspect button from ProviderPageHeader to TreeToolbar via toolbarActions slot, next to ManageColumns - Pass provider prop to VsphereFolderTreeTable for useCanInspectProvider - Only show button in provider details mode (!canSelect), hidden in wizard - Extract column enrichment to module-level constant - Remove unused useForkliftTranslation from ProviderPageHeader Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Resolves: MTV-2482 * Fix knip unused exports and constants placement Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Address review: hook type pattern, constant placement, extract types - Use function type annotation for useCreateDeepInspections hook - Move INITIAL_OFFSET constant to top of createDeepInspections.ts - Extract PhaseConfig type to utils/types.ts Resolves: MTV-2482 Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Signed-off-by: Aviv Turgeman <aturgema@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 9065391 commit 9cfe78b

86 files changed

Lines changed: 3447 additions & 105 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/rules/react-components.mdc

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,44 @@ const { control, handleSubmit, formState: { errors } } = methods;
117117

118118
---
119119

120-
## 6. Test Identifiers
120+
## 6. Modals
121+
122+
Always use the shared `ModalForm` component (`@components/ModalForm/ModalForm`) when creating new modals. It handles:
123+
- Modal shell (open/close, variant, position)
124+
- Loading state on confirm button
125+
- Error display (catches thrown errors automatically)
126+
- Confirm/Cancel buttons with proper variants
127+
- `closeModal` on success
128+
129+
```typescript
130+
import ModalForm from '@components/ModalForm/ModalForm';
131+
132+
const MyModal: ModalComponent<MyModalProps> = ({ myData, ...rest }) => {
133+
const handleConfirm = useCallback(async () => {
134+
await doSomething(myData);
135+
// throw new Error('message') on failure -- ModalForm catches and displays it
136+
}, [myData]);
137+
138+
return (
139+
<ModalForm
140+
title={t('My title')}
141+
onConfirm={handleConfirm}
142+
confirmLabel={t('Confirm')}
143+
isDisabled={!isValid}
144+
variant={ModalVariant.large}
145+
{...rest}
146+
>
147+
{/* Modal body content */}
148+
</ModalForm>
149+
);
150+
};
151+
```
152+
153+
Do NOT use raw `Modal` + `ModalHeader` + `ModalBody` + `ModalFooter` + manual error/loading state.
154+
155+
---
156+
157+
## 7. Test Identifiers
121158

122159
Use `testId` prop for test selectors:
123160
```typescript

.cursor/rules/selectors.mdc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
description: Use selectors for K8s resource property access
3+
globs: "**/*.{ts,tsx}"
4+
alwaysApply: false
5+
---
6+
7+
# Selector Usage Rule
8+
9+
When accessing properties of Kubernetes resources (CRDs, Pods, Secrets, etc.), always use a selector function instead of direct property chains.
10+
11+
## Common selectors (`@utils/crds/common/selectors`)
12+
13+
Available for all `K8sResourceCommon` resources:
14+
- `getName(resource)` instead of `resource?.metadata?.name`
15+
- `getNamespace(resource)` instead of `resource?.metadata?.namespace`
16+
- `getUID(resource)` instead of `resource?.metadata?.uid`
17+
- `getCreatedAt(resource)` instead of `resource?.metadata?.creationTimestamp`
18+
- `getLabels(resource)` instead of `resource?.metadata?.labels`
19+
- `getAnnotations(resource)` instead of `resource?.metadata?.annotations`
20+
- `getApiVersion(resource)` instead of `resource?.apiVersion`
21+
- `getKind(resource)` instead of `resource?.kind`
22+
23+
Provider-specific:
24+
- `getType(provider)` instead of `provider?.spec?.type`
25+
- `getProviderSecretRef(provider)` instead of `provider?.spec?.secret`
26+
- `getVddkInitImage(provider)` instead of `provider?.spec?.settings?.vddkInitImage`
27+
28+
## CRD-specific selectors
29+
30+
If a property access is specific to a CRD (e.g., Conversion, Plan), check for existing selectors under `@utils/crds/<crd>/selectors.ts`.
31+
32+
## When no selector exists
33+
34+
1. If the property is common to all K8s resources, add it to `src/utils/crds/common/selectors.ts`
35+
2. If the property is CRD-specific, add it to the CRD's selectors file under `src/utils/crds/<crd>/selectors.ts`
36+
3. Never access `metadata.*` or `spec.*` or `status.*` directly in component or hook code

cspell.wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ snapshotting
5555
hotplug
5656
RHVM
5757
metav
58+
moref
59+
mountpoint
60+
mountpoints
5861
tolerations
5962
Virtualmachine
6063
domainname

i18n-scripts.config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"languages": ["ja", "zh-cn", "ko", "fr", "es"],
66
"languageAliases": { "zh-cn": "zh" },
77
"pluralOverrides": {
8-
"{{count}} virtual machine selected_other": "{{count}} virtual machines selected"
8+
"{{count}} virtual machine selected_other": "{{count}} virtual machines selected",
9+
"Failed to create inspection for {{count}} VM_other": "Failed to create inspections for {{count}} VMs",
10+
"Inspect {{count}} VM_other": "Inspect {{count}} VMs"
911
}
1012
}

locales/en/plugin__forklift-console-plugin.json

Lines changed: 42 additions & 1 deletion
Large diffs are not rendered by default.

locales/es/plugin__forklift-console-plugin.json

Lines changed: 44 additions & 1 deletion
Large diffs are not rendered by default.

locales/fr/plugin__forklift-console-plugin.json

Lines changed: 44 additions & 1 deletion
Large diffs are not rendered by default.

locales/ja/plugin__forklift-console-plugin.json

Lines changed: 40 additions & 1 deletion
Large diffs are not rendered by default.

locales/ko/plugin__forklift-console-plugin.json

Lines changed: 40 additions & 1 deletion
Large diffs are not rendered by default.

locales/zh/plugin__forklift-console-plugin.json

Lines changed: 40 additions & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)