Provisioning: Prevent sync if repository is not healthy (#110767)
* Provisioning: Prevent sync if repository is not healthy * Update alert position * Lint & i18n * Improve check * Update message * Remove info and add cancel button * Add spinner * Fix test
This commit is contained in:
@@ -3275,11 +3275,6 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"public/app/features/provisioning/Wizard/SynchronizeStep.tsx": {
|
||||
"react/no-unescaped-entities": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"public/app/features/query/components/QueryEditorRow.tsx": {
|
||||
"@grafana/no-aria-label-selectors": {
|
||||
"count": 1
|
||||
|
||||
@@ -358,7 +358,13 @@ export function ProvisioningWizard({ type }: { type: RepoType }) {
|
||||
<div className={styles.content}>
|
||||
{activeStep === 'connection' && <ConnectStep />}
|
||||
{activeStep === 'bootstrap' && <BootstrapStep settingsData={data} repoName={repoName} />}
|
||||
{activeStep === 'synchronize' && <SynchronizeStep isLegacyStorage={isLegacyStorage} />}
|
||||
{activeStep === 'synchronize' && (
|
||||
<SynchronizeStep
|
||||
isLegacyStorage={isLegacyStorage}
|
||||
onCancel={handleRepositoryDeletion}
|
||||
isCancelling={isCancelling}
|
||||
/>
|
||||
)}
|
||||
{activeStep === 'finish' && <FinishStep />}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useState } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { Button, Text, Stack, Alert, TextLink, Field, Checkbox } from '@grafana/ui';
|
||||
import { Job } from 'app/api/clients/provisioning/v0alpha1';
|
||||
import { Alert, Button, Checkbox, Field, Spinner, Stack, Text, TextLink } from '@grafana/ui';
|
||||
import { Job, useGetRepositoryStatusQuery } from 'app/api/clients/provisioning/v0alpha1';
|
||||
|
||||
import { JobStatus } from '../Job/JobStatus';
|
||||
import { ProvisioningAlert } from '../Shared/ProvisioningAlert';
|
||||
|
||||
import { useStepStatus } from './StepStatusContext';
|
||||
import { useCreateSyncJob } from './hooks/useCreateSyncJob';
|
||||
@@ -14,9 +16,11 @@ import { WizardFormData } from './types';
|
||||
|
||||
export interface SynchronizeStepProps {
|
||||
isLegacyStorage?: boolean;
|
||||
onCancel?: (repoName: string) => void;
|
||||
isCancelling?: boolean;
|
||||
}
|
||||
|
||||
export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) {
|
||||
export function SynchronizeStep({ isLegacyStorage, onCancel, isCancelling }: SynchronizeStepProps) {
|
||||
const { getValues, register, watch } = useFormContext<WizardFormData>();
|
||||
const { setStepStatusInfo } = useStepStatus();
|
||||
const [repoName = '', repoType] = watch(['repositoryName', 'repository.type']);
|
||||
@@ -29,6 +33,14 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) {
|
||||
setStepStatusInfo,
|
||||
});
|
||||
const [job, setJob] = useState<Job>();
|
||||
const repositoryStatusQuery = useGetRepositoryStatusQuery(repoName ? { name: repoName } : skipToken);
|
||||
|
||||
const {
|
||||
healthy: isRepositoryHealthy,
|
||||
message: repositoryHealthMessages,
|
||||
checked,
|
||||
} = repositoryStatusQuery?.data?.status?.health || {};
|
||||
const isButtonDisabled = checked !== undefined && isRepositoryHealthy === false;
|
||||
|
||||
const startSynchronization = async () => {
|
||||
const [history] = getValues(['migrate.history']);
|
||||
@@ -38,53 +50,69 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) {
|
||||
}
|
||||
};
|
||||
|
||||
if (repositoryStatusQuery.isFetching) {
|
||||
return <Spinner />;
|
||||
}
|
||||
if (job) {
|
||||
return <JobStatus watch={job} onStatusChange={setStepStatusInfo} jobType="sync" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack direction="column" gap={3} alignItems="flex-start">
|
||||
<Stack direction="column" gap={3}>
|
||||
<Text color="secondary">
|
||||
<Trans i18nKey="provisioning.wizard.sync-description">
|
||||
Sync resources with external storage. After this one-time step, all future updates will be automatically saved
|
||||
to the repository and provisioned back into the instance.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Alert
|
||||
title={t(
|
||||
'provisioning.wizard.alert-title',
|
||||
'Important: No data or configuration will be lost, but dashboards will be temporarily unavailable for a few minutes.'
|
||||
)}
|
||||
severity={'info'}
|
||||
>
|
||||
<ul style={{ marginLeft: '16px' }}>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-1">
|
||||
Resources won't be able to be created, edited, or deleted during this process. In the last step, they will
|
||||
disappear.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-2">
|
||||
Once provisioning is complete, resources will reappear and be managed through external storage.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-3">
|
||||
The duration of this process depends on the number of resources involved.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-4">
|
||||
Enterprise instance administrators can display an announcement banner to users. See{' '}
|
||||
<TextLink external href="https://grafana.com/docs/grafana/latest/administration/announcement-banner/">
|
||||
this guide
|
||||
</TextLink>{' '}
|
||||
for step-by-step instructions.
|
||||
</Trans>
|
||||
</li>
|
||||
</ul>
|
||||
</Alert>
|
||||
{repositoryHealthMessages && !isRepositoryHealthy && (
|
||||
<ProvisioningAlert
|
||||
error={{
|
||||
title: t(
|
||||
'provisioning.synchronize-step.repository-unhealthy',
|
||||
'The repository cannot be synchronized. Cancel provisioning and try again once the issue has been resolved. See details below.'
|
||||
),
|
||||
message: repositoryHealthMessages,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isRepositoryHealthy && (
|
||||
<Alert
|
||||
title={t(
|
||||
'provisioning.wizard.alert-title',
|
||||
'Important: No data or configuration will be lost, but dashboards will be temporarily unavailable for a few minutes.'
|
||||
)}
|
||||
severity={'info'}
|
||||
>
|
||||
<ul style={{ marginLeft: '16px' }}>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-1">
|
||||
Resources won't be able to be created, edited, or deleted during this process. In the last step,
|
||||
they will disappear.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-2">
|
||||
Once provisioning is complete, resources will reappear and be managed through external storage.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-3">
|
||||
The duration of this process depends on the number of resources involved.
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<Trans i18nKey="provisioning.wizard.alert-point-4">
|
||||
Enterprise instance administrators can display an announcement banner to users. See{' '}
|
||||
<TextLink external href="https://grafana.com/docs/grafana/latest/administration/announcement-banner/">
|
||||
this guide
|
||||
</TextLink>{' '}
|
||||
for step-by-step instructions.
|
||||
</Trans>
|
||||
</li>
|
||||
</ul>
|
||||
</Alert>
|
||||
)}
|
||||
{supportsHistory && (
|
||||
<>
|
||||
<Text element="h3">
|
||||
@@ -105,9 +133,21 @@ export function SynchronizeStep({ isLegacyStorage }: SynchronizeStepProps) {
|
||||
</>
|
||||
)}
|
||||
|
||||
<Button variant="primary" onClick={startSynchronization}>
|
||||
<Trans i18nKey="provisioning.wizard.button-start">Begin synchronization</Trans>
|
||||
</Button>
|
||||
<Field noMargin>
|
||||
{isRepositoryHealthy === false ? (
|
||||
<Button variant="destructive" onClick={() => onCancel?.(repoName)} disabled={isCancelling}>
|
||||
{isCancelling ? (
|
||||
<Trans i18nKey="provisioning.wizard.button-cancelling">Cancelling...</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="provisioning.wizard.button-cancel">Cancel</Trans>
|
||||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="primary" onClick={startSynchronization} disabled={isButtonDisabled}>
|
||||
<Trans i18nKey="provisioning.wizard.button-start">Begin synchronization</Trans>
|
||||
</Button>
|
||||
)}
|
||||
</Field>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11655,6 +11655,7 @@
|
||||
"tooltip-unhealthy-repository": "Unable to pull an unhealthy repository"
|
||||
},
|
||||
"synchronize-step": {
|
||||
"repository-unhealthy": "The repository cannot be synchronized. Cancel provisioning and try again once the issue has been resolved. See details below.",
|
||||
"synchronization-description": "Include commits for each historical value",
|
||||
"synchronization-options": "Synchronization options"
|
||||
},
|
||||
@@ -11678,6 +11679,8 @@
|
||||
"alert-point-3": "The duration of this process depends on the number of resources involved.",
|
||||
"alert-point-4": "Enterprise instance administrators can display an announcement banner to users. See <2>this guide</2> for step-by-step instructions.",
|
||||
"alert-title": "Important: No data or configuration will be lost, but dashboards will be temporarily unavailable for a few minutes.",
|
||||
"button-cancel": "Cancel",
|
||||
"button-cancelling": "Cancelling...",
|
||||
"button-next": "Finish",
|
||||
"button-start": "Begin synchronization",
|
||||
"discard-modal": {
|
||||
|
||||
Reference in New Issue
Block a user