Wizard: Add validation for kernel step

This adds validation for the Kernel step.
This commit is contained in:
regexowl 2025-01-20 12:35:48 +01:00 committed by Klara Simickova
parent 2d011c52e1
commit bfef28999d
5 changed files with 64 additions and 1 deletions

View file

@ -40,6 +40,7 @@ import {
useDetailsValidation,
useRegistrationValidation,
useHostnameValidation,
useKernelValidation,
} from './utilities/useValidation';
import {
isAwsAccountIdValid,
@ -223,6 +224,8 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
const fileSystemValidation = useFilesystemValidation();
// Hostname
const hostnameValidation = useHostnameValidation();
// Kernel
const kernelValidation = useKernelValidation();
// Firstboot
const firstBootValidation = useFirstBootValidation();
// Details
@ -510,8 +513,12 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
key="wizard-kernel"
navItem={customStatusNavItem}
isHidden={!isKernelEnabled}
status={kernelValidation.disabledNext ? 'error' : 'default'}
footer={
<CustomWizardFooter disableNext={false} optional={true} />
<CustomWizardFooter
disableNext={kernelValidation.disabledNext}
optional={true}
/>
}
>
<KernelStep />

View file

@ -4,6 +4,8 @@ import { FormGroup } from '@patternfly/react-core';
import {
Alert,
Button,
HelperText,
HelperTextItem,
MenuToggle,
MenuToggleElement,
Select,
@ -20,6 +22,7 @@ import {
changeKernelName,
selectKernel,
} from '../../../../../store/wizardSlice';
import { useKernelValidation } from '../../../utilities/useValidation';
const initialOptions = ['kernel', 'kernel-debug'];
let kernelOptions = initialOptions;
@ -28,6 +31,8 @@ const KernelName = () => {
const dispatch = useAppDispatch();
const kernel = useAppSelector(selectKernel).name;
const stepValidation = useKernelValidation();
const [isOpen, setIsOpen] = useState(false);
const [inputValue, setInputValue] = useState<string>('');
const [filterValue, setFilterValue] = useState<string>('');
@ -166,6 +171,13 @@ const KernelName = () => {
))}
</SelectList>
</Select>
{stepValidation.errors.kernel && (
<HelperText>
<HelperTextItem variant={'error'}>
{stepValidation.errors.kernel}
</HelperTextItem>
</HelperText>
)}
</FormGroup>
</>
);

View file

@ -19,6 +19,7 @@ import {
selectActivationKey,
selectRegistrationType,
selectHostname,
selectKernel,
} from '../../../store/wizardSlice';
import {
getDuplicateMountPoints,
@ -27,6 +28,7 @@ import {
isMountpointMinSizeValid,
isSnapshotValid,
isHostnameValid,
isKernelNameValid,
} from '../validators';
export type StepValidation = {
@ -41,6 +43,7 @@ export function useIsBlueprintValid(): boolean {
const filesystem = useFilesystemValidation();
const snapshot = useSnapshotValidation();
const hostname = useHostnameValidation();
const kernel = useKernelValidation();
const firstBoot = useFirstBootValidation();
const details = useDetailsValidation();
return (
@ -48,6 +51,7 @@ export function useIsBlueprintValid(): boolean {
!filesystem.disabledNext &&
!snapshot.disabledNext &&
!hostname.disabledNext &&
!kernel.disabledNext &&
!firstBoot.disabledNext &&
!details.disabledNext
);
@ -155,6 +159,20 @@ export function useHostnameValidation(): StepValidation {
return { errors: {}, disabledNext: false };
}
export function useKernelValidation(): StepValidation {
const kernel = useAppSelector(selectKernel);
if (!isKernelNameValid(kernel.name)) {
return {
errors: {
kernel: 'Invalid format.',
},
disabledNext: true,
};
}
return { errors: {}, disabledNext: false };
}
export function useDetailsValidation(): StepValidation {
const name = useAppSelector(selectBlueprintName);
const description = useAppSelector(selectBlueprintDescription);

View file

@ -91,6 +91,17 @@ export const isHostnameValid = (hostname: string) => {
);
};
export const isKernelNameValid = (kernelName: string) => {
if (!kernelName) {
return true;
}
return (
kernelName.length < 65 &&
/^[a-z0-9]|[a-z0-9][a-z0-9-_.+]*[a-z0-9]$/.test(kernelName)
);
};
export const isPortValid = (port: string) => {
return /^(\d{1,5}|[a-z]{1,6})(-\d{1,5})?:[a-z]{1,6}$/.test(port);
};

View file

@ -8,6 +8,7 @@ import {
clickBack,
clickNext,
enterBlueprintName,
getNextButton,
interceptBlueprintRequest,
openAndDismissSaveAndBuildModal,
verifyCancelButton,
@ -121,6 +122,20 @@ describe('Step Kernel', () => {
await openKernelNameOptions(kernelNameDropdown);
await screen.findByText(CUSTOM_NAME);
});
test('disable Next with invalid custom kernel name', async () => {
await renderCreateMode();
await goToKernelStep();
await selectCustomKernelName('-----------');
await screen.findByText(/Invalid format/);
const nextButton = await getNextButton();
expect(nextButton).toBeDisabled();
await clearKernelName();
expect(screen.queryByText(/Invalid format/)).not.toBeInTheDocument();
expect(nextButton).toBeEnabled();
});
});
describe('Kernel request generated correctly', () => {