Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Commit

Permalink
validate template sources with missing DataVolume
Browse files Browse the repository at this point in the history
  • Loading branch information
suomiy committed Jul 25, 2019
1 parent f95bd97 commit 8ae94b0
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 11 deletions.
14 changes: 8 additions & 6 deletions src/components/TemplateSource/TemplateSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ import { PROVISION_SOURCE_URL } from '../../constants';
import { getId } from '../../selectors';
import { prefixedId } from '../../utils/utils';

const Type = ({ type, source, id, isInline }) => (
<div id={id} title={source} className={isInline ? 'kubevirt-template-source__overlay' : ''}>
const Type = ({ type, source, error, id, isInline }) => (
<div id={id} title={source || error} className={isInline ? 'kubevirt-template-source__overlay' : ''}>
{type}
</div>
);

Type.propTypes = {
type: PropTypes.string.isRequired,
error: PropTypes.string,
source: PropTypes.string,
id: PropTypes.string,
isInline: PropTypes.bool,
};

Type.defaultProps = {
error: undefined,
source: undefined,
id: undefined,
isInline: false,
Expand Down Expand Up @@ -54,22 +56,22 @@ Source.defaultProps = {
export const TemplateSource = ({ template, dataVolumes, detailed }) => {
const provisionSource = getTemplateProvisionSource(template, dataVolumes);

if (!provisionSource) {
if (!provisionSource || !provisionSource.type) {
return '---';
}

const { type, source } = provisionSource;
const { type, source, error } = provisionSource;
const id = getId(template);
const typeId = prefixedId(id, 'type');
const sourceId = prefixedId(id, 'source');

if (!detailed) {
return <Type id={typeId} type={type} source={source} isInline />;
return <Type id={typeId} type={type} source={source} error={error} isInline />;
}

return (
<React.Fragment>
<Type id={typeId} type={type} source={source} />
<Type id={typeId} type={type} source={source} error={error} />
<Source id={sourceId} type={type} source={source} />
</React.Fragment>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/Wizard/CreateVmWizard/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ export const DATA_VOLUME_SOURCE_PVC = 'datavolume-pvc';
export const VIRTUAL_MACHINES_KEY = 'virtualMachines';
export const CREATE_TEMPLATE_KEY = 'createTemplate';
export const TEMPLATES_KEY = 'templates';
export const DATAVOLUMES_KEY = 'dataVolumes';
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
PROVISION_SOURCE_IMPORT,
PROVISION_SOURCE_URL,
TEMPLATE_TYPE_VM,
VALIDATION_ERROR_TYPE,
} from '../../../../constants';
import {
selectVm,
Expand Down Expand Up @@ -340,8 +341,10 @@ export const selectedUserTemplateUpdateCreator = (prevProps, prevState, props, s

// update provision source
const provisionSource = getTemplateProvisionSource(userTemplate, dataVolumes);
if (provisionSource) {
update[PROVISION_SOURCE_TYPE_KEY] = asValueObject(provisionSource.type);
update[PROVISION_SOURCE_TYPE_KEY] = asValueObject(
provisionSource && !provisionSource.error ? provisionSource.type : null
);
if (provisionSource && !provisionSource.error) {
const dataFieldName = provisionSourceDataFieldResolver[provisionSource.type];
if (dataFieldName) {
update[dataFieldName] = asValueObject(provisionSource.source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
validateVmLikeEntityName,
validateURL,
validateMemory,
validateUserTemplate,
} from '../../../../utils/validations';
import { objectMerge } from '../../../../utils/utils';
import { settingsValue } from '../../../../k8s/selectors';
Expand All @@ -20,6 +21,7 @@ import {
PROVIDERS_DATA_KEY,
PROVISION_SOURCE_TYPE_KEY,
MEMORY_KEY,
USER_TEMPLATE_KEY,
} from '../constants';
import { NAMESPACE_MUST_BE_SELECTED } from '../../../../utils/strings';
import { isProviderValid, validateProvider } from '../providers';
Expand All @@ -44,6 +46,7 @@ const asVmSettingsValidator = validator => asGenericFieldValidator(asUpdateValid

const validateResolver = {
[NAME_KEY]: asVmSettingsValidator(validateVmLikeEntityName),
[USER_TEMPLATE_KEY]: validateUserTemplate,
[CONTAINER_IMAGE_KEY]: asVmSettingsValidator(validateContainer),
[IMAGE_URL_KEY]: asVmSettingsValidator(validateURL),
[PROVIDER_KEY]: validateProviderDropdown,
Expand Down
2 changes: 2 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export const PROVISION_SOURCE_CONTAINER = 'Container';
export const PROVISION_SOURCE_URL = 'URL';
export const PROVISION_SOURCE_IMPORT = 'Import';
export const PROVISION_SOURCE_CLONED_DISK = 'Cloned Disk'; // PVC or upload image to PVC
export const PROVISION_SOURCE_UNKNOWN_DATAVOLUME = 'Unknown DataVolume';
export const PROVISION_SOURCE_UNKNOWN_DATAVOLUME_SOURCE = 'Unknown DataVolume Source';

export const PVC_ACCESSMODE_RWO = 'ReadWriteOnce';
export const PVC_ACCESSMODE_RWM = 'ReadWriteMany';
Expand Down
16 changes: 14 additions & 2 deletions src/utils/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
PROVISION_SOURCE_CONTAINER,
PROVISION_SOURCE_URL,
PROVISION_SOURCE_CLONED_DISK,
PROVISION_SOURCE_UNKNOWN_DATAVOLUME,
PROVISION_SOURCE_UNKNOWN_DATAVOLUME_SOURCE,
} from '../constants';
import { TemplateModel } from '../models';
import { DATA_VOLUME_SOURCE_URL, DATA_VOLUME_SOURCE_PVC } from '../components/Wizard/CreateVmWizard/constants';
Expand Down Expand Up @@ -146,12 +148,22 @@ export const getTemplateProvisionSource = (template, dataVolumes) => {
source: `${source.namespace}/${source.name}`,
};
default:
return null;
return {
type: PROVISION_SOURCE_UNKNOWN_DATAVOLUME_SOURCE,
error: `Datavolume ${bootVolume.dataVolume.name} does not have a supported source.`,
};
}
} else {
return {
type: PROVISION_SOURCE_UNKNOWN_DATAVOLUME,
error: `Datavolume ${bootVolume.dataVolume.name} does not exist.`,
};
}
}
}
return null;
return {
error: `No bootable device found.`,
};
};

export const retrieveVmTemplate = (k8sGet, vm) =>
Expand Down
20 changes: 19 additions & 1 deletion src/utils/validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ import {

import { parseUrl } from './utils';

import { VALIDATION_ERROR_TYPE, METALKUBE_CONTROLLER_PROTOCOLS } from '../constants';
import { VALIDATION_ERROR_TYPE, METALKUBE_CONTROLLER_PROTOCOLS, TEMPLATE_TYPE_VM } from '../constants';
import { getName, getNamespace } from '../selectors';
import {
CREATE_TEMPLATE_KEY,
DATAVOLUMES_KEY,
NAMESPACE_KEY,
TEMPLATES_KEY,
VIRTUAL_MACHINES_KEY,
} from '../components/Wizard/CreateVmWizard/constants';
import { getTemplate, getTemplateProvisionSource } from './templates';

export const isPositiveNumber = value => value && value.toString().match(/^[1-9]\d*$/);

Expand Down Expand Up @@ -84,6 +86,22 @@ export const validateVmLikeEntityName = (value, vmSettings, props) => {
);
};

export const validateUserTemplate = (userTemplateKey, vmSettings, props) => {
const userTemplateName = get(vmSettings, [userTemplateKey, 'value']);
const userTemplate =
userTemplateName &&
getTemplate(props[TEMPLATES_KEY], TEMPLATE_TYPE_VM).find(template => getName(template) === userTemplateName);

const provisionSource = userTemplate && getTemplateProvisionSource(userTemplate, props[DATAVOLUMES_KEY]);

return {
validation:
provisionSource && provisionSource.error
? getValidationObject(`Could not select Provision Source. ${provisionSource.error}`)
: null,
};
};

export const validateMemory = value => {
if (!value) {
return getValidationObject(EMPTY_ERROR);
Expand Down

0 comments on commit 8ae94b0

Please sign in to comment.