From e5a513a4cb4b57ccc6fe12e5ff712f65a8f558ac Mon Sep 17 00:00:00 2001 From: Gianluca Zuccarelli Date: Tue, 25 Mar 2025 14:50:53 +0000 Subject: [PATCH] CreateImageWizard: refactor oscap availability Refactor the OpenSCAP on-premise availability check. Add the check to the component so we run the check everytime the step is loaded. The benefits to this is that if the user installs the packages, they won't need to reload the page to use the OpenSCAP step. The downside is that the check is not very quick, so a spinner was added just to indicate that the check is running. --- .../CreateImageWizard/CreateImageWizard.tsx | 10 +---- .../steps/Oscap/OnPremSpinner.tsx | 18 ++++++++ .../CreateImageWizard/steps/Oscap/index.tsx | 21 +++++++++- src/Utilities/useOnPremOpenSCAP.tsx | 42 +++++++++---------- 4 files changed, 58 insertions(+), 33 deletions(-) create mode 100644 src/Components/CreateImageWizard/steps/Oscap/OnPremSpinner.tsx diff --git a/src/Components/CreateImageWizard/CreateImageWizard.tsx b/src/Components/CreateImageWizard/CreateImageWizard.tsx index 26430bc5..e7c59e5a 100644 --- a/src/Components/CreateImageWizard/CreateImageWizard.tsx +++ b/src/Components/CreateImageWizard/CreateImageWizard.tsx @@ -22,7 +22,6 @@ import ImageOutputStep from './steps/ImageOutput'; import KernelStep from './steps/Kernel'; import LocaleStep from './steps/Locale'; import OscapStep from './steps/Oscap'; -import OscapOnPremWarning from './steps/Oscap/OnPremWarning'; import PackagesStep from './steps/Packages'; import RegistrationStep from './steps/Registration'; import RepositoriesStep from './steps/Repositories'; @@ -82,7 +81,6 @@ import { import isRhel from '../../Utilities/isRhel'; import { resolveRelPath } from '../../Utilities/path'; import { useFlag } from '../../Utilities/useGetEnvironment'; -import { useOnPremOpenSCAPAvailable } from '../../Utilities/useOnPremOpenSCAP'; import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader'; type CustomWizardFooterPropType = { @@ -157,8 +155,6 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => { const isFirewallEnabled = useFlag('image-builder.firewall.enabled'); const isServicesStepEnabled = useFlag('image-builder.services.enabled'); - const onPremOpenSCAPAvailable = useOnPremOpenSCAPAvailable(); - // IMPORTANT: Ensure the wizard starts with a fresh initial state useEffect(() => { dispatch(initializeWizard()); @@ -416,11 +412,7 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => { } > - {process.env.IS_ON_PREMISE && !onPremOpenSCAPAvailable ? ( - - ) : ( - - )} + , { + return ( +
+ + OpenSCAP profile + + + + +
+ ); +}; + +export default OscapOnPremSpinner; diff --git a/src/Components/CreateImageWizard/steps/Oscap/index.tsx b/src/Components/CreateImageWizard/steps/Oscap/index.tsx index 1df6a309..96322a55 100644 --- a/src/Components/CreateImageWizard/steps/Oscap/index.tsx +++ b/src/Components/CreateImageWizard/steps/Oscap/index.tsx @@ -10,6 +10,8 @@ import { } from '@patternfly/react-core'; import { ExternalLinkAltIcon } from '@patternfly/react-icons'; +import OscapOnPremSpinner from './OnPremSpinner'; +import OscapOnPremWarning from './OnPremWarning'; import { Oscap, removeBetaFromRelease } from './Oscap'; import { @@ -36,8 +38,9 @@ import { clearKernelAppend, } from '../../../../store/wizardSlice'; import { useFlag } from '../../../../Utilities/useGetEnvironment'; +import { useOnPremOpenSCAPAvailable } from '../../../../Utilities/useOnPremOpenSCAP'; -const OscapStep = () => { +const OscapContent = () => { const dispatch = useAppDispatch(); const complianceEnabled = useFlag('image-builder.compliance.enabled'); const complianceType = useAppSelector(selectComplianceType); @@ -159,4 +162,20 @@ const OscapStep = () => { ); }; +const OnPremOscapStep = () => { + const [onPremOpenSCAPAvailable, isLoading] = useOnPremOpenSCAPAvailable(); + + if (isLoading) { + return ; + } + + if (!onPremOpenSCAPAvailable) { + return ; + } + + return ; +}; + +const OscapStep = process.env.IS_ON_PREMISE ? OnPremOscapStep : OscapContent; + export default OscapStep; diff --git a/src/Utilities/useOnPremOpenSCAP.tsx b/src/Utilities/useOnPremOpenSCAP.tsx index 9c8a2d9c..6629ed4f 100644 --- a/src/Utilities/useOnPremOpenSCAP.tsx +++ b/src/Utilities/useOnPremOpenSCAP.tsx @@ -3,34 +3,30 @@ import { useEffect, useState } from 'react'; import cockpit from 'cockpit'; export const useOnPremOpenSCAPAvailable = () => { + // this can default to false in the service, since we will only render + // a loading spinner for on-prem + const [isLoading, setIsLoading] = useState(true); const [packagesAvailable, setPackagesAvailable] = useState(false); useEffect(() => { - const checkPackages = async () => { - try { - const openSCAPAvailable = await cockpit.spawn( - ['rpm', '-qa', 'openscap-scanner'], - {} - ); - - const ssgAvailable = await cockpit.spawn( - ['rpm', '-qa', 'scap-security-guide'], - {} - ); - - setPackagesAvailable(openSCAPAvailable !== '' && ssgAvailable !== ''); - } catch { - // this doesn't change the value, - // but we need to handle the error - // so just set the value to false - setPackagesAvailable(false); - } + const checkPackages = () => { + cockpit + .spawn(['rpm', '-qa', 'openscap-scanner', 'scap-security-guide'], {}) + .then((res: string) => { + setPackagesAvailable( + res.includes('openscap-scanner') && + res.includes('scap-security-guide') + ); + setIsLoading(false); + }) + .catch(() => { + setPackagesAvailable(false); + setIsLoading(false); + }); }; - if (process.env.IS_ON_PREMISE) { - checkPackages(); - } + checkPackages(); }, []); - return packagesAvailable; + return [packagesAvailable, isLoading]; };