1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-04 21:35:23 +02:00

refactor(k8s): namespace core logic (#12142)

Co-authored-by: testA113 <aliharriss1995@gmail.com>
Co-authored-by: Anthony Lapenna <anthony.lapenna@portainer.io>
Co-authored-by: James Carppe <85850129+jamescarppe@users.noreply.github.com>
Co-authored-by: Ali <83188384+testA113@users.noreply.github.com>
This commit is contained in:
Steven Kang 2024-10-01 14:15:51 +13:00 committed by GitHub
parent da010f3d08
commit ea228c3d6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
276 changed files with 9241 additions and 3361 deletions

View file

@ -3,11 +3,9 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import {
mutationOptions,
withError,
withGlobalError,
withInvalidate,
} from '@/react-tools/react-query';
import { getServices } from '@/react/kubernetes/networks/services/service';
import { isFulfilled } from '@/portainer/helpers/promise-utils';
import {
getIngresses,
@ -19,13 +17,23 @@ import {
} from './service';
import { DeleteIngressesRequest, Ingress } from './types';
const ingressKeys = {
all: ['environments', 'kubernetes', 'namespace', 'ingress'] as const,
namespace: (
const queryKeys = {
base: ['environments', 'kubernetes', 'ingress'] as const,
clusterIngresses: (environmentId: EnvironmentId) =>
[...queryKeys.base, String(environmentId)] as const,
namespaceIngresses: (
environmentId: EnvironmentId,
namespace: string,
ingress: string
) => [...ingressKeys.all, String(environmentId), namespace, ingress] as const,
) => [...queryKeys.base, String(environmentId), namespace, ingress] as const,
ingress: (environmentId: EnvironmentId, namespace: string, name: string) =>
[...queryKeys.base, String(environmentId), namespace, name] as const,
ingressControllers: (environmentId: EnvironmentId, namespace: string) => [
...queryKeys.base,
String(environmentId),
namespace,
'ingresscontrollers',
],
};
export function useIngress(
@ -34,93 +42,34 @@ export function useIngress(
name: string
) {
return useQuery(
[
'environments',
environmentId,
'kubernetes',
'namespace',
namespace,
'ingress',
name,
],
queryKeys.ingress(environmentId, namespace, name),
async () => {
const ing = await getIngress(environmentId, namespace, name);
return ing;
},
{
...withError('Unable to get ingress'),
...withGlobalError('Unable to get ingress'),
}
);
}
export function useIngresses(
environmentId: EnvironmentId,
namespaces?: string[],
options?: { autoRefreshRate?: number }
options?: {
autoRefreshRate?: number;
enabled?: boolean;
withServices?: boolean;
}
) {
const { enabled, autoRefreshRate, ...params } = options ?? {};
return useQuery(
[
'environments',
environmentId,
'kubernetes',
'namespace',
namespaces,
'ingress',
],
async () => {
if (!namespaces?.length) {
return [];
}
const settledIngressesPromise = await Promise.allSettled(
namespaces.map((namespace) => getIngresses(environmentId, namespace))
);
const ingresses = settledIngressesPromise
.filter(isFulfilled)
?.map((i) => i.value);
// flatten the array and remove empty ingresses
const filteredIngresses = ingresses.flat().filter((ing) => ing);
// get all services in only the namespaces that the ingresses are in to find missing services
const uniqueNamespacesWithIngress = [
...new Set(filteredIngresses.map((ing) => ing?.Namespace)),
];
const settledServicesPromise = await Promise.allSettled(
uniqueNamespacesWithIngress.map((ns) => getServices(environmentId, ns))
);
const services = settledServicesPromise
.filter(isFulfilled)
?.map((s) => s.value)
.flat();
// check if each ingress path service has a service that still exists
const updatedFilteredIngresses: Ingress[] = filteredIngresses.map(
(ing) => {
const servicesInNamespace = services?.filter(
(service) => service?.Namespace === ing?.Namespace
);
const serviceNamesInNamespace = servicesInNamespace?.map(
(service) => service.Name
);
const updatedPaths =
ing.Paths?.map((path) => {
const hasService = serviceNamesInNamespace?.includes(
path.ServiceName
);
return { ...path, HasService: hasService };
}) || null;
return { ...ing, Paths: updatedPaths };
}
);
return updatedFilteredIngresses;
},
['environments', environmentId, 'kubernetes', 'ingress', params],
async () => getIngresses(environmentId, params),
{
enabled: !!namespaces?.length,
...withError('Unable to get ingresses'),
refetchInterval() {
return options?.autoRefreshRate ?? false;
},
...withGlobalError('Unable to get ingresses'),
refetchInterval: autoRefreshRate,
enabled,
}
);
}
@ -136,8 +85,8 @@ export function useCreateIngress() {
ingress: Ingress;
}) => createIngress(environmentId, ingress),
mutationOptions(
withError('Unable to create ingress controller'),
withInvalidate(queryClient, [ingressKeys.all])
withGlobalError('Unable to create ingress controller'),
withInvalidate(queryClient, [queryKeys.base])
)
);
}
@ -153,8 +102,8 @@ export function useUpdateIngress() {
ingress: Ingress;
}) => updateIngress(environmentId, ingress),
mutationOptions(
withError('Unable to update ingress controller'),
withInvalidate(queryClient, [ingressKeys.all])
withGlobalError('Unable to update ingress controller'),
withInvalidate(queryClient, [queryKeys.base])
)
);
}
@ -170,8 +119,8 @@ export function useDeleteIngresses() {
data: DeleteIngressesRequest;
}) => deleteIngresses(environmentId, data),
mutationOptions(
withError('Unable to update ingress controller'),
withInvalidate(queryClient, [ingressKeys.all])
withGlobalError('Unable to update ingress controller'),
withInvalidate(queryClient, [queryKeys.base])
)
);
}
@ -185,21 +134,14 @@ export function useIngressControllers(
allowedOnly?: boolean
) {
return useQuery(
[
'environments',
environmentId,
'kubernetes',
'namespace',
namespace,
'ingresscontrollers',
],
queryKeys.ingressControllers(environmentId, namespace ?? ''),
async () =>
namespace
? getIngressControllers(environmentId, namespace, allowedOnly)
: [],
{
enabled: !!namespace,
...withError('Unable to get ingress controllers'),
...withGlobalError('Unable to get ingress controllers'),
}
);
}