Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 39 additions & 47 deletions ui/contexts/KubernetesContext.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
'use client'

import React, { createContext, useContext, useMemo, useState } from 'react'
import React, { createContext, useContext, useState } from 'react'
import {
KubernetesProvider as BaseKubernetesProvider,
useKubernetes as useBaseKubernetes,
queryClient
} from '@kubernetesjs/react'
import { KubernetesClient } from 'kubernetesjs'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

// Configuration types
export interface KubernetesConfig {
Expand All @@ -23,17 +27,7 @@ interface KubernetesContextValue {
// Create context
const KubernetesContext = createContext<KubernetesContextValue | undefined>(undefined)

// Query client for TanStack Query
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
retry: 3,
staleTime: 30 * 1000, // 30 seconds
gcTime: 5 * 60 * 1000, // 5 minutes
},
},
})


// Provider props
interface KubernetesProviderProps {
Expand All @@ -42,48 +36,46 @@ interface KubernetesProviderProps {
}

// Provider component
export function KubernetesProvider({
children,
initialConfig
}: KubernetesProviderProps) {
const [config, setConfig] = useState<KubernetesConfig>({
restEndpoint: initialConfig?.restEndpoint || process.env.NEXT_PUBLIC_K8S_API_URL || '/api/k8s',
namespace: initialConfig?.namespace || 'default',
headers: initialConfig?.headers || {},
})

const [namespace, setNamespace] = useState(config.namespace || 'default')

// Create client instance
const client = useMemo(() => {
return new KubernetesClient({
restEndpoint: config.restEndpoint,
})
}, [config.restEndpoint])

// Update config function
const updateConfig = (newConfig: Partial<KubernetesConfig>) => {
setConfig(prev => ({ ...prev, ...newConfig }))
if (newConfig.namespace) {
setNamespace(newConfig.namespace)
export function KubernetesProvider({ children, initialConfig }: KubernetesProviderProps) {
const [namespace, setNamespace] = useState(initialConfig?.namespace || 'default')

return (
<BaseKubernetesProvider
initialConfig={{
restEndpoint: initialConfig?.restEndpoint || process.env.NEXT_PUBLIC_K8S_API_URL || '/api/k8s',
headers: initialConfig?.headers || {}
}}
>
<InnerProvider namespace={namespace} setNamespace={setNamespace}>{children}</InnerProvider>
</BaseKubernetesProvider>
)
}

interface InnerProviderProps {
children: React.ReactNode
namespace: string
setNamespace: (namespace: string) => void
}

function InnerProvider({ children, namespace, setNamespace }: InnerProviderProps) {
const base = useBaseKubernetes()

const updateConfig = (config: Partial<KubernetesConfig>) => {
base.updateConfig(config)
if (config.namespace) {
setNamespace(config.namespace)
}
}

const contextValue: KubernetesContextValue = {
client,
config,
client: base.client as KubernetesClient,
config: { ...base.config, namespace },
namespace,
setNamespace,
updateConfig,
}

return (
<QueryClientProvider client={queryClient}>
<KubernetesContext.Provider value={contextValue}>
{children}
</KubernetesContext.Provider>
</QueryClientProvider>
)
return <KubernetesContext.Provider value={contextValue}>{children}</KubernetesContext.Provider>
}

// Hook to use Kubernetes context
Expand All @@ -96,4 +88,4 @@ export function useKubernetes() {
}

// Export query client for use in hooks
export { queryClient }
export { queryClient }
2 changes: 1 addition & 1 deletion ui/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ export * from './useDaemonSets'
export * from './useReplicaSets'

// Re-export context hook
export { useKubernetes } from '../contexts/KubernetesContext'
export { useKubernetes } from '../contexts/KubernetesContext'
135 changes: 43 additions & 92 deletions ui/hooks/useConfigMaps.ts
Original file line number Diff line number Diff line change
@@ -1,111 +1,62 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
useListCoreV1ConfigMapForAllNamespacesQuery,
useListCoreV1NamespacedConfigMapQuery,
useReadCoreV1NamespacedConfigMapQuery,
useCreateCoreV1NamespacedConfigMap,
useReplaceCoreV1NamespacedConfigMap,
useDeleteCoreV1NamespacedConfigMap
} from '@kubernetesjs/react'
import { useKubernetes } from '../contexts/KubernetesContext'
import type { ConfigMap, ConfigMapList } from 'kubernetesjs'

// Query keys
const CONFIGMAPS_KEY = ['configmaps'] as const
import type { ConfigMap } from 'kubernetesjs'

export function useConfigMaps(namespace?: string) {
const { client, namespace: defaultNamespace } = useKubernetes()
const { namespace: defaultNamespace } = useKubernetes()
const ns = namespace || defaultNamespace

return useQuery<ConfigMapList, Error>({
queryKey: [...CONFIGMAPS_KEY, ns],
queryFn: async () => {
if (ns === '_all') {
const result = await client.listCoreV1ConfigMapForAllNamespaces({
query: {},
})
return result
} else {
const result = await client.listCoreV1NamespacedConfigMap({
path: { namespace: ns },
query: {},
})
return result
}
},
refetchOnMount: 'always',
staleTime: 0,
})
if (ns === '_all') {
return useListCoreV1ConfigMapForAllNamespacesQuery({ query: {} })
}
return useListCoreV1NamespacedConfigMapQuery({ path: { namespace: ns }, query: {} })
}

export function useConfigMap(name: string, namespace?: string) {
const { client, namespace: defaultNamespace } = useKubernetes()
const { namespace: defaultNamespace } = useKubernetes()
const ns = namespace || defaultNamespace

return useQuery<ConfigMap, Error>({
queryKey: [...CONFIGMAPS_KEY, ns, name],
queryFn: async () => {
const result = await client.readCoreV1NamespacedConfigMap({
path: { namespace: ns, name },
query: {},
})
return result
},
enabled: !!name,
refetchOnMount: 'always',
staleTime: 0,
})
return useReadCoreV1NamespacedConfigMapQuery({ path: { namespace: ns, name }, query: {} })
}

export function useCreateConfigMap() {
const { client, namespace: defaultNamespace } = useKubernetes()
const queryClient = useQueryClient()

return useMutation<ConfigMap, Error, { configMap: ConfigMap; namespace?: string }>({
mutationFn: async ({ configMap, namespace }) => {
const ns = namespace || defaultNamespace
const result = await client.createCoreV1NamespacedConfigMap({
path: { namespace: ns },
query: {},
body: configMap,
})
return result
},
onSuccess: (_, variables) => {
const ns = variables.namespace || defaultNamespace
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
},
})
const { namespace: defaultNamespace } = useKubernetes()
const mutation = useCreateCoreV1NamespacedConfigMap()
return {
...mutation,
mutate: ({ configMap, namespace }) =>
mutation.mutate({ path: { namespace: namespace || defaultNamespace }, query: {}, body: configMap }),
mutateAsync: ({ configMap, namespace }) =>
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace }, query: {}, body: configMap }),
}
}

