Skip to content

frontend: useKubeObject: probe endpoints with GET-by-name instead of List#4696

Open
Kaniikura wants to merge 2 commits intokubernetes-sigs:mainfrom
Kaniikura:fix/4674-use-get-probe-for-single-resource
Open

frontend: useKubeObject: probe endpoints with GET-by-name instead of List#4696
Kaniikura wants to merge 2 commits intokubernetes-sigs:mainfrom
Kaniikura:fix/4674-use-get-probe-for-single-resource

Conversation

@Kaniikura
Copy link

@Kaniikura Kaniikura commented Feb 12, 2026

Summary

This PR fixes useKubeObject failing when a user has get permission but lacks list permission, by switching endpoint probing from collection-URL LIST to name-based GET for single-resource views.

Related Issue

Fixes #4674

Changes

  • Updated useKubeObject to pass name and namespace to useEndpoints, so endpoint discovery uses a name-specific GET request (/deployments/demo) instead of a collection GET (/deployments) that Kubernetes authorizes as the list verb
  • Added getFirstWorkingGetEndpoint — parallel GET-by-name probing strategy for single-resource views
  • Renamed the existing probing logic to getFirstWorkingListEndpoint for clarity
  • Added hooks.test.tsx with 7 tests covering both probing strategies and edge cases

Steps to Test

  1. Create a Kubernetes Role granting only get (not list) permission on a resource (e.g., Deployments) and bind it to a user
  2. Log in to Headlamp as that user
  3. Navigate directly to the detail page of a specific resource (e.g., /c/my-cluster/apps/v1/Deployment/default/my-deployment)
  4. Verify the page loads successfully without a 403 error
  5. Verify that list views (e.g., Deployments list) still work correctly for users who have list permission

Screenshots (if applicable)

N/A — no UI changes; the fix is in the endpoint probing logic.

Notes for the Reviewer

  • The existing listProbe mode (used by useKubeObjectList) is unchanged in behavior — the new getProbe mode is only used by useKubeObject for single-resource detail views

@k8s-ci-robot k8s-ci-robot requested review from illume and sniok February 12, 2026 15:41
@k8s-ci-robot
Copy link
Contributor

Welcome @Kaniikura!

It looks like this is your first PR to kubernetes-sigs/headlamp 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/headlamp has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Feb 12, 2026
@illume illume requested a review from Copilot February 12, 2026 15:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the frontend Kubernetes API v2 endpoint resolution logic so useKubeObject can load single-resource detail views for users who have get RBAC permission but not list, by probing candidate endpoints with GET-by-name instead of collection LIST.

Changes:

  • Switch useKubeObject to call useEndpoints with { mode: 'getProbe', name } (and namespace) to avoid RBAC list authorization during endpoint discovery.
  • Add GET-by-name probing (getFirstWorkingGetEndpoint) alongside the existing list-based probing (getFirstWorkingListEndpoint) and unify probe error selection via throwMostRelevantError.
  • Add a new hooks.test.tsx suite covering both probing modes and error prioritization behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
frontend/src/lib/k8s/api/v2/hooks.ts Implements get-by-name endpoint probing, updates useKubeObject to use it, and adjusts probing/error selection logic.
frontend/src/lib/k8s/api/v2/hooks.test.tsx Adds unit tests validating getProbe/listProbe behavior, error precedence, and configuration edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@sniok sniok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi, thanks for opening a PR, I've left a couple of comments

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Feb 12, 2026
@Kaniikura Kaniikura requested a review from sniok February 13, 2026 04:33
@illume illume requested a review from Copilot February 13, 2026 11:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@illume illume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, thanks.

Can you please update the commit messages after the first one to match the git commit guidelines?

Also, please remove the revert commit by rebasing. We aim to have atomic commits, and within a single PR not have fixes for previous commits in the same PR. Instead rebase the fixes into existing commits.

@Kaniikura Kaniikura force-pushed the fix/4674-use-get-probe-for-single-resource branch from b916517 to ebf9954 Compare February 13, 2026 13:31
@Kaniikura
Copy link
Author

Thanks for the feedback.

I've cleaned up the commit history and updated the messages as requested. I also added the test case for cluster-scoped resources.

Force-pushed the updates. Let me know if anything else is needed!

@Kaniikura Kaniikura requested a review from illume February 13, 2026 13:36
@illume
Copy link
Contributor

illume commented Feb 13, 2026

A little nit, we use Capitals at the start of the git subject after the context...
For example:

frontend: multiplexer: Cancel pending timers in test teardown

Copy link
Contributor

@illume illume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 🎉

(I'll leave it open a while longer to give someone else a chance to have a look. Please ask in the headlamp channel on the Kubernetes slack for a review?)

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: illume, Kaniikura

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

The pull request process is described 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

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 13, 2026
@Kaniikura Kaniikura force-pushed the fix/4674-use-get-probe-for-single-resource branch from ebf9954 to 4acec81 Compare February 13, 2026 15:00
@Kaniikura
Copy link
Author

Updated commit subjects to follow the capitalization guideline after the prefix. No code changes.

@Kaniikura
Copy link
Author

Thanks for the suggestion to ask in Slack!
I’ve posted a review request in the Kubernetes #headlamp

Copy link
Contributor

@sniok sniok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating pr. I left just one final comment

…List

Updates the frontend Kubernetes API v2 endpoint resolution logic so useKubeObject can load single-resource detail views for users who have get RBAC permission but not list, by probing candidate endpoints with GET-by-name instead of collection LIST.
The afterEach in multiplexer.test.ts called
pendingUnsubscribes.clear() without cancelling the stored timeouts.
This left orphaned setTimeout callbacks that could fire after vitest
tore down the jsdom environment, causing a sporadic
"ReferenceError: WebSocket is not defined".

Call forEach(clearTimeout) before clear() so all pending debounce
timers are cancelled before the test environment is destroyed.
@Kaniikura Kaniikura force-pushed the fix/4674-use-get-probe-for-single-resource branch from 4acec81 to a469b7a Compare February 13, 2026 23:26
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

frontend/src/lib/k8s/api/v2/hooks.ts:251

  • The PR description mentions adding separate functions getFirstWorkingGetEndpoint and renaming the existing logic to getFirstWorkingListEndpoint, but the actual implementation uses a single getWorkingEndpoint function with conditional logic based on whether name is provided. While the implementation is cleaner and works correctly, the description should be updated to match the actual code changes.
const getWorkingEndpoint = async (
  endpoints: KubeObjectEndpoint[],
  cluster: string,
  namespace?: string,
  name?: string
) => {
  const promises = endpoints.map(endpoint => {
    const resourceUrl = KubeObjectEndpoint.toUrl(endpoint, namespace);
    // If a name is provided, we probe for that specific resource.
    // Otherwise we probe for the list of resources.
    const url = name ? makeUrl([resourceUrl, name]) : resourceUrl;

    return clusterFetch(url, {
      method: 'GET',
      cluster: cluster ?? getCluster() ?? '',
    }).then(() => endpoint);
  });

  return Promise.any(promises).catch((aggregateError: AggregateError) => {
    // when no endpoint is available, throw an error
    throw aggregateError.errors[0];
  });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] useGet fails when user has 'get' permission but lacks 'list' permission

4 participants