Provisioning: Allow viewers to view /status subresource and wait on the frontend before sync (#111576)
This commit is contained in:
@@ -355,7 +355,11 @@ func (b *APIBuilder) GetAuthorizer() authorizer.Authorizer {
|
|||||||
} else {
|
} else {
|
||||||
return authorizer.DecisionDeny, "editor role is required", nil
|
return authorizer.DecisionDeny, "editor role is required", nil
|
||||||
}
|
}
|
||||||
|
case "status":
|
||||||
|
if id.GetOrgRole().Includes(identity.RoleViewer) && a.GetVerb() == apiutils.VerbGet {
|
||||||
|
return authorizer.DecisionAllow, "", nil
|
||||||
|
}
|
||||||
|
return authorizer.DecisionDeny, "users cannot update the status of a repository", nil
|
||||||
default:
|
default:
|
||||||
if id.GetIsGrafanaAdmin() {
|
if id.GetIsGrafanaAdmin() {
|
||||||
return authorizer.DecisionAllow, "", nil
|
return authorizer.DecisionAllow, "", nil
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
useCreateRepositoryJobsMutation,
|
useCreateRepositoryJobsMutation,
|
||||||
useGetFrontendSettingsQuery,
|
useGetFrontendSettingsQuery,
|
||||||
useGetRepositoryFilesQuery,
|
useGetRepositoryFilesQuery,
|
||||||
|
useGetRepositoryStatusQuery,
|
||||||
useGetResourceStatsQuery,
|
useGetResourceStatsQuery,
|
||||||
} from 'app/api/clients/provisioning/v0alpha1';
|
} from 'app/api/clients/provisioning/v0alpha1';
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ jest.mock('app/api/clients/provisioning/v0alpha1', () => ({
|
|||||||
...jest.requireActual('app/api/clients/provisioning/v0alpha1'),
|
...jest.requireActual('app/api/clients/provisioning/v0alpha1'),
|
||||||
useGetFrontendSettingsQuery: jest.fn(),
|
useGetFrontendSettingsQuery: jest.fn(),
|
||||||
useGetRepositoryFilesQuery: jest.fn(),
|
useGetRepositoryFilesQuery: jest.fn(),
|
||||||
|
useGetRepositoryStatusQuery: jest.fn(),
|
||||||
useGetResourceStatsQuery: jest.fn(),
|
useGetResourceStatsQuery: jest.fn(),
|
||||||
useCreateRepositoryJobsMutation: jest.fn(),
|
useCreateRepositoryJobsMutation: jest.fn(),
|
||||||
}));
|
}));
|
||||||
@@ -43,6 +45,9 @@ const mockUseGetFrontendSettingsQuery = useGetFrontendSettingsQuery as jest.Mock
|
|||||||
const mockUseGetRepositoryFilesQuery = useGetRepositoryFilesQuery as jest.MockedFunction<
|
const mockUseGetRepositoryFilesQuery = useGetRepositoryFilesQuery as jest.MockedFunction<
|
||||||
typeof useGetRepositoryFilesQuery
|
typeof useGetRepositoryFilesQuery
|
||||||
>;
|
>;
|
||||||
|
const mockUseGetRepositoryStatusQuery = useGetRepositoryStatusQuery as jest.MockedFunction<
|
||||||
|
typeof useGetRepositoryStatusQuery
|
||||||
|
>;
|
||||||
const mockUseGetResourceStatsQuery = useGetResourceStatsQuery as jest.MockedFunction<typeof useGetResourceStatsQuery>;
|
const mockUseGetResourceStatsQuery = useGetResourceStatsQuery as jest.MockedFunction<typeof useGetResourceStatsQuery>;
|
||||||
const mockUseCreateRepositoryJobsMutation = useCreateRepositoryJobsMutation as jest.MockedFunction<
|
const mockUseCreateRepositoryJobsMutation = useCreateRepositoryJobsMutation as jest.MockedFunction<
|
||||||
typeof useCreateRepositoryJobsMutation
|
typeof useCreateRepositoryJobsMutation
|
||||||
@@ -131,6 +136,23 @@ describe('ProvisioningWizard', () => {
|
|||||||
refetch: jest.fn(),
|
refetch: jest.fn(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mockUseGetRepositoryStatusQuery.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
status: {
|
||||||
|
health: {
|
||||||
|
healthy: true,
|
||||||
|
checked: true,
|
||||||
|
message: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isLoading: false,
|
||||||
|
isFetching: false,
|
||||||
|
isError: false,
|
||||||
|
error: null,
|
||||||
|
refetch: jest.fn(),
|
||||||
|
});
|
||||||
|
|
||||||
mockUseGetResourceStatsQuery.mockReturnValue({
|
mockUseGetResourceStatsQuery.mockReturnValue({
|
||||||
data: {
|
data: {
|
||||||
instance: [],
|
instance: [],
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ export function SynchronizeStep({ isLegacyStorage, onCancel, isCancelling }: Syn
|
|||||||
message: repositoryHealthMessages,
|
message: repositoryHealthMessages,
|
||||||
checked,
|
checked,
|
||||||
} = repositoryStatusQuery?.data?.status?.health || {};
|
} = repositoryStatusQuery?.data?.status?.health || {};
|
||||||
const isButtonDisabled = checked !== undefined && isRepositoryHealthy === false;
|
|
||||||
|
const hasError = repositoryStatusQuery.isError;
|
||||||
|
const isButtonDisabled = hasError || (checked !== undefined && isRepositoryHealthy === false);
|
||||||
|
|
||||||
const startSynchronization = async () => {
|
const startSynchronization = async () => {
|
||||||
const [history] = getValues(['migrate.history']);
|
const [history] = getValues(['migrate.history']);
|
||||||
@@ -65,7 +67,18 @@ export function SynchronizeStep({ isLegacyStorage, onCancel, isCancelling }: Syn
|
|||||||
to the repository and provisioned back into the instance.
|
to the repository and provisioned back into the instance.
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
{repositoryHealthMessages && !isRepositoryHealthy && (
|
{hasError && (
|
||||||
|
<ProvisioningAlert
|
||||||
|
error={{
|
||||||
|
title: t('provisioning.synchronize-step.repository-error', 'Repository error'),
|
||||||
|
message: t(
|
||||||
|
'provisioning.synchronize-step.repository-error-message',
|
||||||
|
'Unable to check repository status. Please verify the repository configuration and try again.'
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{repositoryHealthMessages && !isRepositoryHealthy && !hasError && (
|
||||||
<ProvisioningAlert
|
<ProvisioningAlert
|
||||||
error={{
|
error={{
|
||||||
title: t(
|
title: t(
|
||||||
@@ -134,7 +147,7 @@ export function SynchronizeStep({ isLegacyStorage, onCancel, isCancelling }: Syn
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Field noMargin>
|
<Field noMargin>
|
||||||
{isRepositoryHealthy === false ? (
|
{hasError || isRepositoryHealthy === false ? (
|
||||||
<Button variant="destructive" onClick={() => onCancel?.(repoName)} disabled={isCancelling}>
|
<Button variant="destructive" onClick={() => onCancel?.(repoName)} disabled={isCancelling}>
|
||||||
{isCancelling ? (
|
{isCancelling ? (
|
||||||
<Trans i18nKey="provisioning.wizard.button-cancelling">Cancelling...</Trans>
|
<Trans i18nKey="provisioning.wizard.button-cancelling">Cancelling...</Trans>
|
||||||
|
|||||||
@@ -11674,6 +11674,8 @@
|
|||||||
"tooltip-unhealthy-repository": "Unable to pull an unhealthy repository"
|
"tooltip-unhealthy-repository": "Unable to pull an unhealthy repository"
|
||||||
},
|
},
|
||||||
"synchronize-step": {
|
"synchronize-step": {
|
||||||
|
"repository-error": "Repository error",
|
||||||
|
"repository-error-message": "Unable to check repository status. Please verify the repository configuration and try again.",
|
||||||
"repository-unhealthy": "The repository cannot be synchronized. Cancel provisioning and try again once the issue has been resolved. See details below.",
|
"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-description": "Include commits for each historical value",
|
||||||
"synchronization-options": "Synchronization options"
|
"synchronization-options": "Synchronization options"
|
||||||
|
|||||||
Reference in New Issue
Block a user