Skip to content

OCPBUGS-114021: Retry failed console plugin manifest fetches - #17108

Open
kchawlani19 wants to merge 1 commit into
openshift:mainfrom
kchawlani19:OCPBUGS-114021
Open

OCPBUGS-114021: Retry failed console plugin manifest fetches#17108
kchawlani19 wants to merge 1 commit into
openshift:mainfrom
kchawlani19:OCPBUGS-114021

Conversation

@kchawlani19

@kchawlani19 kchawlani19 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Analysis / Root cause:
Console fetches each dynamic plugin manifest once at page load via PluginStore.loadPlugin. If that fetch fails — commonly a 401 when the request lands on a console replica that does not have the OAuth session — the loader never retries. The plugin's UI is missing for the rest of the browser session; only a full reload recovers it. PluginStore does not register the plugin until the manifest is fetched, so a retry is a clean second attempt rather than a reload of a failed plugin.

Solution description:
loadAndEnablePlugin now retries the manifest load up to 3 times (same budget as coFetch) when the failure is transient: 401, 408, 429, 5xx, timeouts, and network TypeErrors. Permanent errors such as 404/403 are not retried. Intermediate failures log a warning; onError is called only after the last attempt.

Fixes https://issues.redhat.com/browse/OCPBUGS-114021

Screenshots / screen recording:
N/A — plugin load retry; no visual/layout change when the fetch succeeds.

Test setup:
OpenShift web console with at least one dynamic plugin enabled (for example monitoring-plugin).

Test cases:

  • Load the console normally; dynamic plugins still appear.
  • In DevTools, block the first request to /api/plugins/<plugin>/plugin-manifest.json, reload, then unblock; the plugin should appear without a second full reload.
  • Confirm a genuine missing plugin (404) is still not retried forever and does not load.

Browser conformance:

  • Chrome
  • Firefox
  • Safari (or Epiphany on Linux)

Additional info:
Unit tests cover retry-then-success for 401 and network errors, giving up after 3 attempts, skipping non-transient errors, and the existing disableStaticPlugins behavior.

Reviewers and assignees:

Summary by CodeRabbit

  • New Features

    • Plugin manifest loading now automatically retries transient failures, such as timeouts and temporary server errors.
    • Plugin errors are reported only after all retry attempts are exhausted.
    • Plugins that cannot be loaded are correctly marked as failed.
  • Bug Fixes

    • Improved handling of dynamic and static plugin states during plugin loading.

A 401 from a console replica that does not have the session, or a
transient network error, left the plugin unloaded for the rest of
the browser session. Retry the manifest load so the plugin can
recover without a full page reload.

Fixes https://issues.redhat.com/browse/OCPBUGS-114021
@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-robot openshift-ci-robot added jira/severity-low Referenced Jira bug's severity is low for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Aug 29, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@kchawlani19: This pull request references Jira Issue OCPBUGS-114021, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.1.0) matches configured target version for branch (5.1.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Analysis / Root cause:
Console fetches each dynamic plugin manifest once at page load via PluginStore.loadPlugin. If that fetch fails — commonly a 401 when the request lands on a console replica that does not have the OAuth session — the loader never retries. The plugin's UI is missing for the rest of the browser session; only a full reload recovers it. PluginStore does not register the plugin until the manifest is fetched, so a retry is a clean second attempt rather than a reload of a failed plugin.

Solution description:
loadAndEnablePlugin now retries the manifest load up to 3 times (same budget as coFetch) when the failure is transient: 401, 408, 429, 5xx, timeouts, and network TypeErrors. Permanent errors such as 404/403 are not retried. Intermediate failures log a warning; onError is called only after the last attempt.

Fixes https://issues.redhat.com/browse/OCPBUGS-114021

Screenshots / screen recording:
N/A — plugin load retry; no visual/layout change when the fetch succeeds.

Test setup:
OpenShift web console with at least one dynamic plugin enabled (for example monitoring-plugin).

