1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 15:55:23 +02:00

allow nested kube error that's thrown to bubble up

This commit is contained in:
testa113 2023-10-17 01:49:26 +01:00
parent cb8174bd24
commit 749a9d1a47
3 changed files with 128 additions and 161 deletions

View file

@ -31,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
@ -54,34 +47,23 @@ async function getApplicationsForNamespace(
environmentId: EnvironmentId,
namespace: string
) {
try {
const [deployments, daemonSets, statefulSets, pods] = await Promise.all([
getApplicationsByKind<DeploymentList>(
environmentId,
namespace,
'Deployment'
),
getApplicationsByKind<DaemonSetList>(
environmentId,
namespace,
'DaemonSet'
),
getApplicationsByKind<StatefulSetList>(
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<DeploymentList>(
environmentId,
namespace,
'Deployment'
),
getApplicationsByKind<DaemonSetList>(environmentId, namespace, 'DaemonSet'),
getApplicationsByKind<StatefulSetList>(
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
@ -94,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<T>(
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<T>(
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<Deployment>(
environmentId,
namespace,
'Deployment',
name,
yaml
),
getApplicationByKind<DaemonSet>(
environmentId,
namespace,
'DaemonSet',
name,
yaml
),
getApplicationByKind<StatefulSet>(
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<Deployment>(
environmentId,
namespace,
'Deployment',
name,
yaml
),
getApplicationByKind<DaemonSet>(
environmentId,
namespace,
'DaemonSet',
name,
yaml
),
getApplicationByKind<StatefulSet>(
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(
@ -169,44 +144,37 @@ export async function patchApplication(
name: string,
patch: ApplicationPatch
) {
try {
switch (appKind) {
case 'Deployment':
return await patchApplicationByKind<Deployment>(
environmentId,
namespace,
appKind,
name,
patch
);
case 'DaemonSet':
return await patchApplicationByKind<DaemonSet>(
environmentId,
namespace,
appKind,
name,
patch,
'application/strategic-merge-patch+json'
);
case 'StatefulSet':
return await patchApplicationByKind<StatefulSet>(
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<Deployment>(
environmentId,
namespace,
appKind,
name,
patch
);
case 'DaemonSet':
return patchApplicationByKind<DaemonSet>(
environmentId,
namespace,
appKind,
name,
patch,
'application/strategic-merge-patch+json'
);
case 'StatefulSet':
return patchApplicationByKind<StatefulSet>(
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}`);
}
}
@ -220,7 +188,7 @@ async function patchApplicationByKind<T extends Application>(
) {
try {
const res = await axios.patch<T>(
buildUrl(environmentId, namespace, `${appKind}s`, name),
buildUrl(environmentId, namespace, `${appKind}s`, `${name}sd`),
patch,
{
headers: {
@ -230,7 +198,7 @@ async function patchApplicationByKind<T extends Application>(
);
return res;
} catch (e) {
throw parseAxiosError(e, 'Unable to patch application');
throw parseKubernetesAxiosError(e, 'Unable to patch application');
}
}
@ -267,7 +235,10 @@ async function getApplicationsByKind<T extends ApplicationList>(
);
return data.items as T['items'];
} catch (e) {
throw parseKubernetesAxiosError(e, `Unable to retrieve ${appKind}s`);
throw parseKubernetesAxiosError(
e,
`Unable to retrieve ${appKind}s in namespace '${namespace}'`
);
}
}

View file

@ -23,7 +23,10 @@ export async function getNamespacePods(
);
return data.items;
} catch (e) {
throw parseKubernetesAxiosError(e, 'Unable to retrieve pods');
throw parseKubernetesAxiosError(
e,
`Unable to retrieve pods in namespace '${namespace}'`
);
}
}

View file

@ -1,6 +1,6 @@
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';
@ -9,17 +9,10 @@ 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