Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1889213: The error message of uploading failure is not clear enough #7567

Merged
merged 1 commit into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,30 @@ import {
Alert,
AlertVariant,
Spinner,
Checkbox,
Split,
SplitItem,
} from '@patternfly/react-core';
import { ErrorCircleOIcon, InProgressIcon } from '@patternfly/react-icons';
import { history, resourcePath } from '@console/internal/components/utils';
import { getName, getNamespace } from '@console/shared';
import { PodModel } from '@console/internal/models';
import { DataUpload } from '../cdi-upload-provider';
import { getProgressVariant } from '../upload-pvc-popover';
import { killUploadPVC } from '../../../k8s/requests/cdi-upload/cdi-upload-requests';
import { V1alpha1DataVolume } from '../../../types/vm/disk/V1alpha1DataVolume';
import { UPLOAD_STATUS } from '../consts';

export enum uploadErrorType {
MISSING = 'missing',
ALLOCATE = 'allocate',
CERT = 'cert',
CDI_INIT = 'cdi_init',
}

export const UploadPVCFormStatus: React.FC<UploadPVCFormStatusProps> = ({
upload,
dataVolume,
isSubmitting,
isAllocating,
allocateError,
Expand Down Expand Up @@ -53,6 +68,7 @@ export const UploadPVCFormStatus: React.FC<UploadPVCFormStatusProps> = ({
<EmptyState>
<DataUploadStatus
upload={upload}
dataVolume={dataVolume}
error={error}
isAllocating={isAllocating}
onErrorClick={onErrorClick}
Expand All @@ -66,13 +82,23 @@ export const UploadPVCFormStatus: React.FC<UploadPVCFormStatusProps> = ({

const DataUploadStatus: React.FC<DataUploadStatus> = ({
upload,
dataVolume,
error,
onErrorClick,
isAllocating,
onSuccessClick,
onCancelClick,
}) => {
if (error) return <ErrorStatus error={error} onErrorClick={onErrorClick} />;
if (error)
return error === uploadErrorType.CDI_INIT ? (
<CDIInitErrorStatus
onErrorClick={onErrorClick}
pvcName={getName(dataVolume)}
namespace={getNamespace(dataVolume)}
/>
) : (
<ErrorStatus error={error} onErrorClick={onErrorClick} />
);
if (isAllocating) return <AllocatingStatus />;
if (upload?.uploadStatus === UPLOAD_STATUS.CANCELED) return <CancellingStatus />;
return (
Expand Down Expand Up @@ -120,6 +146,69 @@ const ErrorStatus: React.FC<ErrorStatusProps> = ({ error, onErrorClick }) => (
</>
);

const CDIInitErrorStatus: React.FC<CDIInitErrorStatus> = ({ onErrorClick, pvcName, namespace }) => {
const [shouldKillDv, setShouldKillDv] = React.useState(true);
return (
<>
<EmptyStateIcon icon={ErrorCircleOIcon} color="#cf1010" />
<Title headingLevel="h4" size="lg">
CDI Error: Could not initiate Data Volume
</Title>
<EmptyStateBody>
<Stack hasGutter>
<StackItem>
Data Volume failed to initiate upload, you can either delete the Data Volume and try
again, or check logs
</StackItem>
<StackItem>
<Split>
<SplitItem isFilled />
<Checkbox
id="approve-checkbox"
isChecked={shouldKillDv}
aria-label="kill datavolume checkbox"
label={`Delete Data Volume: ${pvcName}`}
onChange={(v) => setShouldKillDv(v)}
/>
<SplitItem isFilled />
</Split>
</StackItem>
</Stack>
</EmptyStateBody>
<Button
id="cdi-upload-error-btn"
variant="primary"
onClick={
shouldKillDv
? () => {
killUploadPVC(pvcName, namespace)
.then(() => {
onErrorClick();
})
.catch(() => {
onErrorClick();
});
}
: onErrorClick
}
>
Back to Form {shouldKillDv && '(Deletes DV)'}
</Button>
<EmptyStateSecondaryActions>
<Button
id="cdi-upload-check-logs"
onClick={() =>
history.push(`${resourcePath(PodModel.kind, `cdi-upload-${pvcName}`, namespace)}/logs`)
}
variant="link"
>
Check Logs
</Button>
</EmptyStateSecondaryActions>
</>
);
};

const UploadingStatus: React.FC<UploadingStatusProps> = ({
upload,
onSuccessClick,
Expand Down Expand Up @@ -170,14 +259,15 @@ const UploadingStatus: React.FC<UploadingStatusProps> = ({

type UploadingStatusProps = {
upload: DataUpload;
dataVolume?: V1alpha1DataVolume;
onSuccessClick?: () => void;
onCancelClick?: () => void;
};

export type UploadPVCFormStatusProps = UploadingStatusProps & {
isSubmitting: boolean;
isAllocating: boolean;
allocateError: React.ReactNode;
allocateError: any;
onErrorClick: () => void;
};

Expand All @@ -186,6 +276,12 @@ type ErrorStatusProps = {
onErrorClick: () => void;
};

type CDIInitErrorStatus = {
onErrorClick: () => void;
pvcName: string;
namespace: string;
};

export type DataUploadStatus = UploadingStatusProps &
ErrorStatusProps & {
isAllocating: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,12 @@ import {
} from '@console/internal/components/utils/k8s-watch-hook';
import { useBaseImages } from '../../../hooks/use-base-images';
import { DataVolumeModel } from '../../../models';
import { createUploadPVC } from '../../../k8s/requests/cdi-upload/cdi-upload-requests';
import {
createUploadPVC,
PVCInitError,
} from '../../../k8s/requests/cdi-upload/cdi-upload-requests';
import { CDIUploadContext } from '../cdi-upload-provider';
import { UploadPVCFormStatus } from './upload-pvc-form-status';
import { UploadPVCFormStatus, uploadErrorType } from './upload-pvc-form-status';
import { PersistentVolumeClaimModel, TemplateModel } from '@console/internal/models';
import { getName, getNamespace } from '@console/shared';
import { V1alpha1DataVolume } from '../../../types/vm/disk/V1alpha1DataVolume';
Expand Down Expand Up @@ -80,12 +83,6 @@ const templatesResource: WatchK8sResource = {
},
};

export enum uploadErrorType {
MISSING = 'missing',
ALLOCATE = 'allocate',
CERT = 'cert',
}

export const uploadErrorMessage = (t: TFunction) => ({
[uploadErrorType.MISSING]: t('kubevirt-plugin~File input is missing'),
[uploadErrorType.ALLOCATE]: t('kubevirt-plugin~Could not create persistent volume claim'),
Expand Down Expand Up @@ -521,7 +518,7 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
setError('');
setIsAllocating(true);
setIsSubmitting(true);
return createUploadPVC(dvObj, t);
return createUploadPVC(dvObj);
})
.then(({ token }) => {
setIsAllocating(false);
Expand All @@ -532,9 +529,11 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
namespace,
});
})
.catch(({ message }: { message: string }) => {
.catch((err) => {
setIsAllocating(false);
setError(message || uploadErrorType.ALLOCATE);
err instanceof PVCInitError
? setError(uploadErrorType.CDI_INIT)
: setError(err?.message || uploadErrorType.ALLOCATE);
});
}
};
Expand Down Expand Up @@ -626,9 +625,10 @@ export const UploadPVCPage: React.FC<UploadPVCPageProps> = (props) => {
upload={uploads.find(
(upl) => upl.pvcName === getName(dvObj) && upl.namespace === namespace,
)}
dataVolume={dvObj}
isSubmitting={isSubmitting}
isAllocating={isAllocating}
allocateError={errorMessage}
allocateError={error}
onErrorClick={() => {
setIsSubmitting(false);
setError('');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { Alert, Button, ActionGroup, Stack, StackItem } from '@patternfly/react-
import { useAccessReview2, LoadingBox } from '@console/internal/components/utils';
import { coFetch } from '@console/internal/co-fetch';

import { UploadPVCFormStatus } from '../../cdi-upload-provider/upload-pvc-form/upload-pvc-form-status';
import {
UploadPVCFormStatus,
uploadErrorType,
} from '../../cdi-upload-provider/upload-pvc-form/upload-pvc-form-status';
import { createUploadPVC } from '../../../k8s/requests/cdi-upload/cdi-upload-requests';
import {
TEMPLATE_BASE_IMAGE_NAME_PARAMETER,
Expand All @@ -28,10 +31,7 @@ import { getRootDataVolume } from '../../../k8s/requests/vm/create/simple-create
import { ProvisionSource } from '../../../constants/vm/provision-source';
import { useErrorTranslation } from '../../../hooks/use-error-translation';
import { CDI_UPLOAD_URL_BUILDER } from '../../cdi-upload-provider/consts';
import {
uploadErrorMessage,
uploadErrorType,
} from '../../cdi-upload-provider/upload-pvc-form/upload-pvc-form';
import { uploadErrorMessage } from '../../cdi-upload-provider/upload-pvc-form/upload-pvc-form';

const getAction = (t: TFunction, dataSource: string): string => {
switch (ProvisionSource.fromString(dataSource)) {
Expand Down Expand Up @@ -147,7 +147,7 @@ export const AddTemplateSourceModal: React.FC<ModalComponentProps &
try {
setAllocating(true);
setSubmitting(true);
const { token } = await createUploadPVC(dvObj, t);
const { token } = await createUploadPVC(dvObj);
setAllocating(false);
uploadData({
file: file.value?.value,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable camelcase, @typescript-eslint/camelcase,no-await-in-loop */
import { TFunction } from 'i18next';
import { getName, getNamespace } from '@console/shared';
import { DataVolumeModel, UploadTokenRequestModel } from '@console/kubevirt-plugin/src/models';
import { V1alpha1DataVolume } from '@console/kubevirt-plugin/src/types/vm/disk/V1alpha1DataVolume';
Expand All @@ -18,7 +17,7 @@ const UPLOAD_STATES = {
READY: 'UploadReady',
};

class PVCInitError extends Error {
export class PVCInitError extends Error {
constructor() {
// t('kubevirt-plugin~Data Volume failed to initiate upload, and has been deleted.')
super('kubevirt-plugin~Data Volume failed to initiate upload, and has been deleted.');
Expand Down Expand Up @@ -65,7 +64,7 @@ const createUploadToken = async (pvcName: string, namespace: string): Promise<st
}
};

export const createUploadPVC = async (dataVolume: V1alpha1DataVolume, t: TFunction) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice !

export const createUploadPVC = async (dataVolume: V1alpha1DataVolume) => {
const dataVolumeName = getName(dataVolume);
const namespace = getNamespace(dataVolume);

Expand All @@ -77,8 +76,7 @@ export const createUploadPVC = async (dataVolume: V1alpha1DataVolume, t: TFuncti
return { token };
} catch (error) {
if (error instanceof PVCInitError) {
await killUploadPVC(dataVolumeName, namespace);
throw new Error(t(error.message));
throw new PVCInitError();
}
throw new Error(error.message);
}
Expand Down