fsc: load the oscap profile when available.

When the user has selected a profile to customize their distribution,
the FSC step now shows immediately the manual configuration opened up
with the partitions coming from the profile already filled in.

If the user goes back to the Compliance step and changes anything, the
FSC step is going to be reinitialized.

HMS-2077
This commit is contained in:
Thomas Lavocat 2023-10-03 14:23:44 +02:00 committed by Klara Simickova
parent 18cc74cf6b
commit 7c55190ac3
4 changed files with 112 additions and 19 deletions

View file

@ -7,6 +7,7 @@ import {
Alert,
Button,
Popover,
Spinner,
Text,
TextContent,
TextVariants,
@ -28,10 +29,11 @@ import {
} from '@patternfly/react-table';
import { v4 as uuidv4 } from 'uuid';
import MountPoint from './MountPoint';
import MountPoint, { MountPointValidPrefixes } from './MountPoint';
import SizeUnit from './SizeUnit';
import { UNIT_GIB } from '../../../constants';
import { UNIT_GIB, UNIT_KIB, UNIT_MIB } from '../../../constants';
import { useGetOscapCustomizationsQuery } from '../../../store/imageBuilderApi';
const initialRow = {
id: uuidv4(),
@ -52,6 +54,56 @@ const FileSystemConfiguration = ({ ...props }) => {
const bodyref = useRef();
const [rows, setRows] = useState([initialRow]);
const oscapPolicy = getState()?.values?.['oscap-policy'];
const hasNoOscapPolicy = !oscapPolicy;
const hasCustomizations = !(
getState()?.values?.['file-system-configuration'] === undefined ||
getState().values['file-system-configuration'].length === 1
);
const {
data: customizations,
isFetching: isFetchingCustomizations,
isSuccess,
} = useGetOscapCustomizationsQuery(
{
distribution: getState()?.values?.['release'],
profile: oscapPolicy,
},
{
// Don't override the user's data if they made customizations
skip: hasNoOscapPolicy || hasCustomizations,
}
);
useEffect(() => {
if (hasCustomizations || rows.length > 1) {
return;
}
if (customizations && customizations.filesystem && isSuccess) {
const newRows = rows;
// Only keep the required partitions that have a valid mount points
const fss = customizations.filesystem.filter((fs) =>
MountPointValidPrefixes.includes(fs.mountpoint)
);
// And add them all to the list.
for (const fs of fss) {
newRows.push({
id: uuidv4(),
mountpoint: fs.mountpoint,
fstype: 'xfs',
size: fs.min_size / UNIT_MIB, // the unit from the customizations are in bytes
unit: UNIT_MIB, // and using MIB seems sensible here instead
});
}
setRows(newRows);
setItemOrder(newRows.map((row) => row.id));
change('file-system-config-radio', 'manual');
}
}, [customizations, isSuccess]);
useEffect(() => {
const fsc = getState()?.values?.['file-system-configuration'];
if (!fsc) {
@ -244,6 +296,13 @@ const FileSystemConfiguration = ({ ...props }) => {
setRows(newRows);
};
// Don't let the user interact with the partitions while we are getting the
// customizations. Having a customizations added by the user first would mess
// up the logic.
if (isFetchingCustomizations) {
return <Spinner isSVG size="lg" />;
}
return (
<FormSpy>
{() => (

View file

@ -10,26 +10,27 @@ import {
} from '@patternfly/react-core';
import PropTypes from 'prop-types';
export const MountPointValidPrefixes = [
'/app',
'/boot',
'/data',
'/home',
'/opt',
'/srv',
'/tmp',
'/usr',
'/usr/local',
'/var',
];
const MountPoint = ({ ...props }) => {
const validPrefixes = [
'/app',
'/boot',
'/data',
'/home',
'/opt',
'/srv',
'/tmp',
'/usr',
'/usr/local',
'/var',
];
const [isOpen, setIsOpen] = useState(false);
const [prefix, setPrefix] = useState('/');
const [suffix, setSuffix] = useState('');
// split
useEffect(() => {
for (const p of validPrefixes) {
for (const p of MountPointValidPrefixes) {
if (props.mountpoint.startsWith(p)) {
setPrefix(p);
setSuffix(props.mountpoint.substring(p.length));
@ -73,7 +74,7 @@ const MountPoint = ({ ...props }) => {
variant={SelectVariant.single}
isDisabled={prefix === '/' ? true : false}
>
{validPrefixes.map((pfx, index) => {
{MountPointValidPrefixes.map((pfx, index) => {
return <SelectOption key={index} value={pfx} />;
})}
</Select>

View file

@ -14,6 +14,17 @@ import {
import PropTypes from 'prop-types';
import { useGetOscapProfilesQuery } from '../../../store/imageBuilderApi';
import { reinitFileSystemConfiguratioStep } from '../steps/fileSystemConfiguration';
/**
* Every time there is change on this form step's state, reinitialise the steps
* that are depending on it. This will ensure that if the user goes back and
* change their mind, going forward again leaves them in a coherent and workable
* form state.
*/
const reinitDependingSteps = (change) => {
reinitFileSystemConfiguratioStep(change);
};
/**
* Component for the user to select the policy to apply to their image.
@ -49,12 +60,15 @@ const PolicySelector = ({ input, showSelector }) => {
const handleClear = () => {
selectPolicy(undefined);
change(input.name, undefined);
reinitDependingSteps(change);
};
const setPolicy = (_, selection) => {
selectPolicy(selection);
setIsOpen(false);
change(input.name, selection);
reinitDependingSteps(change);
change('file-system-config-radio', 'manual');
};
return (
@ -125,6 +139,7 @@ const AddPolicy = ({ input }) => {
isChecked={wantsPolicy}
onChange={() => {
setWantsPolicy(true);
reinitDependingSteps(change);
}}
/>
<Radio
@ -137,6 +152,7 @@ const AddPolicy = ({ input }) => {
onChange={() => {
setWantsPolicy(false);
change(input.name, undefined);
reinitDependingSteps(change);
}}
/>
</FormGroup>

View file

@ -15,6 +15,11 @@ import StepTemplate from './stepTemplate';
import FileSystemConfigButtons from '../formComponents/FileSystemConfigButtons';
export const reinitFileSystemConfiguratioStep = (change) => {
change('file-system-configuration', undefined);
change('file-system-config-radio', 'automatic');
};
const fileSystemConfigurationStep = {
StepTemplate,
id: 'wizard-systemconfiguration-filesystem',
@ -63,6 +68,10 @@ const fileSystemConfigurationStep = {
className: 'pf-u-mt-sm',
},
],
condition: {
when: 'oscap-policy',
is: undefined,
},
},
{
component: 'file-system-configuration',
@ -73,8 +82,13 @@ const fileSystemConfigurationStep = {
{ type: validatorTypes.REQUIRED },
],
condition: {
when: 'file-system-config-radio',
is: 'manual',
or: [
{
when: 'file-system-config-radio',
is: 'manual',
},
{ not: [{ when: 'oscap-policy', is: undefined }] },
],
},
},
{
@ -111,7 +125,10 @@ const fileSystemConfigurationStep = {
</TextContent>
),
condition: {
or: [{ when: 'file-system-config-radio', is: 'automatic' }],
or: [
{ when: 'file-system-config-radio', is: 'automatic' },
{ when: 'oscap-policy', is: undefined },
],
},
},
],