diff --git a/libs/types/assisted-installer-service.d.ts b/libs/types/assisted-installer-service.d.ts index f81331bacb..58c7f5e366 100644 --- a/libs/types/assisted-installer-service.d.ts +++ b/libs/types/assisted-installer-service.d.ts @@ -1838,6 +1838,10 @@ export interface InfraEnv { * The type of network configuration for hosts: 'dhcp' for DHCP only, 'static' for static IP configuration. */ hostsNetworkConfigurationType?: 'dhcp' | 'static'; + /** + * The pull secret obtained from Red Hat OpenShift Cluster Manager at console.redhat.com/openshift/install/pull-secret. + */ + pullSecret?: string; } export interface InfraEnvCreateParams { /** diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterDetails.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterDetails.tsx index 1a5dde8102..ce95bd2b61 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterDetails.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterDetails.tsx @@ -39,7 +39,6 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => { const navigate = useNavigate(); const dispatch = useDispatch(); const { usedClusterNames } = useUsedClusterNames(cluster?.id || ''); - const pullSecret = usePullSecret(); const { error: errorOCPVersions, loading: loadingOCPVersions, @@ -47,6 +46,8 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => { } = useOpenShiftVersionsContext(); const location = useLocation(); const isSingleClusterFeatureEnabled = useFeature('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE'); + const defaultPullSecret = usePullSecret(); + const pullSecret = isSingleClusterFeatureEnabled ? infraEnv?.pullSecret || '' : defaultPullSecret; const handleClusterUpdate = React.useCallback( async ( diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContext.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContext.tsx index 8027e86961..9c7522ca9a 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContext.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContext.tsx @@ -23,12 +23,6 @@ export type ClusterWizardContextType = { setInstallDisconnected: (enabled: boolean) => void; disconnectedInfraEnv?: InfraEnv; setDisconnectedInfraEnv: (infraEnv: InfraEnv | undefined) => void; - /** Last pull secret submitted in disconnected Optional configurations (restored when going back from Review) */ - disconnectedFormPullSecret?: string; - setDisconnectedFormPullSecret: (value: string | undefined) => void; - /** Whether "Edit pull secret" was checked when user last clicked Next (restored when going back from Review) */ - disconnectedFormEditPullSecret?: boolean; - setDisconnectedFormEditPullSecret: (value: boolean) => void; }; export const ClusterWizardContext = React.createContext(null); diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx index d83c946652..86863ed601 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx @@ -124,9 +124,6 @@ const ClusterWizardContextProvider = ({ const [disconnectedInfraEnv, setDisconnectedInfraEnv] = React.useState( infraEnv, ); - const [disconnectedFormPullSecret, setDisconnectedFormPullSecret] = React.useState(); - const [disconnectedFormEditPullSecret, setDisconnectedFormEditPullSecret] = - React.useState(); const location = useLocation(); const locationState = location.state as ClusterWizardFlowStateType | undefined; const { @@ -334,10 +331,6 @@ const ClusterWizardContextProvider = ({ }, disconnectedInfraEnv, setDisconnectedInfraEnv, - disconnectedFormPullSecret, - setDisconnectedFormPullSecret, - disconnectedFormEditPullSecret, - setDisconnectedFormEditPullSecret, }; }, [ wizardStepIds, @@ -353,8 +346,6 @@ const ClusterWizardContextProvider = ({ connectedWizardStepIds, disconnectedWizardStepIds, disconnectedInfraEnv, - disconnectedFormPullSecret, - disconnectedFormEditPullSecret, ]); if (!contextValue) { diff --git a/libs/ui-lib/lib/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.tsx b/libs/ui-lib/lib/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.tsx index e55dadd701..f8dbc6028d 100644 --- a/libs/ui-lib/lib/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.tsx @@ -1,12 +1,11 @@ import * as React from 'react'; -import { Formik, useFormikContext } from 'formik'; +import { Formik } from 'formik'; import { TFunction } from 'i18next'; import * as Yup from 'yup'; import { ClusterWizardStep, TechnologyPreview, sshPublicKeyValidationSchema, - pullSecretValidationSchema, getFormikErrorFields, httpProxyValidationSchema, noProxyValidationSchema, @@ -15,16 +14,17 @@ import { CheckboxField, AdditionalNTPSourcesField, ProxyFieldsType, + PullSecret, + pullSecretValidationSchema, } from '../../../../common'; -import { Split, SplitItem, Grid, GridItem, Form, Content, Checkbox } from '@patternfly/react-core'; +import { Split, SplitItem, Grid, GridItem, Form, Content } from '@patternfly/react-core'; import { useClusterWizardContext } from '../ClusterWizardContext'; import ClusterWizardFooter from '../ClusterWizardFooter'; import ClusterWizardNavigation from '../ClusterWizardNavigation'; import { WithErrorBoundary } from '../../../../common/components/ErrorHandling/WithErrorBoundary'; import UploadSSH from '../../../../common/components/clusterConfiguration/UploadSSH'; -import PullSecretField from '../../../../common/components/ui/formik/PullSecretField'; import { ProxyInputFields } from '../../../../common/components/clusterConfiguration/ProxyFields'; -import { isInOcm, handleApiError, getApiErrorMessage } from '../../../../common/api'; +import { handleApiError, getApiErrorMessage } from '../../../../common/api'; import { useAlerts } from '../../../../common/components/AlertsContextProvider'; import { AlertVariant } from '@patternfly/react-core'; import InfraEnvsService from '../../../services/InfraEnvsService'; @@ -43,22 +43,22 @@ import { HostsNetworkConfigurationType } from '../../../services/types'; import { useTranslation } from '../../../../common/hooks/use-translation-wrapper'; import { getDummyInfraEnvField } from '../../clusterConfiguration/staticIp/data/dummyData'; import { ntpSourceValidationSchema } from '../../../../common/validationSchemas/ntpValidation'; +import { isInOcm } from '../../../../common/api'; const DEFAULT_CPU_ARCHITECTURE = 'x86_64' as const; const DISCONNECTED_IMAGE_TYPE = 'disconnected-iso' as const; type OptionalConfigurationsFormValues = ProxyFieldsType & { sshPublicKey?: string; - pullSecret: string; enableNtpSources: boolean; additionalNtpSources?: string; hostsNetworkConfigurationType: HostsNetworkConfigurationType; rendezvousIp?: string; + pullSecret?: string; }; const DEFAULT_INITIAL_VALUES: OptionalConfigurationsFormValues = { sshPublicKey: '', - pullSecret: '', enableProxy: false, httpProxy: '', httpsProxy: '', @@ -67,18 +67,15 @@ const DEFAULT_INITIAL_VALUES: OptionalConfigurationsFormValues = { additionalNtpSources: '', hostsNetworkConfigurationType: HostsNetworkConfigurationType.DHCP, rendezvousIp: '', + pullSecret: '', }; /** - * Rehydrate form values from infraEnv and optional stored pull secret (API does not return pull secret). + * Rehydrate form values from infraEnv when navigating back to this step. */ -const infraEnvToFormValues = ( - infraEnv: InfraEnv, - storedPullSecret?: string, -): OptionalConfigurationsFormValues => ({ +const infraEnvToFormValues = (infraEnv: InfraEnv): OptionalConfigurationsFormValues => ({ ...DEFAULT_INITIAL_VALUES, sshPublicKey: infraEnv.sshAuthorizedKey ?? '', - pullSecret: storedPullSecret ?? '', enableProxy: !!(infraEnv.proxy?.httpProxy || infraEnv.proxy?.httpsProxy), httpProxy: infraEnv.proxy?.httpProxy ?? '', httpsProxy: infraEnv.proxy?.httpsProxy ?? '', @@ -105,7 +102,6 @@ const buildInfraEnvParams = (values: OptionalConfigurationsFormValues) => { const hasProxy = Object.keys(proxy).length > 0; return { - pullSecret: values.pullSecret, ...(values.sshPublicKey && { sshAuthorizedKey: values.sshPublicKey }), ...(hasProxy && { proxy }), ...(values.additionalNtpSources && { @@ -120,11 +116,10 @@ const buildInfraEnvParams = (values: OptionalConfigurationsFormValues) => { }; }; -const getValidationSchema = (t: TFunction) => +const getValidationSchema = (t: TFunction, requirePullSecret: boolean) => Yup.lazy((values: OptionalConfigurationsFormValues) => Yup.object().shape({ sshPublicKey: sshPublicKeyValidationSchema(t), - pullSecret: pullSecretValidationSchema(t).required('Required field'), enableProxy: Yup.boolean().required(), httpProxy: httpProxyValidationSchema({ values, @@ -151,40 +146,20 @@ const getValidationSchema = (t: TFunction) => 'Not a valid IP address', (value) => !value || ipValidationSchema(t).isValidSync(value), ), + ...(requirePullSecret && { + pullSecret: pullSecretValidationSchema(t).required(t('ai:Required field')), + }), }), ); -const PullSecretSync = () => { - const defaultPullSecret = usePullSecret(); - const { - setFieldValue, - values: { pullSecret }, - } = useFormikContext(); - - React.useEffect(() => { - if (defaultPullSecret !== undefined && pullSecret === '') { - setFieldValue('pullSecret', defaultPullSecret); - } - }, [defaultPullSecret, pullSecret, setFieldValue]); - - return null; -}; - const OptionalConfigurationsStep = () => { const { clusterId } = useParams<{ clusterId: string }>(); const [cluster, setCluster] = React.useState(null); const { t } = useTranslation(); + const defaultPullSecret = usePullSecret(); - const { - moveNext, - moveBack, - setDisconnectedInfraEnv, - disconnectedInfraEnv, - disconnectedFormPullSecret, - setDisconnectedFormPullSecret, - disconnectedFormEditPullSecret, - setDisconnectedFormEditPullSecret, - } = useClusterWizardContext(); + const { moveNext, moveBack, setDisconnectedInfraEnv, disconnectedInfraEnv } = + useClusterWizardContext(); const { addAlert, clearAlerts } = useAlerts(); React.useEffect(() => { @@ -209,14 +184,14 @@ const OptionalConfigurationsStep = () => { }, [clusterId, addAlert, t]); const initialValues: OptionalConfigurationsFormValues = disconnectedInfraEnv - ? infraEnvToFormValues(disconnectedInfraEnv, disconnectedFormPullSecret) + ? infraEnvToFormValues(disconnectedInfraEnv) : DEFAULT_INITIAL_VALUES; return ( { clearAlerts(); if (!cluster?.id) { @@ -229,6 +204,8 @@ const OptionalConfigurationsStep = () => { } const commonParams = buildInfraEnvParams(values); + // Default pull secret only exists in OCM; when !isInOcm the user must provide it via the field + const pullSecretToUse = isInOcm ? defaultPullSecret : values.pullSecret; try { if (disconnectedInfraEnv?.id) { @@ -236,15 +213,12 @@ const OptionalConfigurationsStep = () => { const updateParams: InfraEnvUpdateParams = { ...commonParams, imageType: DISCONNECTED_IMAGE_TYPE, + pullSecret: pullSecretToUse, }; const { data: updatedInfraEnv } = await InfraEnvsAPI.update( disconnectedInfraEnv.id, updateParams, ); - setDisconnectedFormPullSecret(values.pullSecret); - setDisconnectedFormEditPullSecret( - disconnectedFormEditPullSecret ?? !!disconnectedInfraEnv?.pullSecretSet, - ); setDisconnectedInfraEnv({ ...updatedInfraEnv, // infraEnv does not return the whole OCP version @@ -258,13 +232,10 @@ const OptionalConfigurationsStep = () => { openshiftVersion: cluster.openshiftVersion, cpuArchitecture: DEFAULT_CPU_ARCHITECTURE, imageType: DISCONNECTED_IMAGE_TYPE, + pullSecret: pullSecretToUse ?? '', ...commonParams, }; const createdInfraEnv = await InfraEnvsService.create(createParams); - setDisconnectedFormPullSecret(values.pullSecret); - setDisconnectedFormEditPullSecret( - disconnectedFormEditPullSecret ?? !!disconnectedInfraEnv?.pullSecretSet, - ); setDisconnectedInfraEnv({ ...createdInfraEnv, // infraEnv does not return the whole OCP version @@ -306,7 +277,6 @@ const OptionalConfigurationsStep = () => { } > - @@ -320,6 +290,9 @@ const OptionalConfigurationsStep = () => {
+ {/* Pull secret (!OCM only) */} + {!isInOcm && } + {/* Rendezvous IP */} { /> - setDisconnectedFormEditPullSecret(checked)} - id="edit-pull-secret-checkbox" - /> - {(disconnectedFormEditPullSecret ?? !!disconnectedInfraEnv?.pullSecretSet) && ( - - )} {/* Proxy Settings */}