Skip to content

Add CRD detection guard and unit tests for Agones views#12

Open
NAME-ASHWANIYADAV wants to merge 6 commits into
agones-dev:mainfrom
NAME-ASHWANIYADAV:feat/crd-detection-guard
Open

Add CRD detection guard and unit tests for Agones views#12
NAME-ASHWANIYADAV wants to merge 6 commits into
agones-dev:mainfrom
NAME-ASHWANIYADAV:feat/crd-detection-guard

Conversation

@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor

Type of change

  • 🐛 Bug fix
  • 🚀 New feature / enhancement
  • 📖 Documentation
  • 🧹 Refactoring / cleanup
  • ⚙️ CI / tooling
  • ⚠️ Breaking change

What this PR does

This PR introduces a robust detection mechanism to verify if the Agones Custom Resource Definitions (CRDs) are installed on the active Kubernetes cluster before attempting to render Agones-specific UI views.

Key additions:

  • isAgonesInstalled utility: Queries the /apis/agones.dev/v1 endpoint and explicitly validates that the response is a valid Kubernetes APIResourceList.
  • useAgonesInstalled hook: A React hook to manage the asynchronous loading state.
  • AgonesInstallCheck wrapper component: Intercepts routes and is designed to display a helpful banner if the API is missing.
  • Route Wrapping: All Agones plugin routes in src/index.tsx are wrapped with this component.
  • Comprehensive Unit Tests: Vitest suite covers the API detection logic and hook completely. All tests pass successfully.

Screenshots / recordings

(I am currently facing a UI rendering issue locally. Attached are the screenshots showing minikube vs test-no-agones where the UI still renders the default view instead of the fallback banner).

image image

Test plan

Automated checks

  • npm ci
  • npm run build
  • npm run tsc
  • npm run lint
  • npm run format -- --check
  • npm run test

Manual verification

  • Tested in Headlamp against a cluster with Agones installed (minikube)
  • Verified on a cluster without Agones (test-no-agones)
    (See Notes for Reviewers regarding the local UI verification issue).

RBAC considerations

No additional RBAC permissions are required beyond what the plugin already needs.

Notes for reviewers

⚠️ Requesting some guidance on the UI rendering:
I have successfully implemented the logic, wrapped the components in index.tsx, and all automated unit tests pass perfectly.

However, when I test this locally on the Headlamp Desktop App (using my test-no-agones cluster), I am facing a weird issue: The isAgonesInstalled check should catch the missing API, but the UI still renders the default AgonesOverview component instead of my NotInstalledBanner (as seen in the second screenshot).

I suspect this might be related to how registerRoute handles wrapped components in Headlamp, or perhaps UI caching in the Desktop app (though I have cleared the .plugins cache).

I've opened this PR so you can review the code structure. Any pointers on why the route wrapper isn't displaying the fallback banner would be hugely appreciated!

@NAME-ASHWANIYADAV NAME-ASHWANIYADAV force-pushed the feat/crd-detection-guard branch from 13b713b to b33c7f0 Compare June 12, 2026 14:14
import { useEffect, useState } from 'react';
import { isAgonesInstalled as checkAgonesInstallation } from '../isAgonesInstalled';

export function useAgonesInstalled() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Please add some documentation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have added full TSDoc documentation for the hook with a description of the return object and a usage example👍

Comment thread src/hooks/useAgonesInstalled.tsx Outdated
*/

import { useEffect, useState } from 'react';
import { isAgonesInstalled as checkAgonesInstallation } from '../isAgonesInstalled';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why rename this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank for pointing this , I have removed it
The function is now called directly as isAgonesInstalled()

Comment thread src/isAgonesInstalled.ts Outdated

import { ApiProxy } from '@kinvolk/headlamp-plugin/lib';

export async function isAgonesInstalled(): Promise<boolean> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could this make more sense inside the useAgonesInstalled? I don't think it will be used anywhere else.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have moved the entire isAgonesInstalled() function into useAgonesInstalled.tsx and deleted this standalone file
I also clean up the debug console.log statements and update the mock strategy in the tests to work with this new structure

@NAME-ASHWANIYADAV NAME-ASHWANIYADAV requested a review from illume June 15, 2026 12:28
@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor Author

@illume @markmandel @lacroixthomas PTAL !!

@lacroixthomas lacroixthomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Otherwise LGTM

Comment thread src/index.tsx Outdated
Comment on lines +78 to +82
component: () => (
<AgonesInstallCheck>
<AgonesOverview />
</AgonesInstallCheck>
),

@lacroixthomas lacroixthomas Jun 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm pretty rusty about react, feel free to ignore me
I was wondering if it's a good pattern to have some kind of helper / wrapper for that as it's duplicated each time ? This way if we add some specific error banner or something it could be done only there ? 🤔

Something along these lines ?

const withInstallCheck = (Component: React.ComponentType) => () => (
  <AgonesInstallCheck>
    <Component />
  </AgonesInstallCheck>
)

then component: withInstallCheck(AgonesOverview)

WDYT ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hey @lacroixthomas! I have implemented the withInstallCheck HOC exactly as you suggested and refactored all the routes in src/index.tsx to use it
I also took the opportunity to resolve the recent merge conflicts in package.json caused by Dependabot, and rebased the branch to keep the history clean.
Thanks for the review! 🙏

Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor Author
Screenshot 2026-06-21 031857 Screenshot 2026-06-21 031925 The CRD detecting guard is now working properly 🎉🎉 will appreciate a re-review @illume @lacroixthomas @markmandel

@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor Author

@markmandel plz re-run ci

Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com>
@NAME-ASHWANIYADAV NAME-ASHWANIYADAV force-pushed the feat/crd-detection-guard branch from 7e26a22 to a450497 Compare June 21, 2026 18:22
@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor Author

@markmandel i have fixed the lint and formatting issues - could you approve the CI run ? Thanks! 🙏

@markmandel

Copy link
Copy Markdown
Member

Oh fun - there is the artifact download too. We should take it for a spin!

@NAME-ASHWANIYADAV

Copy link
Copy Markdown
Contributor Author

Perfect! Let me know if everything works as expected

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants