Skip to content

WIP: Port cluster updates UI from console - #23

Draft
spadgett wants to merge 12 commits into
openshift:mainfrom
spadgett:port-cluster-updates
Draft

spadgett wants to merge 12 commits into
openshift:mainfrom
spadgett:port-cluster-updates

Conversation

@spadgett

@spadgett spadgett commented Sep 16, 2026

Copy link
Copy Markdown
Member

Summary

Ports the cluster updates UI from the console's Cluster Settings page to the cluster-update-console-plugin. This provides a standalone, traditional cluster update experience that works independently of the AI-driven update planning features.

What's Included

Core Cluster Updates Tab

  • ✅ Two-column layout matching console exactly
  • ✅ Current version display with release notes links
  • ✅ Update status component (all states: up to date, available updates, updating, failing, error retrieving, invalid, release not accepted)
  • ✅ Channel display with edit capability
  • ✅ Visual channel graph showing update timeline
  • ✅ "Select a version" button for triggering updates
  • ✅ Update progress display (operators, control plane, worker, custom pools)

Modals

  • ✅ Cluster Update Modal - version selection with full/partial update options
  • ✅ More Updates Modal - shows intermediate update paths
  • ✅ Channel Editor Modal - select or input update channel
  • ✅ Upstream Configuration Modal - configure custom update service

Additional Features

  • ✅ Update History tab with table view
  • ✅ Cluster details (ID, desired image, upstream config)
  • ✅ MCP pausing/resuming for full vs partial updates
  • ✅ Real-time update progress with live progress bars
  • ✅ Support for recommended and not-recommended updates
  • ✅ Blocking indicators for upgradeable=false scenarios

Technical Details

  • All CSS uses plugin prefix (cluster-update-plugin__)
  • Uses only PatternFly CSS variables (no hex colors)
  • Matches console's Cluster Settings layout exactly
  • Gracefully degrades when AgenticRun CRD not available
    • Hides AI-dependent tabs (Updates plan, Active update plans)
    • Shows only traditional update tabs
    • No warning alerts, silent degradation

