import { useMutation, useQueryClient } from '@tanstack/react-query'; import axios, { parseAxiosError } from '@/portainer/services/axios'; import { EnvironmentId } from '@/react/portainer/environments/types'; import { Registry } from '@/react/portainer/registries/types/registry'; import { useEnvironmentRegistries } from '@/react/portainer/environments/queries/useEnvironmentRegistries'; import { withGlobalError, withInvalidate } from '@/react-tools/react-query'; import { buildImageFullURI } from '../utils'; import { withRegistryAuthHeader, withAgentTargetHeader, } from '../../proxy/queries/utils'; import { buildDockerProxyUrl } from '../../proxy/queries/buildDockerProxyUrl'; import { queryKeys } from './queryKeys'; type UsePullImageMutation = Omit & { registryId?: Registry['Id']; }; export function usePullImageMutation(envId: EnvironmentId) { const queryClient = useQueryClient(); const registriesQuery = useEnvironmentRegistries(envId); return useMutation({ mutationFn: (args: UsePullImageMutation) => pullImage({ ...args, registry: getRegistry(registriesQuery.data || [], args.registryId), }), ...withGlobalError('Failure', 'Failed pulling image'), ...withInvalidate(queryClient, [queryKeys.base(envId)]), }); } function getRegistry(registries: Registry[], registryId?: Registry['Id']) { return registryId ? registries.find((registry) => registry.Id === registryId) : undefined; } interface PullImageOptions { environmentId: EnvironmentId; image: string; nodeName?: string; registry?: Registry; ignoreErrors: boolean; } export async function pullImage({ environmentId, ignoreErrors, image, nodeName, registry, }: PullImageOptions) { const imageURI = buildImageFullURI(image, registry); try { await axios.post( buildDockerProxyUrl(environmentId, 'images', 'create'), null, { params: { fromImage: imageURI, }, headers: { ...withRegistryAuthHeader(registry?.Id), ...withAgentTargetHeader(nodeName), }, } ); } catch (err) { if (ignoreErrors) { return; } throw parseAxiosError(err, 'Unable to pull image'); } }