export function useUpdateConfigMap() {
const { client, namespace: defaultNamespace } = useKubernetes()
const queryClient = useQueryClient()

return useMutation<ConfigMap, Error, { name: string; configMap: ConfigMap; namespace?: string }>({
mutationFn: async ({ name, configMap, namespace }) => {
const ns = namespace || defaultNamespace
const result = await client.replaceCoreV1NamespacedConfigMap({
path: { namespace: ns, name },
query: {},
body: configMap,
})
return result
},
onSuccess: (_, variables) => {
const ns = variables.namespace || defaultNamespace
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
},
})
const { namespace: defaultNamespace } = useKubernetes()
const mutation = useReplaceCoreV1NamespacedConfigMap()
return {
...mutation,
mutate: ({ name, configMap, namespace }) =>
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {}, body: configMap }),
mutateAsync: ({ name, configMap, namespace }) =>
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {}, body: configMap }),
}
}

export function useDeleteConfigMap() {
const { client, namespace: defaultNamespace } = useKubernetes()
const queryClient = useQueryClient()

return useMutation<void, Error, { name: string; namespace?: string }>({
mutationFn: async ({ name, namespace }) => {
const ns = namespace || defaultNamespace
await client.deleteCoreV1NamespacedConfigMap({
path: { namespace: ns, name },
query: {},
})
},
onSuccess: (_, variables) => {
const ns = variables.namespace || defaultNamespace
queryClient.invalidateQueries({ queryKey: [...CONFIGMAPS_KEY, ns] })
},
})
const { namespace: defaultNamespace } = useKubernetes()
const mutation = useDeleteCoreV1NamespacedConfigMap()
return {
...mutation,
mutate: ({ name, namespace }) =>
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
mutateAsync: ({ name, namespace }) =>
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
}
}
79 changes: 23 additions & 56 deletions ui/hooks/useDaemonSets.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,36 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
useListAppsV1DaemonSetForAllNamespacesQuery,
useListAppsV1NamespacedDaemonSetQuery,
useReadAppsV1NamespacedDaemonSetQuery,
useDeleteAppsV1NamespacedDaemonSet
} from '@kubernetesjs/react'
import { useKubernetes } from '../contexts/KubernetesContext'
import type { DaemonSet, DaemonSetList } from 'kubernetesjs'

// Query keys
const DAEMONSETS_KEY = ['daemonsets'] as const
import type { DaemonSet } from 'kubernetesjs'

export function useDaemonSets(namespace?: string) {
const { client, namespace: defaultNamespace } = useKubernetes()
const { namespace: defaultNamespace } = useKubernetes()
const ns = namespace || defaultNamespace

return useQuery<DaemonSetList, Error>({
queryKey: [...DAEMONSETS_KEY, ns],
queryFn: async () => {
if (ns === '_all') {
const result = await client.listAppsV1DaemonSetForAllNamespaces({
query: {},
})
return result
} else {
const result = await client.listAppsV1NamespacedDaemonSet({
path: { namespace: ns },
query: {},
})
return result
}
},
refetchOnMount: 'always',
staleTime: 0,
})
if (ns === '_all') {
return useListAppsV1DaemonSetForAllNamespacesQuery({ query: {} })
}
return useListAppsV1NamespacedDaemonSetQuery({ path: { namespace: ns }, query: {} })
}

export function useDaemonSet(name: string, namespace?: string) {
const { client, namespace: defaultNamespace } = useKubernetes()
const { namespace: defaultNamespace } = useKubernetes()
const ns = namespace || defaultNamespace

return useQuery<DaemonSet, Error>({
queryKey: [...DAEMONSETS_KEY, ns, name],
queryFn: async () => {
const result = await client.readAppsV1NamespacedDaemonSet({
path: { namespace: ns, name },
query: {},
})
return result
},
enabled: !!name,
refetchOnMount: 'always',
staleTime: 0,
})
return useReadAppsV1NamespacedDaemonSetQuery({ path: { namespace: ns, name }, query: {} })
}

export function useDeleteDaemonSet() {
const { client, namespace: defaultNamespace } = useKubernetes()
const queryClient = useQueryClient()

return useMutation<void, Error, { name: string; namespace?: string }>({
mutationFn: async ({ name, namespace }) => {
const ns = namespace || defaultNamespace
await client.deleteAppsV1NamespacedDaemonSet({
path: { namespace: ns, name },
query: {},
})
},
onSuccess: (_, variables) => {
const ns = variables.namespace || defaultNamespace
queryClient.invalidateQueries({ queryKey: [...DAEMONSETS_KEY, ns] })
},
})
const { namespace: defaultNamespace } = useKubernetes()
const mutation = useDeleteAppsV1NamespacedDaemonSet()
return {
...mutation,
mutate: ({ name, namespace }) =>
mutation.mutate({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
mutateAsync: ({ name, namespace }) =>
mutation.mutateAsync({ path: { namespace: namespace || defaultNamespace, name }, query: {} }),
}
}
Loading