Test cases:

  • Load the console normally; dynamic plugins still appear.
  • In DevTools, block the first request to /api/plugins/<plugin>/plugin-manifest.json, reload, then unblock; the plugin should appear without a second full reload.
  • Confirm a genuine missing plugin (404) is still not retried forever and does not load.

Browser conformance:

  • Chrome
  • Firefox
  • Safari (or Epiphany on Linux)

Additional info:
Unit tests cover retry-then-success for 401 and network errors, giving up after 3 attempts, skipping non-transient errors, and the existing disableStaticPlugins behavior.

Reviewers and assignees:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8208d4b4-3b77-4563-a283-9420c433cf45

📥 Commits

Reviewing files that changed from the base of the PR and between 0c48df3 and 96b5f8a.

📒 Files selected for processing (2)
  • frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-init.spec.ts
  • frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-init.ts

Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review.


Walkthrough

Changes

Plugin manifest retry handling

Layer / File(s) Summary
Retryable manifest error classification
frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-init.ts, frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-init.spec.ts
The runtime exports the retry limit and identifies retryable HTTP statuses, timeout errors, type errors, and errors in a cause chain. Tests cover retryable and non-retryable errors.
Bounded plugin manifest loading
frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-init.ts, frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-init.spec.ts
loadAndEnablePlugin retries transient manifest failures up to three attempts, reports final failures, constructs manifest URLs from basePath, and preserves static-plugin disabling behavior. Tests cover success, exhaustion, non-retryable errors, failed plugin status, and disabling rules.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 96b5f

The change retries transient dynamic-plugin manifest fetch failures while preserving no-retry behavior for permanent errors, improving plugin availability after temporary network or session issues; no actionable merge-blocking risk remains at the current head beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant loadAndEnablePlugin
  participant PluginStore
  participant onError

  loadAndEnablePlugin->>PluginStore: loadPlugin(manifest URL)
  PluginStore-->>loadAndEnablePlugin: transient failure
  loadAndEnablePlugin->>PluginStore: retry loadPlugin
  PluginStore-->>loadAndEnablePlugin: success or final failure
  loadAndEnablePlugin->>onError: report final failure
Loading

Suggested reviewers: vojtechszocs, logonoff


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error The new retry warning logs error.cause ?? error directly at plugin-init.ts:93-96. PluginStore uses coFetch; its HttpError can contain the original Response and parsed JSON body, and `Timeo… Do not pass the raw error, cause, Response, parsed JSON, or full URL to console.warn. Log only an allowlisted status code and static retry metadata. Sanitize any URL to a relative, fixed manifest path before logging. Add a test that ass…
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the Jira issue and the main change: retrying failed console plugin manifest fetches.
Description check ✅ Passed The description is relevant and mostly complete. It explains the root cause, solution, test setup, test cases, browser conformance section, and additional information. The browser selections and revie…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All added Jest test titles are stable literals. The two parameterized titles use fixed table labels (HTTP status codes and fixed error type names), so they do not vary between runs. Plugin names, URLs…
Test Structure And Quality ✅ Passed PASS — the changed test is a TypeScript Jest test, not Ginkgo code. The diff adds plugin-init.spec.ts with describe/it, Jest mocks, and beforeEach/afterEach; it creates no cluster resources …
Microshift Test Compatibility ✅ Passed PASS: The pull request changes only frontend TypeScript files. The added plugin-init.spec.ts is a Jest unit test, not a Ginkgo e2e test. It uses mocked PluginStore behavior and does not reference …
Single Node Openshift (Sno) Test Compatibility ✅ Passed PASS — The pull request adds TypeScript/Jest unit tests in plugin-init.spec.ts and changes TypeScript runtime code. It adds no Go or Ginkgo e2e tests (It, Describe, Context, or When in the G…
Topology-Aware Scheduling Compatibility ✅ Passed PASS — The pull request changes only TypeScript runtime logic and its unit test: plugin-init.ts and plugin-init.spec.ts. The diff adds plugin-manifest retry handling and no deployment manifests, o…
Ote Binary Stdout Contract ✅ Passed PASS — The pull request changes only two TypeScript files under the frontend dynamic-plugin SDK. The diff contains no Go OTE binary, main/init, Ginkgo suite setup, or process-level stdout code. Its `c…
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PASS: The pull request adds a Jest/TypeScript unit test (plugin-init.spec.ts), not a new Ginkgo e2e test. The test uses a mocked PluginStore and has no public-host connectivity. Its expected `http…
No-Weak-Crypto ✅ Passed The pull request adds retry handling, HTTP status classification, error-cause traversal, and unit tests. The changed files contain no MD5, SHA1, DES, 3DES, RC4, Blowfish, ECB, crypto API, custom crypt…
Container-Privileges ✅ Passed PASS: The pull request changes only two TypeScript files: plugin-init.ts and its unit test. The exact diff adds no container or Kubernetes manifest and contains no privileged, hostPID, `hostNetw…
Full details: Description check

