From de0ec034465b4d9d8a5ba2df126f5e033ecf33c2 Mon Sep 17 00:00:00 2001 From: testa113 Date: Tue, 17 Oct 2023 01:46:24 +0100 Subject: [PATCH] fix(kubeapi): fix ts api error handling [EE-5558] --- .../DetailsView/useNamespaceEventsQuery.ts | 6 ++-- .../applications/application.service.ts | 15 ++++++--- .../applications/autoscaling.service.ts | 4 +-- .../kubernetes/applications/pod.service.ts | 12 ++++--- app/react/kubernetes/axiosError.ts | 2 +- .../useConfigureClusterMutation.ts | 5 +-- .../useStorageClassesFormValues.ts | 5 +-- .../cluster/HomeView/nodes.service.ts | 31 ++++++++++++------- .../ingressClass/ingressClass.service.ts | 8 +++-- .../cluster/kubernetesEndpoint.service.ts | 14 ++++++--- .../kubernetes/configs/configmap.service.ts | 12 ++----- .../kubernetes/configs/secret.service.ts | 4 +-- .../namespaces/getSelfSubjectAccessReview.ts | 8 +++-- app/react/kubernetes/services/service.ts | 6 ++-- app/react/kubernetes/volumes/service.ts | 6 ++-- 15 files changed, 77 insertions(+), 61 deletions(-) diff --git a/app/react/kubernetes/applications/DetailsView/useNamespaceEventsQuery.ts b/app/react/kubernetes/applications/DetailsView/useNamespaceEventsQuery.ts index 68c1f30f6..978fc1d72 100644 --- a/app/react/kubernetes/applications/DetailsView/useNamespaceEventsQuery.ts +++ b/app/react/kubernetes/applications/DetailsView/useNamespaceEventsQuery.ts @@ -2,9 +2,11 @@ import { EventList } from 'kubernetes-types/core/v1'; import { useQuery } from 'react-query'; import { EnvironmentId } from '@/react/portainer/environments/types'; -import axios, { parseAxiosError } from '@/portainer/services/axios'; +import axios from '@/portainer/services/axios'; import { withError } from '@/react-tools/react-query'; +import { parseKubernetesAxiosError } from '../../axiosError'; + async function getNamespaceEvents( environmentId: EnvironmentId, namespace: string, @@ -21,7 +23,7 @@ async function getNamespaceEvents( ); return data.items; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve events'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve events'); } } diff --git a/app/react/kubernetes/applications/application.service.ts b/app/react/kubernetes/applications/application.service.ts index 961cc2791..439561f5e 100644 --- a/app/react/kubernetes/applications/application.service.ts +++ b/app/react/kubernetes/applications/application.service.ts @@ -13,6 +13,8 @@ import axios, { parseAxiosError } from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; import { isFulfilled } from '@/portainer/helpers/promise-utils'; +import { parseKubernetesAxiosError } from '../axiosError'; + import { getPod, getNamespacePods, patchPod } from './pod.service'; import { filterRevisionsByOwnerUid, getNakedPods } from './utils'; import { @@ -228,7 +230,7 @@ async function patchApplicationByKind( ); return res; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to patch application'); + throw parseKubernetesAxiosError(e, 'Unable to patch application'); } } @@ -250,7 +252,7 @@ async function getApplicationByKind< ); return data; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve application'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve application'); } } @@ -265,7 +267,7 @@ async function getApplicationsByKind( ); return data.items as T['items']; } catch (e) { - throw parseAxiosError(e as Error, `Unable to retrieve ${appKind}s`); + throw parseKubernetesAxiosError(e, `Unable to retrieve ${appKind}s`); } } @@ -350,7 +352,7 @@ export async function getReplicaSetList( ); return data; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve ReplicaSets'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve ReplicaSets'); } } @@ -370,7 +372,10 @@ export async function getControllerRevisionList( ); return data; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve ControllerRevisions'); + throw parseKubernetesAxiosError( + e, + 'Unable to retrieve ControllerRevisions' + ); } } diff --git a/app/react/kubernetes/applications/autoscaling.service.ts b/app/react/kubernetes/applications/autoscaling.service.ts index 390f110e4..7733ffab2 100644 --- a/app/react/kubernetes/applications/autoscaling.service.ts +++ b/app/react/kubernetes/applications/autoscaling.service.ts @@ -55,7 +55,7 @@ export async function getNamespaceHorizontalPodAutoscalers( return autoScalarList.items; } catch (e) { throw parseKubernetesAxiosError( - e as Error, + e, 'Unable to retrieve horizontal pod autoscalers' ); } @@ -81,7 +81,7 @@ export async function getNamespaceHorizontalPodAutoscaler< return autoScalar; } catch (e) { throw parseKubernetesAxiosError( - e as Error, + e, 'Unable to retrieve horizontal pod autoscaler' ); } diff --git a/app/react/kubernetes/applications/pod.service.ts b/app/react/kubernetes/applications/pod.service.ts index b9c020f55..37f8b98dd 100644 --- a/app/react/kubernetes/applications/pod.service.ts +++ b/app/react/kubernetes/applications/pod.service.ts @@ -1,7 +1,9 @@ import { Pod, PodList } from 'kubernetes-types/core/v1'; import { EnvironmentId } from '@/react/portainer/environments/types'; -import axios, { parseAxiosError } from '@/portainer/services/axios'; +import axios from '@/portainer/services/axios'; + +import { parseKubernetesAxiosError } from '../axiosError'; import { ApplicationPatch } from './types'; @@ -21,7 +23,7 @@ export async function getNamespacePods( ); return data.items; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve pods'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve pods'); } } @@ -40,7 +42,7 @@ export async function getPod( ); return data; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve pod'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve pod'); } } @@ -61,7 +63,7 @@ export async function patchPod( } ); } catch (e) { - throw parseAxiosError(e as Error, 'Unable to update pod'); + throw parseKubernetesAxiosError(e, 'Unable to update pod'); } } @@ -73,7 +75,7 @@ export async function deletePod( try { return await axios.delete(buildUrl(environmentId, namespace, name)); } catch (e) { - throw parseAxiosError(e as Error, 'Unable to delete pod'); + throw parseKubernetesAxiosError(e as Error, 'Unable to delete pod'); } } diff --git a/app/react/kubernetes/axiosError.ts b/app/react/kubernetes/axiosError.ts index 1c49606a8..d7ece792f 100644 --- a/app/react/kubernetes/axiosError.ts +++ b/app/react/kubernetes/axiosError.ts @@ -24,6 +24,6 @@ export function kubernetesErrorParser(axiosError: AxiosError) { * @param msg An optional error message to prepend. * @returns An error object with an error message and details. */ -export function parseKubernetesAxiosError(err: Error, msg = '') { +export function parseKubernetesAxiosError(err: unknown, msg = '') { return parseAxiosError(err, msg, kubernetesErrorParser); } diff --git a/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts b/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts index 9ef252a34..71ea83294 100644 --- a/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts +++ b/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts @@ -72,9 +72,6 @@ async function patchStorageClass( } ); } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - `Unable to patch StorageClass ${name}` - ); + throw parseKubernetesAxiosError(e, `Unable to patch StorageClass ${name}`); } } diff --git a/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useStorageClassesFormValues.ts b/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useStorageClassesFormValues.ts index b7631aa91..5df713fc7 100644 --- a/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useStorageClassesFormValues.ts +++ b/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useStorageClassesFormValues.ts @@ -65,10 +65,7 @@ async function getStorageClasses( ); return storageClassList.items; } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - 'Unable to retrieve Storage Classes' - ); + throw parseKubernetesAxiosError(e, 'Unable to retrieve Storage Classes'); } } diff --git a/app/react/kubernetes/cluster/HomeView/nodes.service.ts b/app/react/kubernetes/cluster/HomeView/nodes.service.ts index 65e849a48..45582612f 100644 --- a/app/react/kubernetes/cluster/HomeView/nodes.service.ts +++ b/app/react/kubernetes/cluster/HomeView/nodes.service.ts @@ -5,6 +5,8 @@ import axios from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; import { withError } from '@/react-tools/react-query'; +import { parseKubernetesAxiosError } from '../../axiosError'; + const queryKeys = { node: (environmentId: number, nodeName: string) => [ 'environments', @@ -22,10 +24,14 @@ const queryKeys = { }; async function getNode(environmentId: EnvironmentId, nodeName: string) { - const { data: node } = await axios.get( - `/endpoints/${environmentId}/kubernetes/api/v1/nodes/${nodeName}` - ); - return node; + try { + const { data: node } = await axios.get( + `/endpoints/${environmentId}/kubernetes/api/v1/nodes/${nodeName}` + ); + return node; + } catch (e) { + throw parseKubernetesAxiosError(e, 'Unable to get node details'); + } } export function useNodeQuery(environmentId: EnvironmentId, nodeName: string) { @@ -33,20 +39,21 @@ export function useNodeQuery(environmentId: EnvironmentId, nodeName: string) { queryKeys.node(environmentId, nodeName), () => getNode(environmentId, nodeName), { - ...withError( - 'Unable to get node details from the Kubernetes api', - 'Failed to get node details' - ), + ...withError('Unable to get node details'), } ); } // getNodes is used to get a list of nodes using the kubernetes API async function getNodes(environmentId: EnvironmentId) { - const { data: nodeList } = await axios.get( - `/endpoints/${environmentId}/kubernetes/api/v1/nodes` - ); - return nodeList.items; + try { + const { data: nodeList } = await axios.get( + `/endpoints/${environmentId}/kubernetes/api/v1/nodes` + ); + return nodeList.items; + } catch (e) { + throw parseKubernetesAxiosError(e, 'Unable to get nodes'); + } } // useNodesQuery is used to get an array of nodes using the kubernetes API diff --git a/app/react/kubernetes/cluster/ingressClass/ingressClass.service.ts b/app/react/kubernetes/cluster/ingressClass/ingressClass.service.ts index 08ed26d89..876b197b7 100644 --- a/app/react/kubernetes/cluster/ingressClass/ingressClass.service.ts +++ b/app/react/kubernetes/cluster/ingressClass/ingressClass.service.ts @@ -1,16 +1,18 @@ import { IngressClassList } from 'kubernetes-types/networking/v1'; -import axios, { parseAxiosError } from '@/portainer/services/axios'; +import axios from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; +import { parseKubernetesAxiosError } from '../../axiosError'; + export async function getAllIngressClasses(environmentId: EnvironmentId) { try { const { data: { items }, } = await axios.get(urlBuilder(environmentId)); return items; - } catch (error) { - throw parseAxiosError(error as Error); + } catch (e) { + throw parseKubernetesAxiosError(e, 'Unable to retrieve ingress classes'); } } diff --git a/app/react/kubernetes/cluster/kubernetesEndpoint.service.ts b/app/react/kubernetes/cluster/kubernetesEndpoint.service.ts index b7b28a099..7658443e6 100644 --- a/app/react/kubernetes/cluster/kubernetesEndpoint.service.ts +++ b/app/react/kubernetes/cluster/kubernetesEndpoint.service.ts @@ -5,11 +5,17 @@ import axios from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; import { withError } from '@/react-tools/react-query'; +import { parseKubernetesAxiosError } from '../axiosError'; + async function getKubernetesEndpoints(environmentId: EnvironmentId) { - const { data: endpointsList } = await axios.get( - `/endpoints/${environmentId}/kubernetes/api/v1/endpoints` - ); - return endpointsList.items; + try { + const { data: endpointsList } = await axios.get( + `/endpoints/${environmentId}/kubernetes/api/v1/endpoints` + ); + return endpointsList.items; + } catch (e) { + throw parseKubernetesAxiosError(e, 'Unable to retrieve endpoints'); + } } export function useKubernetesEndpointsQuery( diff --git a/app/react/kubernetes/configs/configmap.service.ts b/app/react/kubernetes/configs/configmap.service.ts index adcaa5d9e..961adc55b 100644 --- a/app/react/kubernetes/configs/configmap.service.ts +++ b/app/react/kubernetes/configs/configmap.service.ts @@ -127,10 +127,7 @@ async function getConfigMapsForCluster( ); return configMaps.flat(); } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - 'Unable to retrieve ConfigMaps for cluster' - ); + throw parseKubernetesAxiosError(e, 'Unable to retrieve ConfigMaps'); } } @@ -142,10 +139,7 @@ async function getConfigMaps(environmentId: EnvironmentId, namespace: string) { ); return data.items; } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - 'Unable to retrieve ConfigMaps' - ); + throw parseKubernetesAxiosError(e, 'Unable to retrieve ConfigMaps'); } } @@ -157,7 +151,7 @@ async function deleteConfigMap( try { await axios.delete(buildUrl(environmentId, namespace, name)); } catch (e) { - throw parseKubernetesAxiosError(e as Error, 'Unable to remove ConfigMap'); + throw parseKubernetesAxiosError(e, 'Unable to remove ConfigMap'); } } diff --git a/app/react/kubernetes/configs/secret.service.ts b/app/react/kubernetes/configs/secret.service.ts index 4297162ac..162288e25 100644 --- a/app/react/kubernetes/configs/secret.service.ts +++ b/app/react/kubernetes/configs/secret.service.ts @@ -138,7 +138,7 @@ async function getSecrets(environmentId: EnvironmentId, namespace: string) { ); return data.items; } catch (e) { - throw parseKubernetesAxiosError(e as Error, 'Unable to retrieve secrets'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve secrets'); } } @@ -150,7 +150,7 @@ async function deleteSecret( try { await axios.delete(buildUrl(environmentId, namespace, name)); } catch (e) { - throw parseKubernetesAxiosError(e as Error, 'Unable to remove secret'); + throw parseKubernetesAxiosError(e, 'Unable to remove secret'); } } diff --git a/app/react/kubernetes/namespaces/getSelfSubjectAccessReview.ts b/app/react/kubernetes/namespaces/getSelfSubjectAccessReview.ts index 2d1c0575e..3280886a8 100644 --- a/app/react/kubernetes/namespaces/getSelfSubjectAccessReview.ts +++ b/app/react/kubernetes/namespaces/getSelfSubjectAccessReview.ts @@ -1,6 +1,8 @@ -import axios, { parseAxiosError } from '@/portainer/services/axios'; +import axios from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; +import { parseKubernetesAxiosError } from '../axiosError'; + interface SelfSubjectAccessReviewResponse { status: { allowed: boolean; @@ -43,8 +45,8 @@ export async function getSelfSubjectAccessReview( ); return accessReview; } catch (e) { - throw parseAxiosError( - e as Error, + throw parseKubernetesAxiosError( + e, 'Unable to retrieve self subject access review' ); } diff --git a/app/react/kubernetes/services/service.ts b/app/react/kubernetes/services/service.ts index c5a34f7a6..0239780df 100644 --- a/app/react/kubernetes/services/service.ts +++ b/app/react/kubernetes/services/service.ts @@ -100,7 +100,7 @@ export async function getServices( ); return services; } catch (e) { - throw parseAxiosError(e as Error, 'Unable to retrieve services'); + throw parseAxiosError(e, 'Unable to retrieve services'); } } @@ -120,7 +120,7 @@ export async function getNamespaceServices( ); return services.items; } catch (e) { - throw parseKubernetesAxiosError(e as Error, 'Unable to retrieve services'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve services'); } } @@ -141,7 +141,7 @@ async function getService( ); return service; } catch (e) { - throw parseKubernetesAxiosError(e as Error, 'Unable to retrieve service'); + throw parseKubernetesAxiosError(e, 'Unable to retrieve service'); } } diff --git a/app/react/kubernetes/volumes/service.ts b/app/react/kubernetes/volumes/service.ts index 1c711273e..5f2ec2038 100644 --- a/app/react/kubernetes/volumes/service.ts +++ b/app/react/kubernetes/volumes/service.ts @@ -3,6 +3,8 @@ import { PersistentVolumeClaimList } from 'kubernetes-types/core/v1'; import axios, { parseAxiosError } from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; +import { parseKubernetesAxiosError } from '../axiosError'; + export async function getPVCsForCluster( environmentId: EnvironmentId, namespaces: string[] @@ -28,8 +30,8 @@ export async function getPVCs(environmentId: EnvironmentId, namespace: string) { ); return data.items; } catch (e) { - throw parseAxiosError( - e as Error, + throw parseKubernetesAxiosError( + e, 'Unable to retrieve persistent volume claims' ); }