From 96ead31a8d080a379212cdc8d5ce8ecbbef6fbe6 Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:52:40 +0100 Subject: [PATCH] fix(kubeapi): fix ts api error handling [EE-5558] (#10488) * fix(kubeapi): fix ts api error handling [EE-5558] * use portainer errors for mapped functions * don't parse long patch responses * allow nested kube error that's thrown to bubble up --------- Co-authored-by: testa113 --- .../DetailsView/useNamespaceEventsQuery.ts | 6 +- .../applications/application.service.ts | 278 ++++++++---------- .../applications/autoscaling.service.ts | 4 +- .../kubernetes/applications/pod.service.ts | 13 +- app/react/kubernetes/axiosError.ts | 2 +- .../useConfigureClusterMutation.ts | 8 +- .../useStorageClassesFormValues.ts | 5 +- .../cluster/HomeView/nodes.service.ts | 31 +- .../kubernetes/cluster/getIsRBACEnabled.ts | 5 +- .../ingressClass/ingressClass.service.ts | 8 +- .../useIngressControllerClassMap.ts | 10 +- .../cluster/kubernetesEndpoint.service.ts | 14 +- .../kubernetes/configs/configmap.service.ts | 13 +- .../kubernetes/configs/secret.service.ts | 10 +- .../namespaces/getSelfSubjectAccessReview.ts | 8 +- app/react/kubernetes/services/service.ts | 6 +- app/react/kubernetes/volumes/service.ts | 23 +- 17 files changed, 210 insertions(+), 234 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..8fb2c1909 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 { @@ -29,22 +31,15 @@ export async function getApplicationsForCluster( environmentId: EnvironmentId, namespaceNames?: string[] ) { - try { - if (!namespaceNames) { - return []; - } - const applications = await Promise.all( - namespaceNames.map((namespace) => - getApplicationsForNamespace(environmentId, namespace) - ) - ); - return applications.flat(); - } catch (e) { - throw parseAxiosError( - e as Error, - 'Unable to retrieve applications for cluster' - ); + if (!namespaceNames) { + return []; } + const applications = await Promise.all( + namespaceNames.map((namespace) => + getApplicationsForNamespace(environmentId, namespace) + ) + ); + return applications.flat(); } // get a list of all Deployments, DaemonSets, StatefulSets and naked pods (https://portainer.atlassian.net/browse/CE-2) in one namespace @@ -52,34 +47,23 @@ async function getApplicationsForNamespace( environmentId: EnvironmentId, namespace: string ) { - try { - const [deployments, daemonSets, statefulSets, pods] = await Promise.all([ - getApplicationsByKind( - environmentId, - namespace, - 'Deployment' - ), - getApplicationsByKind( - environmentId, - namespace, - 'DaemonSet' - ), - getApplicationsByKind( - environmentId, - namespace, - 'StatefulSet' - ), - getNamespacePods(environmentId, namespace), - ]); - // find all pods which are 'naked' (not owned by a deployment, daemonset or statefulset) - const nakedPods = getNakedPods(pods, deployments, daemonSets, statefulSets); - return [...deployments, ...daemonSets, ...statefulSets, ...nakedPods]; - } catch (e) { - throw parseAxiosError( - e as Error, - `Unable to retrieve applications in namespace '${namespace}'` - ); - } + const [deployments, daemonSets, statefulSets, pods] = await Promise.all([ + getApplicationsByKind( + environmentId, + namespace, + 'Deployment' + ), + getApplicationsByKind(environmentId, namespace, 'DaemonSet'), + getApplicationsByKind( + environmentId, + namespace, + 'StatefulSet' + ), + getNamespacePods(environmentId, namespace), + ]); + // find all pods which are 'naked' (not owned by a deployment, daemonset or statefulset) + const nakedPods = getNakedPods(pods, deployments, daemonSets, statefulSets); + return [...deployments, ...daemonSets, ...statefulSets, ...nakedPods]; } // if not known, get the type of an application (Deployment, DaemonSet, StatefulSet or naked pod) by name @@ -92,72 +76,65 @@ export async function getApplication< appKind?: AppKind, yaml?: boolean ) { - try { - // if resourceType is known, get the application by type and name - if (appKind) { - switch (appKind) { - case 'Deployment': - case 'DaemonSet': - case 'StatefulSet': - return await getApplicationByKind( - environmentId, - namespace, - appKind, - name, - yaml - ); - case 'Pod': - return await getPod(environmentId, namespace, name, yaml); - default: - throw new Error('Unknown resource type'); - } + // if resourceType is known, get the application by type and name + if (appKind) { + switch (appKind) { + case 'Deployment': + case 'DaemonSet': + case 'StatefulSet': + return getApplicationByKind( + environmentId, + namespace, + appKind, + name, + yaml + ); + case 'Pod': + return getPod(environmentId, namespace, name, yaml); + default: + throw new Error('Unknown resource type'); } - - // if resourceType is not known, get the application by name and return the first one that is fulfilled - const [deployment, daemonSet, statefulSet, pod] = await Promise.allSettled([ - getApplicationByKind( - environmentId, - namespace, - 'Deployment', - name, - yaml - ), - getApplicationByKind( - environmentId, - namespace, - 'DaemonSet', - name, - yaml - ), - getApplicationByKind( - environmentId, - namespace, - 'StatefulSet', - name, - yaml - ), - getPod(environmentId, namespace, name, yaml), - ]); - - if (isFulfilled(deployment)) { - return deployment.value; - } - if (isFulfilled(daemonSet)) { - return daemonSet.value; - } - if (isFulfilled(statefulSet)) { - return statefulSet.value; - } - if (isFulfilled(pod)) { - return pod.value; - } - throw new Error('Unable to retrieve application'); - } catch (e) { - throw parseAxiosError( - e as Error, - `Unable to retrieve application ${name} in namespace '${namespace}'` - ); } + + // if resourceType is not known, get the application by name and return the first one that is fulfilled + const [deployment, daemonSet, statefulSet, pod] = await Promise.allSettled([ + getApplicationByKind( + environmentId, + namespace, + 'Deployment', + name, + yaml + ), + getApplicationByKind( + environmentId, + namespace, + 'DaemonSet', + name, + yaml + ), + getApplicationByKind( + environmentId, + namespace, + 'StatefulSet', + name, + yaml + ), + getPod(environmentId, namespace, name, yaml), + ]); + + if (isFulfilled(deployment)) { + return deployment.value; + } + if (isFulfilled(daemonSet)) { + return daemonSet.value; + } + if (isFulfilled(statefulSet)) { + return statefulSet.value; + } + if (isFulfilled(pod)) { + return pod.value; + } + throw new Error('Unable to retrieve application'); } export async function patchApplication( @@ -167,44 +144,37 @@ export async function patchApplication( name: string, patch: ApplicationPatch ) { - try { - switch (appKind) { - case 'Deployment': - return await patchApplicationByKind( - environmentId, - namespace, - appKind, - name, - patch - ); - case 'DaemonSet': - return await patchApplicationByKind( - environmentId, - namespace, - appKind, - name, - patch, - 'application/strategic-merge-patch+json' - ); - case 'StatefulSet': - return await patchApplicationByKind( - environmentId, - namespace, - appKind, - name, - patch, - 'application/strategic-merge-patch+json' - ); - case 'Pod': - return await patchPod(environmentId, namespace, name, patch); - default: - throw new Error(`Unknown application kind ${appKind}`); - } - } catch (e) { - throw parseAxiosError( - e as Error, - `Unable to patch application ${name} in namespace '${namespace}'` - ); + switch (appKind) { + case 'Deployment': + return patchApplicationByKind( + environmentId, + namespace, + appKind, + name, + patch + ); + case 'DaemonSet': + return patchApplicationByKind( + environmentId, + namespace, + appKind, + name, + patch, + 'application/strategic-merge-patch+json' + ); + case 'StatefulSet': + return patchApplicationByKind( + environmentId, + namespace, + appKind, + name, + patch, + 'application/strategic-merge-patch+json' + ); + case 'Pod': + return patchPod(environmentId, namespace, name, patch); + default: + throw new Error(`Unknown application kind ${appKind}`); } } @@ -218,7 +188,7 @@ async function patchApplicationByKind( ) { try { const res = await axios.patch( - buildUrl(environmentId, namespace, `${appKind}s`, name), + buildUrl(environmentId, namespace, `${appKind}s`, `${name}sd`), patch, { headers: { @@ -228,7 +198,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 +220,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 +235,10 @@ 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 in namespace '${namespace}'` + ); } } @@ -350,7 +323,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 +343,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..fde6248b8 100644 --- a/app/react/kubernetes/applications/pod.service.ts +++ b/app/react/kubernetes/applications/pod.service.ts @@ -3,6 +3,8 @@ import { Pod, PodList } from 'kubernetes-types/core/v1'; import { EnvironmentId } from '@/react/portainer/environments/types'; import axios, { parseAxiosError } from '@/portainer/services/axios'; +import { parseKubernetesAxiosError } from '../axiosError'; + import { ApplicationPatch } from './types'; export async function getNamespacePods( @@ -21,7 +23,10 @@ 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 in namespace '${namespace}'` + ); } } @@ -40,7 +45,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 +66,7 @@ export async function patchPod( } ); } catch (e) { - throw parseAxiosError(e as Error, 'Unable to update pod'); + throw parseAxiosError(e, 'Unable to update pod'); } } @@ -73,7 +78,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..deb0cbfdc 100644 --- a/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts +++ b/app/react/kubernetes/cluster/ConfigureView/ConfigureForm/useConfigureClusterMutation.ts @@ -8,8 +8,7 @@ import { UpdateEnvironmentPayload, updateEnvironment, } from '@/react/portainer/environments/queries/useUpdateEnvironmentMutation'; -import axios from '@/portainer/services/axios'; -import { parseKubernetesAxiosError } from '@/react/kubernetes/axiosError'; +import axios, { parseAxiosError } from '@/portainer/services/axios'; import { updateIngressControllerClassMap } from '../../ingressClass/useIngressControllerClassMap'; import { IngressControllerClassMap } from '../../ingressClass/types'; @@ -72,9 +71,6 @@ async function patchStorageClass( } ); } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - `Unable to patch StorageClass ${name}` - ); + throw parseAxiosError(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/getIsRBACEnabled.ts b/app/react/kubernetes/cluster/getIsRBACEnabled.ts index 67751786d..c36783a67 100644 --- a/app/react/kubernetes/cluster/getIsRBACEnabled.ts +++ b/app/react/kubernetes/cluster/getIsRBACEnabled.ts @@ -1,7 +1,6 @@ import { useQuery } from 'react-query'; -import PortainerError from '@/portainer/error'; -import axios from '@/portainer/services/axios'; +import axios, { parseAxiosError } from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; import { withError } from '@/react-tools/react-query'; @@ -23,6 +22,6 @@ export async function getIsRBACEnabled(environmentId: EnvironmentId) { ); return data; } catch (e) { - throw new PortainerError('Unable to check if RBAC is enabled.', e as Error); + throw parseAxiosError(e, 'Unable to check if RBAC is enabled.'); } } 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/ingressClass/useIngressControllerClassMap.ts b/app/react/kubernetes/cluster/ingressClass/useIngressControllerClassMap.ts index 64fe37394..145b5c422 100644 --- a/app/react/kubernetes/cluster/ingressClass/useIngressControllerClassMap.ts +++ b/app/react/kubernetes/cluster/ingressClass/useIngressControllerClassMap.ts @@ -1,8 +1,7 @@ import { useQuery } from 'react-query'; import { EnvironmentId } from '@/react/portainer/environments/types'; -import PortainerError from '@/portainer/error'; -import axios from '@/portainer/services/axios'; +import axios, { parseAxiosError } from '@/portainer/services/axios'; import { withError } from '@/react-tools/react-query'; import { IngressControllerClassMap } from './types'; @@ -61,7 +60,7 @@ export async function getIngressControllerClassMap({ ); return controllerMaps; } catch (e) { - throw new PortainerError('Unable to get ingress controllers.', e as Error); + throw parseAxiosError(e, 'Unable to get ingress controllers.'); } } @@ -77,10 +76,7 @@ export async function updateIngressControllerClassMap( >(buildUrl(environmentId, namespace), ingressControllerClassMap); return controllerMaps; } catch (e) { - throw new PortainerError( - 'Unable to update ingress controllers.', - e as Error - ); + throw parseAxiosError(e, 'Unable to update ingress controllers.'); } } 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..0d4ff73b3 100644 --- a/app/react/kubernetes/configs/configmap.service.ts +++ b/app/react/kubernetes/configs/configmap.service.ts @@ -10,6 +10,7 @@ import { } from '@/portainer/services/notifications'; import { isFulfilled, isRejected } from '@/portainer/helpers/promise-utils'; import { pluralize } from '@/portainer/helpers/strings'; +import PortainerError from '@/portainer/error'; import { parseKubernetesAxiosError } from '../axiosError'; @@ -127,10 +128,7 @@ async function getConfigMapsForCluster( ); return configMaps.flat(); } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - 'Unable to retrieve ConfigMaps for cluster' - ); + throw new PortainerError('Unable to retrieve ConfigMaps', e); } } @@ -142,10 +140,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 +152,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..f808366a2 100644 --- a/app/react/kubernetes/configs/secret.service.ts +++ b/app/react/kubernetes/configs/secret.service.ts @@ -10,6 +10,7 @@ import { } from '@/portainer/services/notifications'; import { isFulfilled, isRejected } from '@/portainer/helpers/promise-utils'; import { pluralize } from '@/portainer/helpers/strings'; +import PortainerError from '@/portainer/error'; import { parseKubernetesAxiosError } from '../axiosError'; @@ -123,10 +124,7 @@ async function getSecretsForCluster( ); return secrets.flat(); } catch (e) { - throw parseKubernetesAxiosError( - e as Error, - 'Unable to retrieve secrets for cluster' - ); + throw new PortainerError('Unable to retrieve secrets for cluster', e); } } @@ -138,7 +136,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 +148,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..8bd181426 100644 --- a/app/react/kubernetes/volumes/service.ts +++ b/app/react/kubernetes/volumes/service.ts @@ -1,23 +1,18 @@ import { PersistentVolumeClaimList } from 'kubernetes-types/core/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 getPVCsForCluster( environmentId: EnvironmentId, namespaces: string[] ) { - try { - const pvcs = await Promise.all( - namespaces.map((namespace) => getPVCs(environmentId, namespace)) - ); - return pvcs.flat(); - } catch (e) { - throw parseAxiosError( - e as Error, - 'Unable to retrieve persistent volume claims for cluster' - ); - } + const pvcs = await Promise.all( + namespaces.map((namespace) => getPVCs(environmentId, namespace)) + ); + return pvcs.flat(); } // get all persistent volume claims for a namespace @@ -28,8 +23,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' ); }