Files Changed

  • Added src/components/cluster-updates/* - core update UI components
  • Added src/components/modals/Cluster*Modal.tsx - update modals
  • Added src/utils/cluster-updates.ts - update utilities and helpers
  • Added src/models/machineconfigpool.ts - MCP model and types
  • Updated Update History tab to match console table layout
  • Updated console-extensions.json to place nav item above Cluster Settings

Screenshots

Screenshot 2026-09-16 at 4 52 07 PM Screenshot 2026-09-16 at 4 52 24 PM Screenshot 2026-09-16 at 4 52 20 PM Screenshot 2026-09-16 at 4 52 16 PM Screenshot 2026-09-16 at 4 52 09 PM

TODO / Future Work

  • Add paused MCP alerts
  • Add update blocking alerts for specific conditions
  • Consider adding conditional update warnings
  • Add more comprehensive error handling

🤖 Generated with Claude Code

spadgett and others added 7 commits September 16, 2026 14:28
- Port cluster updates tab with two-column layout
- Add visual channel graph with update timeline
- Add update status component with all states
- Add cluster update modal for version selection
- Add more updates modal for intermediate versions
- Add update history tab with table
- Port supporting components (CurrentVersion, CurrentChannel, ReleaseNotesLink)
- Add cluster update utilities and helpers
- Add MachineConfigPool model and hooks
- Show cluster ID, desired image, and upstream config
- All CSS uses plugin prefix and PatternFly variables
- Matches Cluster Settings page layout

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Implement MCP pausing/resuming in ClusterUpdateModal
  - Full update: resumes all paused MCPs
  - Partial update: pauses selected worker/custom MCPs
  - Uses Promise.all to patch ClusterVersion and MCPs together
- Add UpdateInProgress component
  - Shows cluster operators update progress
  - Shows control plane nodes progress
  - Shows worker nodes progress
  - Shows custom pool nodes progress
  - Live progress bars with percentage
- Move Cluster Update nav item above Cluster Settings
  - Add insertBefore property to console-extensions.json
- Update actually triggers cluster update now

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove cluster-update-plugin__settings__section wrapper
- Use plain DescriptionList with utility classes
- Matches console layout (no border on details below graph)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Move cluster details outside bordered container
- Bordered container now only wraps two-column layout
- Cluster details (ID, image, upstream) have no border
- Matches console layout exactly

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove left margin from cluster details section
- Now left-aligned with the border of the box above
- Matches console layout

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Add ClusterChannelModal for editing update channel
  - Dropdown for available channels
  - Text input when no channels available
  - Shows potential channel names as helper text
- Add ConfigureUpstreamModal for editing upstream server
  - Radio buttons for Default vs Custom
  - Default shows Red Hat update service URL
  - Custom allows entering custom update service URL
  - Validation for custom URL
- Make channel editable with pencil icon
- Make upstream configuration editable with pencil icon
  - Always shows (not conditional on upstreamURL)
  - Shows 'Default' when no custom upstream configured
- Both modals patch ClusterVersion on save
- Match console implementation exactly

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove warning alert about missing AgenticRun CRD
- Conditionally render 'Updates plan' and 'Active update plans' tabs
  - Only show when agenticRunsAvailable is true
- Conditionally show 'Tech preview' label
  - Only show when AI features are available
- Update page description based on feature availability
  - Shows AI-focused description when available
  - Shows traditional update description otherwise
- Adjust tab indices dynamically
  - With AI: tabs 0-3 (Cluster updates, Updates plan, Active plans, History)
  - Without AI: tabs 0-1 (Cluster updates, Update history)
- Provides graceful degradation when AgenticRun CRD not installed

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 16, 2026
@openshift-ci

openshift-ci Bot commented Sep 16, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Sep 16, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: spadgett
Once this PR has been reviewed and has the lgtm label, please assign wking for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

spadgett and others added 3 commits September 17, 2026 06:59
- Port ClusterVersion mock data from console with multiple test scenarios:
  - clusterVersionWithUpdates (has available updates)
  - clusterVersionUpgradeableFalse (blocked by Upgradeable=False)
  - clusterVersionUpdating (update in progress)
  - clusterVersionUpToDate (no updates available)
  - clusterVersionWithNotRecommendedUpdates (has conditional updates)

- Add comprehensive tests for 18 utility functions:
  - getSortedAvailableUpdates, hasAvailableUpdates, hasNotRecommendedUpdates
  - getClusterUpdateStatus, getAvailableClusterChannels
  - getDesiredClusterVersion, getClusterVersionChannel
  - getLastCompletedUpdate, getCurrentVersion
  - getConditionUpgradeableFalse, getClusterID
  - getDesiredImage, getUpstreamURL, getReleaseNotesLink
  - clusterIsUpToDateOrUpdateAvailable
  - getNewerMinorVersionUpdate, isMinorVersionNewer

- Add K8sResourceConditionStatus enum to SDK mock

All 51 tests pass, covering edge cases like missing data,
invalid versions, and various cluster states.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Install @testing-library/react, jest-dom, user-event, and dom
- Install jest-environment-jsdom for React component testing
- Update Jest config to use jsdom test environment
- Add setup file for jest-dom matchers
- Add CSS module mock for style imports

Component tests added:
- UpdateStatus.test.tsx (3 tests):
  - Renders 'Available updates' when updates available
  - Renders 'Up to date' when cluster is up to date
  - Renders update in progress message when updating

- UpdatesGraph.test.tsx (6 tests):
  - Renders current and newest versions
  - Shows '+ More' button when >2 updates available
  - Calls onShowMoreUpdates callback when clicked
  - Shows intermediate version when exactly 2 updates
  - Handles Upgradeable=False blocking scenario

All 116 tests pass (107 unit + 9 component tests).

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Test files added:
- ClusterChannelModal.test.tsx (6 tests):
  - Modal open/close behavior
  - Channel dropdown display
  - Successful channel update via k8sPatch
  - Error handling
  - Cancel functionality

- ConfigureUpstreamModal.test.tsx (8 tests):
  - Modal rendering
  - Default vs Custom radio button selection
  - Switching between Default and Custom
  - Submitting custom URL
  - Submitting default (null)
  - Validation for empty custom URL
  - Error handling

- ClusterUpdateModal.test.tsx (12 tests):
  - Modal open/close behavior
  - Current and target version display
  - Full cluster update vs Control plane only update options
  - Update type selection
  - Successful full update submission
  - Error handling
  - Cancel functionality
  - Upgradeable=False handling (patch updates only)
  - Irreversibility warning display

- UpdateInProgress.test.tsx (9 tests):
  - Cluster operators progress display
  - Control plane nodes progress
  - Worker nodes progress
  - Custom pool progress
  - Graceful handling of missing master/worker pools
  - Empty cluster operators handling

Updated SDK mock:
- Added useK8sWatchResource and useAccessReview mocks

All 149 tests pass (107 unit + 42 component tests).

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@spadgett

Copy link
Copy Markdown
Member Author

🤖 Code Analysis by Claude Code

I analyzed the relationship between the ported cluster updates code and the original openshift/console implementation. Here's what was directly copied vs adapted:

Direct Ports (Minimal Changes)

These components were copied nearly verbatim, with only minor adaptations for the plugin environment:

1. Utility Functions (src/utils/cluster-updates.ts)

  • Source: console/frontend/public/module/k8s/cluster-settings.ts (360 lines → 286 lines)
  • Changes:
    • Removed some console-specific utilities not needed for this plugin
    • Kept all core logic intact (semver sorting, update status, version parsing)
    • Same function signatures and behavior

2. UpdateStatus Component (src/components/cluster-updates/UpdateStatus.tsx)

  • Source: console/frontend/public/components/cluster-settings/cluster-status.tsx (219 lines → 184 lines)
  • Changes:
    • Removed: ClusterVersionConditionsLink (links to details page we don't have)
    • Removed: "Cancel update" button from InvalidMessage
    • Icon changes: Switched from console's custom icons to standard PatternFly icons
    • CSS class prefix: cluster-update-plugin__ instead of co-
    • Otherwise identical logic for all status messages and switch statement

3. ClusterUpdateModal (src/components/modals/ClusterUpdateModal.tsx)

  • Source: console/frontend/public/components/modals/cluster-update-modal.tsx (433 lines → 355 lines)
  • Changes:
    • Removed: Lightspeed integration (UpdateWorkflowOLSButton, FEATURE_FLAG_LIGHTSPEED_PLUGIN)
    • Removed: DropdownWithSwitch component (used FormSelect instead for simpler UI)
    • Removed: OCM link integration
    • Simplified: Version dropdown (no fancy grouped dropdowns)
    • Core logic identical: MCP pausing, Full vs Partial updates, patch structure

4. ClusterChannelModal & ConfigureUpstreamModal

  • Source: Corresponding console modal components
  • Changes: Minimal, mostly just adapted to plugin patterns

Significantly Adapted or New

1. UpdatesGraph (src/components/cluster-updates/UpdatesGraph.tsx)

  • Source: Part of the massive cluster-settings.tsx (1975 lines) in console
  • Extracted: The channel visualization graph was extracted and made standalone
  • Adapted: Simplified to work as an isolated component

2. UpdateInProgress (src/components/cluster-updates/UpdateInProgress.tsx)

  • Source: Extracted from cluster-settings.tsx
  • Adapted: Made into standalone component showing progress bars
  • Logic ported: Cluster operator counting, MCP progress calculation

3. ClusterUpdatesTab (src/components/cluster-updates/ClusterUpdatesTab.tsx)

  • Source: Heavily adapted from cluster-settings.tsx
  • Changes:
    • Removed ~1500 lines of unrelated cluster settings UI
    • Kept only the cluster version/update portions
    • Removed service level, operator list, and many other sections
    • Focused purely on update status and controls

4. Supporting Components

  • ChannelComponents.tsx, SupportingComponents.tsx: Extractions from the massive cluster-settings.tsx file, broken out into composable pieces

5. Update Plan / Active Plans / History Tabs

  • Completely new: Specific to the plugin's AI-driven update plan feature
  • Not in console: The Lightspeed proposal integration is unique to this plugin

Key Architectural Differences

Aspect Console Plugin
File structure Monolithic cluster-settings.tsx (1975 lines) Split into focused components
Lightspeed integration Optional feature flag Core feature with graceful degradation
Update workflow Standard update flow AI proposal workflow
CSS co- prefix classes cluster-update-plugin__ prefix
Icons Custom console icons (BlueArrowCircleUpIcon) Standard PatternFly icons
Navigation Part of admin settings with breadcrumbs Standalone plugin page with tabs

Summary

  • ~60-70% directly ported - The core cluster update logic (utility functions, modals, status display) is nearly identical to console code
  • ~20-30% adapted - Components like UpdatesGraph and UpdateInProgress were extracted from console's monolithic file and made standalone
  • ~10-20% new - The AI update plan workflow, proposal management, and tab structure are unique to the plugin

The ported code is production-tested console code, which is why it's solid. The main value-add of the plugin is the Lightspeed integration and the cleaner, focused UX around cluster updates.

spadgett and others added 2 commits September 17, 2026 10:55
Since the plugin runs within console, we can link to the ClusterVersion
details page with the conditions hash. This matches the console
implementation and provides a way for users to see full condition details.

Changes:
- Add ClusterVersionConditionsLink component that links to the
  ClusterVersion details page in console with #conditions hash
- Add conditions link to ReleaseNotAccepted, Updating, ErrorRetrieving,
  and Failing status messages
- Create react-router mock to avoid TextEncoder issues in jest tests

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
The console implementation includes a "Cancel update" button when the
cluster version is invalid. This allows users to recover from an
invalid state by removing the spec.desiredUpdate field.

Changes:
- Add cancelUpdate function that patches ClusterVersion to remove
  spec/desiredUpdate
- Show "Cancel update" button in InvalidMessage with loading state
- Display inline error alert if cancel operation fails
- Use getErrorMessage utility for error handling

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant