diff --git a/app/react/common/stacks/queries/query-keys.ts b/app/react/common/stacks/queries/query-keys.ts index e57fc2f60..e18073697 100644 --- a/app/react/common/stacks/queries/query-keys.ts +++ b/app/react/common/stacks/queries/query-keys.ts @@ -1,6 +1,6 @@ import { StackId } from '../types'; export const stacksQueryKeys = { - stackFile: (stackId: StackId) => ['stacks', stackId, 'file'], - stacks: ['stacks'], + stackFile: (stackId: StackId) => ['stacks', stackId, 'file'] as const, + stacks: ['stacks'] as const, }; diff --git a/app/react/common/stacks/queries/useStack.ts b/app/react/common/stacks/queries/useStack.ts new file mode 100644 index 000000000..93ecf0522 --- /dev/null +++ b/app/react/common/stacks/queries/useStack.ts @@ -0,0 +1,29 @@ +import { useQuery } from 'react-query'; + +import axios, { parseAxiosError } from '@/portainer/services/axios'; +import { withError } from '@/react-tools/react-query'; + +import { Stack, StackId } from '../types'; + +import { stacksQueryKeys } from './query-keys'; +import { buildStackUrl } from './buildUrl'; + +export function useStack(stackId?: StackId) { + return useQuery( + stacksQueryKeys.stackFile(stackId || 0), + () => getStack(stackId!), + { + ...withError('Unable to retrieve stack'), + enabled: !!stackId, + } + ); +} + +async function getStack(stackId: StackId) { + try { + const { data } = await axios.get(buildStackUrl(stackId)); + return data; + } catch (err) { + throw parseAxiosError(err, 'Unable to retrieve stack'); + } +} diff --git a/app/react/common/stacks/queries/useStackFile.ts b/app/react/common/stacks/queries/useStackFile.ts new file mode 100644 index 000000000..66ee51d7e --- /dev/null +++ b/app/react/common/stacks/queries/useStackFile.ts @@ -0,0 +1,29 @@ +import { useQuery } from 'react-query'; + +import axios, { parseAxiosError } from '@/portainer/services/axios'; +import { withError } from '@/react-tools/react-query'; + +import { StackFile, StackId } from '../types'; + +import { stacksQueryKeys } from './query-keys'; +import { buildStackUrl } from './buildUrl'; + +export function useStackFile(stackId?: StackId) { + return useQuery( + stacksQueryKeys.stackFile(stackId || 0), + () => getStackFile(stackId!), + { + ...withError('Unable to retrieve stack'), + enabled: !!stackId, + } + ); +} + +async function getStackFile(stackId: StackId) { + try { + const { data } = await axios.get(buildStackUrl(stackId, 'file')); + return data; + } catch (err) { + throw parseAxiosError(err, 'Unable to retrieve stack file'); + } +} diff --git a/app/react/common/stacks/queries/useStackQuery.ts b/app/react/common/stacks/queries/useStackQuery.ts deleted file mode 100644 index 371dc3073..000000000 --- a/app/react/common/stacks/queries/useStackQuery.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { useQuery } from 'react-query'; - -import axios from '@/portainer/services/axios'; -import { withError } from '@/react-tools/react-query'; - -import { Stack, StackFile, StackId } from '../types'; - -import { stacksQueryKeys } from './query-keys'; -import { buildStackUrl } from './buildUrl'; - -export function useStackQuery(stackId?: StackId) { - return useQuery( - stacksQueryKeys.stackFile(stackId || 0), - () => getStack(stackId), - { - ...withError('Unable to retrieve stack'), - enabled: !!stackId, - } - ); -} - -async function getStack(stackId?: StackId) { - if (!stackId) { - return Promise.resolve(undefined); - } - const { data } = await axios.get(buildStackUrl(stackId)); - return data; -} - -export function useStackFileQuery(stackId?: StackId) { - return useQuery( - stacksQueryKeys.stackFile(stackId || 0), - () => getStackFile(stackId), - { - ...withError('Unable to retrieve stack'), - enabled: !!stackId, - } - ); -} - -async function getStackFile(stackId?: StackId) { - if (!stackId) { - return Promise.resolve(undefined); - } - const { data } = await axios.get(buildStackUrl(stackId, 'file')); - return data; -} diff --git a/app/react/common/stacks/queries/useUpdateKubeGitStackMutation.ts b/app/react/common/stacks/queries/useUpdateKubeGitStackMutation.ts index a2d779f11..3bf7cc32c 100644 --- a/app/react/common/stacks/queries/useUpdateKubeGitStackMutation.ts +++ b/app/react/common/stacks/queries/useUpdateKubeGitStackMutation.ts @@ -1,44 +1,65 @@ import { useMutation } from 'react-query'; -import axios from '@/portainer/services/axios'; +import axios, { parseAxiosError } from '@/portainer/services/axios'; import { withError, withInvalidate, queryClient, } from '@/react-tools/react-query'; -import { StackId } from '@/react/common/stacks/types'; +import { Stack, StackId } from '@/react/common/stacks/types'; import { EnvironmentId } from '@/react/portainer/environments/types'; -import { AutoUpdateModel } from '@/react/portainer/gitops/types'; +import { stacksQueryKeys } from '@/react/common/stacks/queries/query-keys'; +import { buildStackUrl } from '@/react/common/stacks/queries/buildUrl'; +import { + AutoUpdateResponse, + GitAuthModel, + GitCredentialsModel, +} from '@/react/portainer/gitops/types'; +import { saveGitCredentialsIfNeeded } from '@/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation'; -import { stacksQueryKeys } from './query-keys'; -import { buildStackUrl } from './buildUrl'; - -type UpdateKubeGitStackPayload = { - AutoUpdate: AutoUpdateModel; - RepositoryAuthentication: boolean; - RepositoryGitCredentialID: number; - RepositoryPassword: string; +export interface UpdateKubeGitStackPayload extends GitCredentialsModel { + AutoUpdate: AutoUpdateResponse | null; RepositoryReferenceName: string; - RepositoryUsername: string; TLSSkipVerify: boolean; -}; +} // update a stack from a git repository export function useUpdateKubeGitStackMutation( stackId: StackId, - environmentId: EnvironmentId + environmentId: EnvironmentId, + userId: number ) { return useMutation( - (stack: UpdateKubeGitStackPayload) => - updateGitStack({ stack, stackId, environmentId }), + async ({ + stack, + authentication, + }: { + stack: UpdateKubeGitStackPayload; + authentication: GitAuthModel; + }) => { + // save the new git credentials if the user has selected to save them + const newGitAuth = await saveGitCredentialsIfNeeded( + userId, + authentication + ); + const stackWithUpdatedAuth: UpdateKubeGitStackPayload = { + ...stack, + ...newGitAuth, + }; + return updateGitStack({ + stack: stackWithUpdatedAuth, + stackId, + environmentId, + }); + }, { - ...withError('Unable to update stack'), + ...withError('Unable to update application'), ...withInvalidate(queryClient, [stacksQueryKeys.stackFile(stackId)]), } ); } -function updateGitStack({ +async function updateGitStack({ stackId, stack, environmentId, @@ -47,7 +68,11 @@ function updateGitStack({ stack: UpdateKubeGitStackPayload; environmentId: EnvironmentId; }) { - return axios.put(buildStackUrl(stackId), stack, { - params: { endpointId: environmentId }, - }); + try { + return await axios.post(buildStackUrl(stackId, 'git'), stack, { + params: { endpointId: environmentId }, + }); + } catch (e) { + throw parseAxiosError(e, 'Unable to update stack'); + } } diff --git a/app/react/components/form-components/FormActions.tsx b/app/react/components/form-components/FormActions.tsx index 6b804d777..42c699009 100644 --- a/app/react/components/form-components/FormActions.tsx +++ b/app/react/components/form-components/FormActions.tsx @@ -1,4 +1,4 @@ -import { PropsWithChildren } from 'react'; +import { PropsWithChildren, ReactNode } from 'react'; import { AutomationTestingProps } from '@/types'; @@ -11,6 +11,7 @@ interface Props extends AutomationTestingProps { loadingText: string; isLoading: boolean; isValid: boolean; + submitButtonIcon?: ReactNode; } export function FormActions({ @@ -19,6 +20,7 @@ export function FormActions({ isLoading, children, isValid, + submitButtonIcon, 'data-cy': dataCy, }: PropsWithChildren) { return ( @@ -30,6 +32,7 @@ export function FormActions({ loadingText={loadingText} isLoading={isLoading} disabled={!isValid} + icon={submitButtonIcon} data-cy={dataCy} > {submitLabel} diff --git a/app/react/kubernetes/applications/DetailsView/ApplicationDetailsWidget/ApplicationDetailsWidget.tsx b/app/react/kubernetes/applications/DetailsView/ApplicationDetailsWidget/ApplicationDetailsWidget.tsx index 5bacc4cc3..36f212a50 100644 --- a/app/react/kubernetes/applications/DetailsView/ApplicationDetailsWidget/ApplicationDetailsWidget.tsx +++ b/app/react/kubernetes/applications/DetailsView/ApplicationDetailsWidget/ApplicationDetailsWidget.tsx @@ -3,7 +3,7 @@ import { useCurrentStateAndParams } from '@uirouter/react'; import { Pod } from 'kubernetes-types/core/v1'; import { Authorized } from '@/react/hooks/useUser'; -import { useStackFileQuery } from '@/react/common/stacks/queries/useStackQuery'; +import { useStackFile } from '@/react/common/stacks/queries/useStackFile'; import { Widget, WidgetBody } from '@@/Widget'; import { Button } from '@@/buttons'; @@ -48,7 +48,7 @@ export function ApplicationDetailsWidget() { ); const externalApp = app && isExternalApplication(app); const appStackId = Number(app?.metadata?.labels?.[appStackIdLabel]); - const appStackFileQuery = useStackFileQuery(appStackId); + const appStackFileQuery = useStackFile(appStackId); const { data: appServices } = useApplicationServices( environmentId, namespace, diff --git a/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppForm.tsx b/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppForm.tsx index ab9552025..91a361749 100644 --- a/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppForm.tsx +++ b/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppForm.tsx @@ -1,53 +1,33 @@ -import { Form, Formik, FormikHelpers, useFormikContext } from 'formik'; -import { useRef, useState } from 'react'; -import { RefreshCw } from 'lucide-react'; -import { useRouter } from '@uirouter/react'; +import { Formik, FormikHelpers } from 'formik'; +import { useRef } from 'react'; +import { + UpdateKubeGitStackPayload, + useUpdateKubeGitStackMutation, +} from '@/react/common/stacks/queries/useUpdateKubeGitStackMutation'; import { Stack, StackId } from '@/react/common/stacks/types'; import { parseAutoUpdateResponse, transformAutoUpdateViewModel, } from '@/react/portainer/gitops/AutoUpdateFieldset/utils'; -import { AutoUpdateFieldset } from '@/react/portainer/gitops/AutoUpdateFieldset'; -import { - AutoUpdateMechanism, - AutoUpdateModel, -} from '@/react/portainer/gitops/types'; -import { - baseStackWebhookUrl, - createWebhookId, -} from '@/portainer/helpers/webhookHelper'; -import { TimeWindowDisplay } from '@/react/portainer/gitops/TimeWindowDisplay'; -import { RefField } from '@/react/portainer/gitops/RefField'; +import { AutoUpdateMechanism } from '@/react/portainer/gitops/types'; +import { createWebhookId } from '@/portainer/helpers/webhookHelper'; import { parseAuthResponse } from '@/react/portainer/gitops/AuthFieldset/utils'; -import { confirmEnableTLSVerify } from '@/react/portainer/gitops/utils'; -import { AuthFieldset } from '@/react/portainer/gitops/AuthFieldset'; import { useGitCredentials } from '@/react/portainer/account/git-credentials/git-credentials.service'; import { useCurrentUser } from '@/react/hooks/useUser'; import { useAnalytics } from '@/react/hooks/useAnalytics'; import { RepositoryMechanismTypes } from '@/kubernetes/models/deploy'; -import { useCreateGitCredentialMutation } from '@/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation'; import { useEnvironmentId } from '@/react/hooks/useEnvironmentId'; import { notifySuccess } from '@/portainer/services/notifications'; -import { useStackQuery } from '@/react/common/stacks/queries/useStackQuery'; +import { useStack } from '@/react/common/stacks/queries/useStack'; import { FormSection } from '@@/form-components/FormSection'; -import { SwitchField } from '@@/form-components/SwitchField'; -import { LoadingButton } from '@@/buttons'; -import { buildConfirmButton } from '@@/modals/utils'; -import { confirm } from '@@/modals/confirm'; -import { ModalType } from '@@/modals'; import { InlineLoader } from '@@/InlineLoader'; import { Alert } from '@@/Alert'; -import { useUpdateKubeGitStackMutation } from './queries/useUpdateKubeGitStackMutation'; -import { - KubeAppGitFormValues, - RedeployGitStackPayload, - UpdateKubeGitStackPayload, -} from './types'; +import { KubeAppGitFormValues } from './types'; import { redeployGitAppFormValidationSchema } from './redeployGitAppFormValidationSchema'; -import { useRedeployKubeGitStackMutation } from './queries/useRedeployKubeGitStackMutation'; +import { RedeployGitAppInnerForm } from './RedeployGitAppInnerForm'; type Props = { stackId: StackId; @@ -55,7 +35,7 @@ type Props = { }; export function RedeployGitAppForm({ stackId, namespaceName }: Props) { - const { data: stack, ...stackQuery } = useStackQuery(stackId); + const { data: stack, ...stackQuery } = useStack(stackId); const { trackEvent } = useAnalytics(); const initialValues = getInitialValues(stack); const { user } = useCurrentUser(); @@ -63,10 +43,10 @@ export function RedeployGitAppForm({ stackId, namespaceName }: Props) { user.Id ); const environmentId = useEnvironmentId(); - const createGitCredentialMutation = useCreateGitCredentialMutation(); const updateKubeGitStackMutation = useUpdateKubeGitStackMutation( stack?.Id || 0, - environmentId + environmentId, + user.Id ); // keep a single generated webhook id, so that it doesn't change on every render const generatedWebhookId = useRef(createWebhookId()); @@ -122,40 +102,24 @@ export function RedeployGitAppForm({ stackId, namespaceName }: Props) { ) { trackSubmit(values); - // save the new git credentials if the user has selected to save them - if ( - values.authentication.SaveCredential && - values.authentication.NewCredentialName && - values.authentication.RepositoryPassword && - values.authentication.RepositoryUsername - ) { - createGitCredentialMutation.mutate({ - name: values.authentication.NewCredentialName, - username: values.authentication.RepositoryUsername, - password: values.authentication.RepositoryPassword, - userId: user.Id, - }); - } - // update the kubernetes git stack const { authentication } = values; const updateKubeGitStack: UpdateKubeGitStackPayload = { - RepositoryAuthentication: - !!values.authentication.RepositoryAuthentication, RepositoryReferenceName: values.repositoryReferenceName, AutoUpdate: transformAutoUpdateViewModel(values.autoUpdate, webhookId), TLSSkipVerify: values.tlsSkipVerify, - RepositoryGitCredentialID: authentication.RepositoryGitCredentialID, - RepositoryPassword: authentication.RepositoryPassword, - RepositoryUsername: authentication.RepositoryUsername, + ...authentication, }; - await updateKubeGitStackMutation.mutateAsync(updateKubeGitStack, { - onSuccess: ({ data: newStack }) => { - const newInitialValues = getInitialValues(newStack); - notifySuccess('Success', 'Application saved successfully.'); - resetForm({ values: newInitialValues }); - }, - }); + await updateKubeGitStackMutation.mutateAsync( + { stack: updateKubeGitStack, authentication }, + { + onSuccess: ({ data: newStack }) => { + const newInitialValues = getInitialValues(newStack); + notifySuccess('Success', 'Application saved successfully.'); + resetForm({ values: newInitialValues }); + }, + } + ); } function trackSubmit(values: KubeAppGitFormValues) { @@ -184,168 +148,6 @@ export function RedeployGitAppForm({ stackId, namespaceName }: Props) { } } -function RedeployGitAppInnerForm({ - stack, - namespaceName, - webhookId, -}: { - stack: Stack; - namespaceName: string; - webhookId: string; -}) { - const router = useRouter(); - const environmentId = useEnvironmentId(); - const redeployKubeGitStackMutation = useRedeployKubeGitStackMutation( - stack.Id, - environmentId - ); - const [isRedeployLoading, setIsRedeployLoading] = useState(false); - const { trackEvent } = useAnalytics(); - const { - values, - errors, - setFieldValue, - handleSubmit, - dirty, - isValid, - isSubmitting, - setFieldTouched, - } = useFormikContext(); - - return ( -
- - setFieldValue('autoUpdate', value) - } - baseWebhookUrl={baseStackWebhookUrl()} - webhookId={webhookId} - errors={errors.autoUpdate} - environmentType="KUBERNETES" - isForcePullVisible={false} - webhooksDocs="https://docs.portainer.io/user/kubernetes/applications/webhooks" - /> - - - - setFieldValue('repositoryReferenceName', refName) - } - model={{ - ...values.authentication, - RepositoryURL: values.repositoryURL, - }} - error={errors.repositoryReferenceName} - stackId={stack.Id} - isUrlValid - /> - - Object.entries(value).forEach(([key, value]) => { - setFieldValue(key, value); - // set touched after a delay to revalidate debounced username and access token fields - setTimeout(() => setFieldTouched(key, true), 400); - }) - } - errors={errors.authentication} - /> - - - -
-
- - Pull and update application - - - Save settings - -
-
-
- - ); - - async function handleRedeploy() { - const confirmed = await confirm({ - title: 'Are you sure?', - message: - 'Any changes to this application will be overridden by the definition in git and may cause a service interruption. Do you wish to continue?', - confirmButton: buildConfirmButton('Update', 'warning'), - modalType: ModalType.Warn, - }); - - if (!confirmed) { - return; - } - setIsRedeployLoading(true); - - // track the redeploy event - trackEvent('kubernetes-application-edit-git-pull', { - category: 'kubernetes', - }); - - // redeploy the application - const redeployPayload: RedeployGitStackPayload = { - RepositoryReferenceName: values.repositoryReferenceName, - RepositoryAuthentication: - !!values.authentication.RepositoryAuthentication, - RepositoryGitCredentialID: - values.authentication.RepositoryGitCredentialID, - RepositoryPassword: values.authentication.RepositoryPassword, - RepositoryUsername: values.authentication.RepositoryUsername, - Namespace: namespaceName, - }; - await redeployKubeGitStackMutation.mutateAsync(redeployPayload, { - onSuccess: () => { - notifySuccess('Success', 'Application redeployed successfully.'); - router.stateService.go('kubernetes.applications.application', { - id: stack.Id, - }); - }, - }); - - setIsRedeployLoading(false); - } - - async function onChangeTLSSkipVerify(value: boolean) { - // If the user is disabling TLS verification, ask for confirmation - if (stack.GitConfig?.TLSSkipVerify && !value) { - const confirmed = await confirmEnableTLSVerify(); - if (!confirmed) { - return; - } - } - setFieldValue('tlsSkipVerify', value); - } -} - function getInitialValues(stack?: Stack): KubeAppGitFormValues | undefined { if (!stack || !stack.GitConfig) { return undefined; diff --git a/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppInnerForm.tsx b/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppInnerForm.tsx new file mode 100644 index 000000000..e44620964 --- /dev/null +++ b/app/react/kubernetes/applications/components/RedeployGitAppForm/RedeployGitAppInnerForm.tsx @@ -0,0 +1,184 @@ +import { Form, useFormikContext } from 'formik'; +import { useState } from 'react'; +import { RefreshCw } from 'lucide-react'; +import { useRouter } from '@uirouter/react'; + +import { Stack } from '@/react/common/stacks/types'; +import { AutoUpdateFieldset } from '@/react/portainer/gitops/AutoUpdateFieldset'; +import { AutoUpdateModel } from '@/react/portainer/gitops/types'; +import { baseStackWebhookUrl } from '@/portainer/helpers/webhookHelper'; +import { TimeWindowDisplay } from '@/react/portainer/gitops/TimeWindowDisplay'; +import { RefField } from '@/react/portainer/gitops/RefField'; +import { confirmEnableTLSVerify } from '@/react/portainer/gitops/utils'; +import { AuthFieldset } from '@/react/portainer/gitops/AuthFieldset'; +import { useAnalytics } from '@/react/hooks/useAnalytics'; +import { useEnvironmentId } from '@/react/hooks/useEnvironmentId'; +import { notifySuccess } from '@/portainer/services/notifications'; + +import { FormSection } from '@@/form-components/FormSection'; +import { SwitchField } from '@@/form-components/SwitchField'; +import { LoadingButton } from '@@/buttons'; +import { buildConfirmButton } from '@@/modals/utils'; +import { confirm } from '@@/modals/confirm'; +import { ModalType } from '@@/modals'; +import { FormActions } from '@@/form-components/FormActions'; + +import { KubeAppGitFormValues, RedeployGitStackPayload } from './types'; +import { useRedeployKubeGitStackMutation } from './queries/useRedeployKubeGitStackMutation'; + +type Props = { + stack: Stack; + namespaceName: string; + webhookId: string; +}; + +export function RedeployGitAppInnerForm({ + stack, + namespaceName, + webhookId, +}: Props) { + const router = useRouter(); + const environmentId = useEnvironmentId(); + const redeployKubeGitStackMutation = useRedeployKubeGitStackMutation( + stack.Id, + environmentId + ); + const [isRedeployLoading, setIsRedeployLoading] = useState(false); + const { trackEvent } = useAnalytics(); + const { + values, + errors, + setFieldValue, + handleSubmit, + dirty, + isValid, + isSubmitting, + setFieldTouched, + } = useFormikContext(); + + return ( +
+ + setFieldValue('autoUpdate', value) + } + baseWebhookUrl={baseStackWebhookUrl()} + webhookId={webhookId} + errors={errors.autoUpdate} + environmentType="KUBERNETES" + isForcePullVisible={false} + webhooksDocs="https://docs.portainer.io/user/kubernetes/applications/webhooks" + /> + + + + setFieldValue('repositoryReferenceName', refName) + } + model={{ + ...values.authentication, + RepositoryURL: values.repositoryURL, + }} + error={errors.repositoryReferenceName} + stackId={stack.Id} + isUrlValid + /> + + Object.entries(value).forEach(([key, value]) => { + setFieldValue(key, value); + // set touched after a delay to revalidate debounced username and access token fields + setTimeout(() => setFieldTouched(key, true), 400); + }) + } + errors={errors.authentication} + /> + + + + + Pull and update application + + + + ); + + async function handleRedeploy() { + const confirmed = await confirm({ + title: 'Are you sure?', + message: + 'Any changes to this application will be overridden by the definition in git and may cause a service interruption. Do you wish to continue?', + confirmButton: buildConfirmButton('Update', 'warning'), + modalType: ModalType.Warn, + }); + + if (!confirmed) { + return; + } + setIsRedeployLoading(true); + + // track the redeploy event + trackEvent('kubernetes-application-edit-git-pull', { + category: 'kubernetes', + }); + + // redeploy the application + const redeployPayload: RedeployGitStackPayload = { + RepositoryReferenceName: values.repositoryReferenceName, + RepositoryAuthentication: + !!values.authentication.RepositoryAuthentication, + RepositoryGitCredentialID: + values.authentication.RepositoryGitCredentialID, + RepositoryPassword: values.authentication.RepositoryPassword, + RepositoryUsername: values.authentication.RepositoryUsername, + Namespace: namespaceName, + }; + await redeployKubeGitStackMutation.mutateAsync(redeployPayload, { + onSuccess: () => { + notifySuccess('Success', 'Application redeployed successfully.'); + router.stateService.go('kubernetes.applications.application', { + id: stack.Id, + }); + }, + }); + + setIsRedeployLoading(false); + } + + async function onChangeTLSSkipVerify(value: boolean) { + // If the user is disabling TLS verification, ask for confirmation + if (stack.GitConfig?.TLSSkipVerify && !value) { + const confirmed = await confirmEnableTLSVerify(); + if (!confirmed) { + return; + } + } + setFieldValue('tlsSkipVerify', value); + } +} diff --git a/app/react/kubernetes/applications/components/RedeployGitAppForm/queries/useUpdateKubeGitStackMutation.ts b/app/react/kubernetes/applications/components/RedeployGitAppForm/queries/useUpdateKubeGitStackMutation.ts deleted file mode 100644 index c8a646077..000000000 --- a/app/react/kubernetes/applications/components/RedeployGitAppForm/queries/useUpdateKubeGitStackMutation.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { useMutation } from 'react-query'; - -import axios, { parseAxiosError } from '@/portainer/services/axios'; -import { - withError, - withInvalidate, - queryClient, -} from '@/react-tools/react-query'; -import { Stack, StackId } from '@/react/common/stacks/types'; -import { EnvironmentId } from '@/react/portainer/environments/types'; -import { stacksQueryKeys } from '@/react/common/stacks/queries/query-keys'; -import { buildStackUrl } from '@/react/common/stacks/queries/buildUrl'; - -import { UpdateKubeGitStackPayload } from '../types'; - -// update a stack from a git repository -export function useUpdateKubeGitStackMutation( - stackId: StackId, - environmentId: EnvironmentId -) { - return useMutation( - (stack: UpdateKubeGitStackPayload) => - updateGitStack({ stack, stackId, environmentId }), - { - ...withError('Unable to update application.'), - ...withInvalidate(queryClient, [stacksQueryKeys.stackFile(stackId)]), - } - ); -} - -async function updateGitStack({ - stackId, - stack, - environmentId, -}: { - stackId: StackId; - stack: UpdateKubeGitStackPayload; - environmentId: EnvironmentId; -}) { - try { - return await axios.post(buildStackUrl(stackId, 'git'), stack, { - params: { endpointId: environmentId }, - }); - } catch (e) { - throw parseAxiosError(e); - } -} diff --git a/app/react/kubernetes/applications/components/RedeployGitAppForm/types.ts b/app/react/kubernetes/applications/components/RedeployGitAppForm/types.ts index 85510692a..e5b79a83e 100644 --- a/app/react/kubernetes/applications/components/RedeployGitAppForm/types.ts +++ b/app/react/kubernetes/applications/components/RedeployGitAppForm/types.ts @@ -1,6 +1,5 @@ import { AutoUpdateModel, - AutoUpdateResponse, GitAuthModel, GitCredentialsModel, } from '@/react/portainer/gitops/types'; @@ -13,12 +12,6 @@ export interface KubeAppGitFormValues { autoUpdate: AutoUpdateModel; } -export interface UpdateKubeGitStackPayload extends GitCredentialsModel { - AutoUpdate: AutoUpdateResponse | null; - RepositoryReferenceName: string; - TLSSkipVerify: boolean; -} - export interface RedeployGitStackPayload extends GitCredentialsModel { RepositoryReferenceName: string; Namespace: string; diff --git a/app/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation.ts b/app/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation.ts index 27b40c6ec..1fa0633b7 100644 --- a/app/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation.ts +++ b/app/react/portainer/account/git-credentials/queries/useCreateGitCredentialsMutation.ts @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from 'react-query'; import axios, { parseAxiosError } from '@/portainer/services/axios'; import { notifyError, notifySuccess } from '@/portainer/services/notifications'; -import { GitAuthModel, GitFormModel } from '@/react/portainer/gitops/types'; +import { GitAuthModel } from '@/react/portainer/gitops/types'; import { useCurrentUser } from '@/react/hooks/useUser'; import { UserId } from '@/portainer/users/types'; @@ -84,8 +84,8 @@ export function useSaveCredentialsIfRequired() { export async function saveGitCredentialsIfNeeded( userId: UserId, - gitModel: GitFormModel -) { + gitModel: GitAuthModel +): Promise { let credentialsId = gitModel.RepositoryGitCredentialID; let username = gitModel.RepositoryUsername; let password = gitModel.RepositoryPassword; diff --git a/app/react/portainer/templates/custom-templates/queries/useCreateTemplateMutation.ts b/app/react/portainer/templates/custom-templates/queries/useCreateTemplateMutation.ts index 3295ff803..f789cbc46 100644 --- a/app/react/portainer/templates/custom-templates/queries/useCreateTemplateMutation.ts +++ b/app/react/portainer/templates/custom-templates/queries/useCreateTemplateMutation.ts @@ -84,7 +84,8 @@ async function createTemplateAndGitCredential( userId: UserId, { Git: gitModel, ...values }: CreateTemplatePayload ) { - const newGitModel = await saveGitCredentialsIfNeeded(userId, gitModel); + const newGitAuthModel = await saveGitCredentialsIfNeeded(userId, gitModel); + const newGitModel = { ...gitModel, ...newGitAuthModel }; return createTemplateFromGit({ ...values,