Skip to content

Commit

Permalink
Bug 1803780: Validate disk buses on created VMs
Browse files Browse the repository at this point in the history
Validate disk bus type for created VMs storage disks
using validations written in the template
the VMs were created from.

Signed-off-by: Ido Rosenzwig <irosenzw@redhat.com>
  • Loading branch information
irosenzw committed Mar 3, 2020
1 parent d81d1cf commit 0dfd432
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { DataVolumeWrapper } from '../../../k8s/wrapper/vm/data-volume-wrapper';
import { getUpdateDiskPatches } from '../../../k8s/patches/vm/vm-disk-patches';
import { CombinedDiskFactory } from '../../../k8s/wrapper/vm/combined-disk';
import { DiskModal } from './disk-modal';
import { TemplateValidations } from '../../../utils/validations/template/template-validations';

const DiskModalFirehoseComponent: React.FC<DiskModalFirehoseComponentProps> = (props) => {
const { disk, volume, dataVolume, vmLikeEntity, vmLikeEntityLoading, ...restProps } = props;
Expand Down Expand Up @@ -76,6 +77,7 @@ type DiskModalFirehoseComponentProps = ModalComponentProps & {
persistentVolumeClaims?: FirehoseResult<VMLikeEntityKind[]>;
vmLikeEntityLoading?: FirehoseResult<VMLikeEntityKind>;
vmLikeEntity: VMLikeEntityKind;
templateValidations?: TemplateValidations;
};

const DiskModalFirehose: React.FC<DiskModalFirehoseProps> = (props) => {
Expand Down Expand Up @@ -130,6 +132,7 @@ type DiskModalFirehoseProps = ModalComponentProps & {
dataVolume?: any;
isEditing?: boolean;
useProjects: boolean;
templateValidations?: TemplateValidations;
};

const diskModalStateToProps = ({ k8s }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import {
VMStorageRowActionOpts,
VMStorageRowCustomData,
} from './types';
import { validateDisk } from '../../utils/validations/vm/disk';

const menuActionEdit = (
disk: CombinedDisk,
vmLikeEntity: VMLikeEntityKind,
{ withProgress }: VMNicRowActionOpts,
{ withProgress, templateValidations }: VMStorageRowActionOpts,
): KebabOption => ({
label: 'Edit',
callback: () =>
Expand All @@ -39,6 +40,7 @@ const menuActionEdit = (
disk: disk.diskWrapper.asResource(),
volume: disk.volumeWrapper.asResource(),
dataVolume: disk.dataVolumeWrapper && disk.dataVolumeWrapper.asResource(),
templateValidations,
}).result,
),
accessReview: asAccessReview(
Expand Down Expand Up @@ -148,20 +150,39 @@ export type VMDiskRowProps = {

export const DiskRow: React.FC<VMDiskRowProps> = ({
obj: { disk, ...restData },
customData: { isDisabled, withProgress, vmLikeEntity, columnClasses },
customData: { isDisabled, withProgress, vmLikeEntity, columnClasses, templateValidations },
index,
style,
}) => {
const diskValidations = validateDisk(
disk.diskWrapper,
disk.volumeWrapper,
disk.dataVolumeWrapper,
disk.persistentVolumeClaimWrapper,
{ templateValidations },
);
return (
<DiskSimpleRow
data={restData}
validation={
diskValidations && {
name: diskValidations.validations.name,
size: diskValidations.validations.size,
diskInterface: diskValidations.validations.diskInterface,
source:
diskValidations.validations.url ||
diskValidations.validations.container ||
diskValidations.validations.pvc,
}
}
columnClasses={columnClasses}
index={index}
style={style}
actionsComponent={
<Kebab
options={getActions(disk, vmLikeEntity, {
withProgress,
templateValidations,
})}
isDisabled={
isDisabled ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ValidationObject } from '@console/shared';
import { VMLikeEntityKind } from '../../types/vmLike';
import { CombinedDisk } from '../../k8s/wrapper/vm/combined-disk';
import { UIDiskValidation } from '../../utils/validations/vm/types';
import { TemplateValidations } from '../../utils/validations/template/template-validations';

export type StorageSimpleData = {
name?: string;
Expand All @@ -22,10 +24,13 @@ export type StorageSimpleDataValidation = {

export type StorageBundle = StorageSimpleData & {
disk: CombinedDisk;
templateValidations?: TemplateValidations;
diskValidations?: UIDiskValidation;
};

export type VMStorageRowActionOpts = {
withProgress: (promise: Promise<any>) => void;
templateValidations?: TemplateValidations;
};

export type VMStorageRowCustomData = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import * as React from 'react';
import { Button, ButtonVariant } from '@patternfly/react-core';
import { Table } from '@console/internal/components/factory';
import { PersistentVolumeClaimModel } from '@console/internal/models';
import { PersistentVolumeClaimModel, TemplateModel } from '@console/internal/models';
import { Firehose, FirehoseResult, EmptyBox } from '@console/internal/components/utils';
import { useSafetyFirst } from '@console/internal/components/safety-first';
import { K8sResourceKind } from '@console/internal/module/k8s';
import { K8sResourceKind, TemplateKind } from '@console/internal/module/k8s';
import { dimensifyHeader, getNamespace } from '@console/shared';
import { sortable } from '@patternfly/react-table';
import { DataVolumeModel } from '../../models';
import { VMGenericLikeEntityKind } from '../../types/vmLike';
import { VMLikeEntityTabProps } from '../vms/types';
import { getResource } from '../../utils';
import { getResource, getLoadedData } from '../../utils';
import { wrapWithProgress } from '../../utils/utils';
import { diskModalEnhanced } from '../modals/disk-modal/disk-modal-enhanced';
import { CombinedDiskFactory } from '../../k8s/wrapper/vm/combined-disk';
Expand All @@ -21,6 +21,10 @@ import { DiskRow } from './disk-row';
import { diskTableColumnClasses } from './utils';
import { isVMI } from '../../selectors/vm';
import { ADD_DISK } from '../../utils/strings';
import {
getVMTemplateNamespacedName,
getTemplateValidationsFromTemplate,
} from '../../selectors/vm-template/selectors';

const getStoragesData = ({
vmLikeEntity,
Expand Down Expand Up @@ -118,11 +122,19 @@ type VMDisksProps = {
vmLikeEntity?: VMGenericLikeEntityKind;
pvcs?: FirehoseResult<K8sResourceKind[]>;
datavolumes?: FirehoseResult<V1alpha1DataVolume[]>;
vmTemplate?: FirehoseResult<TemplateKind>;
};

export const VMDisks: React.FC<VMDisksProps> = ({ vmLikeEntity, pvcs, datavolumes }) => {
export const VMDisks: React.FC<VMDisksProps> = ({
vmLikeEntity,
pvcs,
datavolumes,
vmTemplate,
}) => {
const [isLocked, setIsLocked] = useSafetyFirst(false);
const withProgress = wrapWithProgress(setIsLocked);
const templateValidations = getTemplateValidationsFromTemplate(getLoadedData(vmTemplate));

return (
<div className="co-m-list">
{!isVMI(vmLikeEntity) && (
Expand All @@ -136,6 +148,7 @@ export const VMDisks: React.FC<VMDisksProps> = ({ vmLikeEntity, pvcs, datavolume
diskModalEnhanced({
blocking: true,
vmLikeEntity,
templateValidations,
}).result,
)
}
Expand All @@ -153,6 +166,7 @@ export const VMDisks: React.FC<VMDisksProps> = ({ vmLikeEntity, pvcs, datavolume
vmLikeEntity,
withProgress,
isDisabled: isLocked,
templateValidations,
}}
row={DiskRow}
columnClasses={diskTableColumnClasses}
Expand All @@ -164,6 +178,7 @@ export const VMDisks: React.FC<VMDisksProps> = ({ vmLikeEntity, pvcs, datavolume

export const VMDisksFirehose: React.FC<VMLikeEntityTabProps> = ({ obj: vmLikeEntity }) => {
const namespace = getNamespace(vmLikeEntity);
const vmTemplate = getVMTemplateNamespacedName(vmLikeEntity);

const resources = [
getResource(PersistentVolumeClaimModel, {
Expand All @@ -174,6 +189,12 @@ export const VMDisksFirehose: React.FC<VMLikeEntityTabProps> = ({ obj: vmLikeEnt
namespace,
prop: 'datavolumes',
}),
getResource(TemplateModel, {
name: vmTemplate?.name,
namespace: vmTemplate?.namespace,
isList: false,
prop: 'vmTemplate',
}),
];

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { VMGenericLikeEntityKind } from '../../types/vmLike';
import { getLabel, getName, getNamespace } from '@console/shared/src';
import { LABEL_USED_TEMPLATE_NAME, LABEL_USED_TEMPLATE_NAMESPACE } from '../../constants/vm';
import { TemplateKind } from '@console/internal/module/k8s';
import { TemplateValidations } from '../../utils/validations/template/template-validations';

export const getVMTemplateNamespacedName = (
vm: VMGenericLikeEntityKind,
Expand All @@ -24,3 +25,19 @@ export const getVMTemplate = (
)
: undefined;
};

export const getTemplateValidationsFromTemplate = (
vmTemplate: TemplateKind,
): TemplateValidations => {
const result = vmTemplate?.metadata?.annotations?.validations;

if (!result) {
return new TemplateValidations();
}

try {
return new TemplateValidations(JSON.parse(result));
} catch (e) {
return new TemplateValidations();
}
};

0 comments on commit 0dfd432

Please sign in to comment.