From c47bbc0c55ae23063f44c68547255d03111c14d3 Mon Sep 17 00:00:00 2001 From: ashwani yadav <22ashwaniyadav@gmail.com> Date: Fri, 12 Jun 2026 17:24:24 +0530 Subject: [PATCH 1/4] plugin: Add CRD detection guard for Agones sidebar views Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com> --- src/components/AgonesInstallCheck.tsx | 77 +++++++++++++++++++++++++++ src/hooks/useAgonesInstalled.tsx | 35 ++++++++++++ src/index.tsx | 43 ++++++++++++--- src/isAgonesInstalled.ts | 28 ++++++++++ 4 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 src/components/AgonesInstallCheck.tsx create mode 100644 src/hooks/useAgonesInstalled.tsx create mode 100644 src/isAgonesInstalled.ts diff --git a/src/components/AgonesInstallCheck.tsx b/src/components/AgonesInstallCheck.tsx new file mode 100644 index 0000000..5251cd1 --- /dev/null +++ b/src/components/AgonesInstallCheck.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Contributors to Agones a Series of LF Projects, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Box from '@mui/material/Box'; +import CircularProgress from '@mui/material/CircularProgress'; +import Grid from '@mui/material/Grid'; +import Link from '@mui/material/Link'; +import Typography from '@mui/material/Typography'; +import React from 'react'; +import { useAgonesInstalled } from '../hooks/useAgonesInstalled'; + +interface NotInstalledBannerProps { + isLoading?: boolean; +} + +function NotInstalledBanner({ isLoading = false }: NotInstalledBannerProps) { + if (isLoading) { + return ( + + + + ); + } + + return ( + + + + + Agones was not detected on your cluster. If you haven't already, please install it. + + + + + Learn how to{' '} + + install + {' '} + Agones + + + + + ); +} + +interface AgonesInstallCheckProps { + children: React.ReactNode; + fallback?: React.ReactNode; +} + +export function AgonesInstallCheck({ children, fallback }: AgonesInstallCheckProps) { + const { isAgonesInstalled, isAgonesCheckLoading } = useAgonesInstalled(); + + if (!isAgonesInstalled) { + return <>{fallback || }; + } + + return <>{children}; +} diff --git a/src/hooks/useAgonesInstalled.tsx b/src/hooks/useAgonesInstalled.tsx new file mode 100644 index 0000000..ec2d23f --- /dev/null +++ b/src/hooks/useAgonesInstalled.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Contributors to Agones a Series of LF Projects, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useEffect, useState } from 'react'; +import { isAgonesInstalled as checkAgonesInstallation } from '../isAgonesInstalled'; + +export function useAgonesInstalled() { + const [isInstalled, setIsInstalled] = useState(null); + + useEffect(() => { + async function checkInstalled() { + const installed = await checkAgonesInstallation(); + setIsInstalled(!!installed); + } + checkInstalled(); + }, []); + + return { + isAgonesInstalled: isInstalled, + isAgonesCheckLoading: isInstalled === null, + }; +} diff --git a/src/index.tsx b/src/index.tsx index 6f9e55e..1ae3f0a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -20,6 +20,7 @@ import { registerSidebarEntry, } from '@kinvolk/headlamp-plugin/lib'; import React from 'react'; +import { AgonesInstallCheck } from './components/AgonesInstallCheck'; import { agonesMapSource } from './mapView'; import { FleetAutoscalerDetail } from './views/fleetautoscalers/Detail'; import { FleetAutoscalerList } from './views/fleetautoscalers/List'; @@ -74,7 +75,11 @@ registerRoute({ sidebar: 'agones-overview', name: 'agones-overview', exact: true, - component: () => , + component: () => ( + + + + ), }); registerRoute({ @@ -82,13 +87,21 @@ registerRoute({ sidebar: 'agones-fleets', name: 'agones-fleets', exact: true, - component: () => , + component: () => ( + + + + ), }); registerRoute({ path: '/agones/fleets/:namespace/:name', sidebar: 'agones-fleets', name: 'agones-fleet', - component: () => , + component: () => ( + + + + ), }); registerRoute({ @@ -96,13 +109,21 @@ registerRoute({ sidebar: 'agones-gameservers', name: 'agones-gameservers', exact: true, - component: () => , + component: () => ( + + + + ), }); registerRoute({ path: '/agones/gameservers/:namespace/:name', sidebar: 'agones-gameservers', name: 'agones-gameserver', - component: () => , + component: () => ( + + + + ), }); registerRoute({ @@ -110,11 +131,19 @@ registerRoute({ sidebar: 'agones-fleetautoscalers', name: 'agones-fleetautoscalers', exact: true, - component: () => , + component: () => ( + + + + ), }); registerRoute({ path: '/agones/fleetautoscalers/:namespace/:name', sidebar: 'agones-fleetautoscalers', name: 'agones-fleetautoscaler', - component: () => , + component: () => ( + + + + ), }); diff --git a/src/isAgonesInstalled.ts b/src/isAgonesInstalled.ts new file mode 100644 index 0000000..4010e9e --- /dev/null +++ b/src/isAgonesInstalled.ts @@ -0,0 +1,28 @@ +/* + * Copyright Contributors to Agones a Series of LF Projects, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; + +export async function isAgonesInstalled(): Promise { + try { + const response = await ApiProxy.request('/apis/agones.dev/v1', { + method: 'GET', + }); + return !!response; + } catch (error) { + return false; + } +} From ac453fd46aaa0c2af2410d692f2b2797a2c2663f Mon Sep 17 00:00:00 2001 From: ashwani yadav <22ashwaniyadav@gmail.com> Date: Fri, 12 Jun 2026 17:30:12 +0530 Subject: [PATCH 2/4] plugin: Add unit tests for CRD detection guard Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com> --- package-lock.json | 10 ++-- package.json | 2 + src/hooks/useAgonesInstalled.test.tsx | 62 +++++++++++++++++++++ src/isAgonesInstalled.test.ts | 80 +++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 src/hooks/useAgonesInstalled.test.tsx create mode 100644 src/isAgonesInstalled.test.ts diff --git a/package-lock.json b/package-lock.json index 003a04d..ac2980c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "devDependencies": { "@kinvolk/headlamp-plugin": "^0.14.0", + "@testing-library/dom": "^10.4.1", + "@testing-library/react": "^16.3.2", "vite": "^6.4.2", "vite-plugin-svgr": "^4.5.0" } @@ -4060,7 +4062,6 @@ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -4103,11 +4104,10 @@ "license": "MIT" }, "node_modules/@testing-library/react": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", - "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", + "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" }, diff --git a/package.json b/package.json index 57c73da..fb9384f 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,8 @@ }, "devDependencies": { "@kinvolk/headlamp-plugin": "^0.14.0", + "@testing-library/dom": "^10.4.1", + "@testing-library/react": "^16.3.2", "vite": "^6.4.2", "vite-plugin-svgr": "^4.5.0" } diff --git a/src/hooks/useAgonesInstalled.test.tsx b/src/hooks/useAgonesInstalled.test.tsx new file mode 100644 index 0000000..e9ddd56 --- /dev/null +++ b/src/hooks/useAgonesInstalled.test.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Contributors to Agones a Series of LF Projects, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { renderHook, waitFor } from '@testing-library/react'; +import { useAgonesInstalled } from './useAgonesInstalled'; + +// Mock the isAgonesInstalled function +vi.mock('../isAgonesInstalled', () => ({ + isAgonesInstalled: vi.fn(), +})); + +import { isAgonesInstalled } from '../isAgonesInstalled'; + +describe('useAgonesInstalled', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should start in loading state', () => { + vi.mocked(isAgonesInstalled).mockReturnValue(new Promise(() => {})); // never resolves + const { result } = renderHook(() => useAgonesInstalled()); + + expect(result.current.isAgonesInstalled).toBeNull(); + expect(result.current.isAgonesCheckLoading).toBe(true); + }); + + it('should return isAgonesInstalled=true when Agones is detected', async () => { + vi.mocked(isAgonesInstalled).mockResolvedValue(true); + const { result } = renderHook(() => useAgonesInstalled()); + + await waitFor(() => { + expect(result.current.isAgonesInstalled).toBe(true); + }); + + expect(result.current.isAgonesCheckLoading).toBe(false); + }); + + it('should return isAgonesInstalled=false when Agones is not detected', async () => { + vi.mocked(isAgonesInstalled).mockResolvedValue(false); + const { result } = renderHook(() => useAgonesInstalled()); + + await waitFor(() => { + expect(result.current.isAgonesInstalled).toBe(false); + }); + + expect(result.current.isAgonesCheckLoading).toBe(false); + }); +}); diff --git a/src/isAgonesInstalled.test.ts b/src/isAgonesInstalled.test.ts new file mode 100644 index 0000000..78275b0 --- /dev/null +++ b/src/isAgonesInstalled.test.ts @@ -0,0 +1,80 @@ +/* + * Copyright Contributors to Agones a Series of LF Projects, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, expect, it, vi } from 'vitest'; + +// Mock ApiProxy before importing the module under test +vi.mock('@kinvolk/headlamp-plugin/lib', () => ({ + ApiProxy: { + request: vi.fn(), + }, +})); + +import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; +import { isAgonesInstalled } from './isAgonesInstalled'; + +describe('isAgonesInstalled', () => { + it('should return true when the Agones API group responds successfully', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ kind: 'APIResourceList' }); + + const result = await isAgonesInstalled(); + + expect(result).toBe(true); + expect(ApiProxy.request).toHaveBeenCalledWith('/apis/agones.dev/v1', { + method: 'GET', + }); + }); + + it('should return true for any truthy response', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ resources: [] }); + + const result = await isAgonesInstalled(); + + expect(result).toBe(true); + }); + + it('should return false when the API call throws (Agones not installed)', async () => { + vi.mocked(ApiProxy.request).mockRejectedValue(new Error('404 Not Found')); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); + + it('should return false on network errors', async () => { + vi.mocked(ApiProxy.request).mockRejectedValue(new Error('Network Error')); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); + + it('should return false when the response is null', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue(null); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); + + it('should return false when the response is undefined', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue(undefined); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); +}); From b33c7f097ae5ebbb3efb114f6a9f6698a80bc80a Mon Sep 17 00:00:00 2001 From: ashwani yadav <22ashwaniyadav@gmail.com> Date: Fri, 12 Jun 2026 19:12:42 +0530 Subject: [PATCH 3/4] fix: make Agones installation check robust by validating APIResourceList Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com> --- src/isAgonesInstalled.test.ts | 36 +++++++++++++++++++++++++++++++---- src/isAgonesInstalled.ts | 8 +++++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/isAgonesInstalled.test.ts b/src/isAgonesInstalled.test.ts index 78275b0..b384aa0 100644 --- a/src/isAgonesInstalled.test.ts +++ b/src/isAgonesInstalled.test.ts @@ -27,8 +27,11 @@ import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; import { isAgonesInstalled } from './isAgonesInstalled'; describe('isAgonesInstalled', () => { - it('should return true when the Agones API group responds successfully', async () => { - vi.mocked(ApiProxy.request).mockResolvedValue({ kind: 'APIResourceList' }); + it('should return true when the Agones API group responds with a valid APIResourceList', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ + kind: 'APIResourceList', + resources: [{ name: 'gameservers' }], + }); const result = await isAgonesInstalled(); @@ -38,8 +41,11 @@ describe('isAgonesInstalled', () => { }); }); - it('should return true for any truthy response', async () => { - vi.mocked(ApiProxy.request).mockResolvedValue({ resources: [] }); + it('should return true when resources array is empty but valid', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ + kind: 'APIResourceList', + resources: [], + }); const result = await isAgonesInstalled(); @@ -77,4 +83,26 @@ describe('isAgonesInstalled', () => { expect(result).toBe(false); }); + + it('should return false when response is a non-APIResourceList object (error object)', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ + kind: 'Status', + status: 'Failure', + message: 'the server could not find the requested resource', + }); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); + + it('should return false when response has no resources field', async () => { + vi.mocked(ApiProxy.request).mockResolvedValue({ + kind: 'APIResourceList', + }); + + const result = await isAgonesInstalled(); + + expect(result).toBe(false); + }); }); diff --git a/src/isAgonesInstalled.ts b/src/isAgonesInstalled.ts index 4010e9e..958d98c 100644 --- a/src/isAgonesInstalled.ts +++ b/src/isAgonesInstalled.ts @@ -18,11 +18,17 @@ import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; export async function isAgonesInstalled(): Promise { try { + console.log('[Agones] Checking if Agones is installed...'); const response = await ApiProxy.request('/apis/agones.dev/v1', { method: 'GET', }); - return !!response; + console.log('[Agones] API response:', JSON.stringify(response)); + // Verify the response is a real K8s API resource list, not an error object. + const result = response?.kind === 'APIResourceList' && Array.isArray(response?.resources); + console.log('[Agones] Detection result:', result); + return result; } catch (error) { + console.log('[Agones] API error (not installed):', error); return false; } } From a09a9a167a6e379b3b955803c1ce263185db66b0 Mon Sep 17 00:00:00 2001 From: ashwani yadav <22ashwaniyadav@gmail.com> Date: Mon, 15 Jun 2026 17:55:13 +0530 Subject: [PATCH 4/4] plugin: Move isAgonesInstalled into hook and add TSDoc Signed-off-by: ashwani yadav <22ashwaniyadav@gmail.com> --- src/hooks/useAgonesInstalled.test.tsx | 25 ++++++++++------ src/hooks/useAgonesInstalled.tsx | 41 +++++++++++++++++++++++++-- src/isAgonesInstalled.test.ts | 2 +- src/isAgonesInstalled.ts | 34 ---------------------- 4 files changed, 57 insertions(+), 45 deletions(-) delete mode 100644 src/isAgonesInstalled.ts diff --git a/src/hooks/useAgonesInstalled.test.tsx b/src/hooks/useAgonesInstalled.test.tsx index e9ddd56..0fc874b 100644 --- a/src/hooks/useAgonesInstalled.test.tsx +++ b/src/hooks/useAgonesInstalled.test.tsx @@ -16,14 +16,17 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import { renderHook, waitFor } from '@testing-library/react'; -import { useAgonesInstalled } from './useAgonesInstalled'; -// Mock the isAgonesInstalled function -vi.mock('../isAgonesInstalled', () => ({ - isAgonesInstalled: vi.fn(), +// Mock ApiProxy so the hook's internal isAgonesInstalled() call +// doesn't make real HTTP requests. +vi.mock('@kinvolk/headlamp-plugin/lib', () => ({ + ApiProxy: { + request: vi.fn(), + }, })); -import { isAgonesInstalled } from '../isAgonesInstalled'; +import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; +import { useAgonesInstalled } from './useAgonesInstalled'; describe('useAgonesInstalled', () => { afterEach(() => { @@ -31,7 +34,8 @@ describe('useAgonesInstalled', () => { }); it('should start in loading state', () => { - vi.mocked(isAgonesInstalled).mockReturnValue(new Promise(() => {})); // never resolves + // Never-resolving promise keeps the hook in loading state + vi.mocked(ApiProxy.request).mockReturnValue(new Promise(() => {})); const { result } = renderHook(() => useAgonesInstalled()); expect(result.current.isAgonesInstalled).toBeNull(); @@ -39,7 +43,11 @@ describe('useAgonesInstalled', () => { }); it('should return isAgonesInstalled=true when Agones is detected', async () => { - vi.mocked(isAgonesInstalled).mockResolvedValue(true); + vi.mocked(ApiProxy.request).mockResolvedValue({ + kind: 'APIResourceList', + resources: [{ name: 'gameservers' }], + }); + const { result } = renderHook(() => useAgonesInstalled()); await waitFor(() => { @@ -50,7 +58,8 @@ describe('useAgonesInstalled', () => { }); it('should return isAgonesInstalled=false when Agones is not detected', async () => { - vi.mocked(isAgonesInstalled).mockResolvedValue(false); + vi.mocked(ApiProxy.request).mockRejectedValue(new Error('404 Not Found')); + const { result } = renderHook(() => useAgonesInstalled()); await waitFor(() => { diff --git a/src/hooks/useAgonesInstalled.tsx b/src/hooks/useAgonesInstalled.tsx index ec2d23f..f117aa3 100644 --- a/src/hooks/useAgonesInstalled.tsx +++ b/src/hooks/useAgonesInstalled.tsx @@ -14,15 +14,52 @@ * limitations under the License. */ +import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; import { useEffect, useState } from 'react'; -import { isAgonesInstalled as checkAgonesInstallation } from '../isAgonesInstalled'; +/** + * Checks whether the Agones CRDs are installed on the current cluster by + * querying the {@link https://agones.dev/site/docs/reference/agones_crd_api_reference/ | Agones API group} + * at `/apis/agones.dev/v1`. + * + * The response is validated to be a genuine Kubernetes `APIResourceList` + * (not a `Status` error object that some proxies return for 404s). + * + * @returns `true` if Agones CRDs are present, `false` otherwise. + */ +export async function isAgonesInstalled(): Promise { + try { + const response = await ApiProxy.request('/apis/agones.dev/v1', { + method: 'GET', + }); + // Verify the response is a real K8s API resource list, not an error object. + return response?.kind === 'APIResourceList' && Array.isArray(response?.resources); + } catch { + return false; + } +} + +/** + * React hook that asynchronously checks whether the Agones CRDs are installed + * on the current Kubernetes cluster. + * + * @returns An object with: + * - `isAgonesInstalled` — `null` while loading, `true` if detected, `false` if not. + * - `isAgonesCheckLoading` — `true` while the API check is in progress. + * + * @example + * ```tsx + * const { isAgonesInstalled, isAgonesCheckLoading } = useAgonesInstalled(); + * if (isAgonesCheckLoading) return ; + * if (!isAgonesInstalled) return ; + * ``` + */ export function useAgonesInstalled() { const [isInstalled, setIsInstalled] = useState(null); useEffect(() => { async function checkInstalled() { - const installed = await checkAgonesInstallation(); + const installed = await isAgonesInstalled(); setIsInstalled(!!installed); } checkInstalled(); diff --git a/src/isAgonesInstalled.test.ts b/src/isAgonesInstalled.test.ts index b384aa0..5d14e22 100644 --- a/src/isAgonesInstalled.test.ts +++ b/src/isAgonesInstalled.test.ts @@ -24,7 +24,7 @@ vi.mock('@kinvolk/headlamp-plugin/lib', () => ({ })); import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; -import { isAgonesInstalled } from './isAgonesInstalled'; +import { isAgonesInstalled } from './hooks/useAgonesInstalled'; describe('isAgonesInstalled', () => { it('should return true when the Agones API group responds with a valid APIResourceList', async () => { diff --git a/src/isAgonesInstalled.ts b/src/isAgonesInstalled.ts deleted file mode 100644 index 958d98c..0000000 --- a/src/isAgonesInstalled.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Contributors to Agones a Series of LF Projects, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ApiProxy } from '@kinvolk/headlamp-plugin/lib'; - -export async function isAgonesInstalled(): Promise { - try { - console.log('[Agones] Checking if Agones is installed...'); - const response = await ApiProxy.request('/apis/agones.dev/v1', { - method: 'GET', - }); - console.log('[Agones] API response:', JSON.stringify(response)); - // Verify the response is a real K8s API resource list, not an error object. - const result = response?.kind === 'APIResourceList' && Array.isArray(response?.resources); - console.log('[Agones] Detection result:', result); - return result; - } catch (error) { - console.log('[Agones] API error (not installed):', error); - return false; - } -}