Explanation

The description is relevant and mostly complete. It explains the root cause, solution, test setup, test cases, browser conformance section, and additional information. The browser selections and reviewer assignments remain incomplete, but these omissions are non-critical for this change.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

Full details: Stable And Deterministic Test Names

Explanation

All added Jest test titles are stable literals. The two parameterized titles use fixed table labels (HTTP status codes and fixed error type names), so they do not vary between runs. Plugin names, URLs, and error values appear in test bodies or fixed assertions, not as runtime-generated title data. No title contains a timestamp, UUID, generated suffix, node or namespace name, IP address, or other run-dependent value.

Full details: Test Structure And Quality

Explanation

PASS — the changed test is a TypeScript Jest test, not Ginkgo code. The diff adds plugin-init.spec.ts with describe/it, Jest mocks, and beforeEach/afterEach; it creates no cluster resources and uses no Eventually or Consistently calls. Therefore the Ginkgo-specific quality check is not applicable.

Full details: Microshift Test Compatibility

Explanation

PASS: The pull request changes only frontend TypeScript files. The added plugin-init.spec.ts is a Jest unit test, not a Ginkgo e2e test. It uses mocked PluginStore behavior and does not reference OpenShift APIs, MicroShift-incompatible namespaces, or unsupported cluster assumptions. The MicroShift Test Compatibility check therefore does not apply.

Full details: Single Node Openshift (Sno) Test Compatibility

Explanation

PASS — The pull request adds TypeScript/Jest unit tests in plugin-init.spec.ts and changes TypeScript runtime code. It adds no Go or Ginkgo e2e tests (It, Describe, Context, or When in the Ginkgo sense), and the changed code contains no node, topology, scheduling, or HA assumptions. The SNO compatibility check is therefore not applicable.

Full details: Topology-Aware Scheduling Compatibility

Explanation

PASS — The pull request changes only TypeScript runtime logic and its unit test: plugin-init.ts and plugin-init.spec.ts. The diff adds plugin-manifest retry handling and no deployment manifests, operator/controller code, replica settings, affinity, topology spread, node selectors, tolerations, or PDBs. The topology-aware scheduling check is therefore not applicable.

Full details: Ote Binary Stdout Contract

Explanation

PASS — The pull request changes only two TypeScript files under the frontend dynamic-plugin SDK. The diff contains no Go OTE binary, main/init, Ginkgo suite setup, or process-level stdout code. Its console.warn and existing console.error calls are JavaScript runtime logging, not the OTE binary stdout contract.

Full details: Ipv6 And Disconnected Network Test Compatibility

Explanation

PASS: The pull request adds a Jest/TypeScript unit test (plugin-init.spec.ts), not a new Ginkgo e2e test. The test uses a mocked PluginStore and has no public-host connectivity. Its expected http://localhost/... value is a URL string only; it is not the prohibited hardcoded IPv4 address 127.0.0.1. No IPv4-only parsing, CIDRs, IP interpolation, or external service access was introduced.

Full details: No-Weak-Crypto

Explanation

The pull request adds retry handling, HTTP status classification, error-cause traversal, and unit tests. The changed files contain no MD5, SHA1, DES, 3DES, RC4, Blowfish, ECB, crypto API, custom cryptography, secret/token comparison, or timing-sensitive comparison logic.

Full details: Container-Privileges

Explanation

PASS: The pull request changes only two TypeScript files: plugin-init.ts and its unit test. The exact diff adds no container or Kubernetes manifest and contains no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation setting. The container-privileges check is not applicable.

Full details: No-Sensitive-Data-In-Logs

Explanation

The new retry warning logs error.cause ?? error directly at plugin-init.ts:93-96. PluginStore uses coFetch; its HttpError can contain the original Response and parsed JSON body, and TimeoutError contains the full request URL. The URL uses the browser origin, which can reveal an internal hostname. A transient failure that later succeeds now logs this raw error even though onError is not called. This matches the check condition for possible exposure of internal hostnames or response/customer data.

Resolution

Do not pass the raw error, cause, Response, parsed JSON, or full URL to console.warn. Log only an allowlisted status code and static retry metadata. Sanitize any URL to a relative, fixed manifest path before logging. Add a test that asserts the warning arguments do not contain the error object or its response/body.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@openshift-ci
openshift-ci Bot requested review from cajieh and jhadvig August 29, 2026 15:20
@openshift-ci openshift-ci Bot added the component/sdk Related to console-plugin-sdk label Aug 29, 2026
@openshift-ci

openshift-ci Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: kchawlani19
Once this PR has been reviewed and has the lgtm label, please assign logonoff 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

@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@kchawlani19: This pull request references Jira Issue OCPBUGS-114021, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.1.0) matches configured target version for branch (5.1.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

Analysis / Root cause:
Console fetches each dynamic plugin manifest once at page load via PluginStore.loadPlugin. If that fetch fails — commonly a 401 when the request lands on a console replica that does not have the OAuth session — the loader never retries. The plugin's UI is missing for the rest of the browser session; only a full reload recovers it. PluginStore does not register the plugin until the manifest is fetched, so a retry is a clean second attempt rather than a reload of a failed plugin.

Solution description:
loadAndEnablePlugin now retries the manifest load up to 3 times (same budget as coFetch) when the failure is transient: 401, 408, 429, 5xx, timeouts, and network TypeErrors. Permanent errors such as 404/403 are not retried. Intermediate failures log a warning; onError is called only after the last attempt.

Fixes https://issues.redhat.com/browse/OCPBUGS-114021

Screenshots / screen recording:
N/A — plugin load retry; no visual/layout change when the fetch succeeds.

Test setup:
OpenShift web console with at least one dynamic plugin enabled (for example monitoring-plugin).

Test cases:

  • Load the console normally; dynamic plugins still appear.
  • In DevTools, block the first request to /api/plugins/<plugin>/plugin-manifest.json, reload, then unblock; the plugin should appear without a second full reload.
  • Confirm a genuine missing plugin (404) is still not retried forever and does not load.

Browser conformance:

  • Chrome
  • Firefox
  • Safari (or Epiphany on Linux)

Additional info:
Unit tests cover retry-then-success for 401 and network errors, giving up after 3 attempts, skipping non-transient errors, and the existing disableStaticPlugins behavior.

Reviewers and assignees:

Summary by CodeRabbit

  • New Features

  • Plugin manifest loading now automatically retries transient failures, such as timeouts and temporary server errors.

  • Plugin errors are reported only after all retry attempts are exhausted.

  • Plugins that cannot be loaded are correctly marked as failed.

  • Bug Fixes

  • Improved handling of dynamic and static plugin states during plugin loading.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

@kchawlani19: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/sdk Related to console-plugin-sdk jira/severity-low Referenced Jira bug's severity is low for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants