portainer/app/react/docker/stacks/ItemView/useSwarmStackServices.ts

112 lines
3.4 KiB
TypeScript

import { useQueryClient } from '@tanstack/react-query';
import _ from 'lodash';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { useEnvironment } from '@/react/portainer/environments/queries';
import { isAgentEnvironment } from '@/react/portainer/environments/utils';
import { useTasks } from '@/react/docker/proxy/queries/tasks/useTasks';
import { queryKeys as tasksQueryKeys } from '@/react/docker/proxy/queries/tasks/query-keys';
import { TaskViewModel } from '@/docker/models/task';
import { useServices } from '@/react/docker/services/queries/useServices';
import { queryKeys as servicesQueryKeys } from '@/react/docker/services/queries/query-keys';
import { ServiceViewModel } from '@/docker/models/service';
import { useContainers } from '@/react/docker/containers/queries/useContainers';
import { queryKeys as containersQueryKeys } from '@/react/docker/containers/queries/query-keys';
import { ContainerListViewModel } from '@/react/docker/containers/types';
import { SWARM_STACK_NAME_LABEL } from '@/react/constants';
import { associateContainerToTask } from '../../tasks/utils';
import { associateServiceTasks } from '../../services/utils';
export function useSwarmStackResources(
stackName: string,
{ enabled }: { enabled?: boolean } = {}
) {
const queryClient = useQueryClient();
const environmentId = useEnvironmentId();
const isAgentQuery = useEnvironment(environmentId, (env) =>
isAgentEnvironment(env.Type)
);
const stackFilter = {
label: [`${SWARM_STACK_NAME_LABEL}=${stackName}`],
};
const isAgent = isAgentQuery.data || false;
const servicesQuery = useServices(
{ environmentId, filters: stackFilter },
{
enabled,
select: (services) => services.map((s) => new ServiceViewModel(s)),
}
);
const tasksQuery = useTasks(
{
environmentId,
filters: stackFilter,
},
{ enabled, select: (tasks) => tasks.map((t) => new TaskViewModel(t)) }
);
const containersQuery = useContainers(environmentId, {
enabled: enabled && isAgent,
});
const containerQueryIsLoading = isAgent && containersQuery.isLoading;
if (!servicesQuery.data || !tasksQuery.data || containerQueryIsLoading) {
return {
data: undefined,
isLoading: true,
};
}
const containers =
isAgent && containersQuery.data ? containersQuery.data : [];
const data = assignSwarmStackResources({
services: servicesQuery.data,
tasks: tasksQuery.data,
isAgent,
containers,
});
return {
data,
isLoading: false,
refetch: () =>
Promise.all(
_.compact([
queryClient.invalidateQueries(servicesQueryKeys.list(environmentId)),
queryClient.invalidateQueries(tasksQueryKeys.list(environmentId)),
isAgent &&
queryClient.invalidateQueries(
containersQueryKeys.list(environmentId)
),
])
),
};
}
function assignSwarmStackResources({
services,
tasks,
isAgent,
containers,
}: {
services: ServiceViewModel[];
tasks: TaskViewModel[];
isAgent: boolean;
containers: ContainerListViewModel[];
}) {
const associatedTasks = isAgent
? tasks.map((task) => associateContainerToTask(task, containers))
: tasks;
return services.map((service) => {
const serviceTasks = associateServiceTasks(service, associatedTasks);
return {
...service,
Tasks: serviceTasks,
};
});
}