diff --git a/libs/locales/lib/en/translation.json b/libs/locales/lib/en/translation.json index 4b778f0db2..fd7337b9e4 100644 --- a/libs/locales/lib/en/translation.json +++ b/libs/locales/lib/en/translation.json @@ -36,6 +36,7 @@ "ai:1-{{count}} characters_plural": "1-{{count}} characters", "ai:1-253 characters": "1-253 characters", "ai:1-63 characters": "1-63 characters", + "ai:2 (Two-Nodes Arbiter)": "2 (Two-Nodes Arbiter)", "ai:2-{{count}} characters": "2-{{count}} characters", "ai:2-{{count}} characters_plural": "2-{{count}} characters", "ai:3 (highly available cluster)": "3 (highly available cluster)", @@ -838,7 +839,6 @@ "ai:The storage sizes will be used to store different files and data for cluster creation.": "The storage sizes will be used to store different files and data for cluster creation.", "ai:The subnet prefix length to assign to each individual node. For example, if Cluster Network Host Prefix is set to 116, then each node is assigned a /116 subnet out of the given cidr (clusterNetworkCIDR), which allows for 4,094 (2^(128 - 116) - 2) pod IPs addresses. If you are required to provide access to nodes from an external network, configure load balancers and routers to manage the traffic.": "The subnet prefix length to assign to each individual node. For example, if Cluster Network Host Prefix is set to 116, then each node is assigned a /116 subnet out of the given cidr (clusterNetworkCIDR), which allows for 4,094 (2^(128 - 116) - 2) pod IPs addresses. If you are required to provide access to nodes from an external network, configure load balancers and routers to manage the traffic.", "ai:The subnet prefix length to assign to each individual node. For example, if Cluster Network Host Prefix is set to 23, then each node is assigned a /23 subnet out of the given cidr (clusterNetworkCIDR), which allows for 510 (2^(32 - 23) - 2) pod IPs addresses. If you are required to provide access to nodes from an external network, configure load balancers and routers to manage the traffic.": "The subnet prefix length to assign to each individual node. For example, if Cluster Network Host Prefix is set to 23, then each node is assigned a /23 subnet out of the given cidr (clusterNetworkCIDR), which allows for 510 (2^(32 - 23) - 2) pod IPs addresses. If you are required to provide access to nodes from an external network, configure load balancers and routers to manage the traffic.", - "ai:The use of Tang encryption mode to encrypt your disks is only supported for bare metal or vSphere installations on user-provisioned infrastructure.": "The use of Tang encryption mode to encrypt your disks is only supported for bare metal or vSphere installations on user-provisioned infrastructure.", "ai:The Value is not valid BMC address, supported protocols are redfish-virtualmedia or idrac-virtualmedia.": "The Value is not valid BMC address, supported protocols are redfish-virtualmedia or idrac-virtualmedia.", "ai:The YAML file might not be formatted correctly. Use the template to format and try again.": "The YAML file might not be formatted correctly. Use the template to format and try again.", "ai:There are no events that match the current filters. Adjust or clear the filters to view events.": "There are no events that match the current filters. Adjust or clear the filters to view events.", @@ -882,7 +882,6 @@ "ai:To enable the host's baseboard management controller (BMC) on the hub cluster, you must first <2>create a provisioning configuration.": "To enable the host's baseboard management controller (BMC) on the hub cluster, you must first <2>create a provisioning configuration.", "ai:To finish adding nodes to the cluster, approve the join request inside OpenShift Console's Nodes section.": "To finish adding nodes to the cluster, approve the join request inside OpenShift Console's Nodes section.", "ai:To use static network configuration, follow the steps listed in the documentation.": "To use static network configuration, follow the steps listed in the documentation.", - "ai:To use this encryption method, enable TPMv2 encryption in the BIOS of each selected host.": "To use this encryption method, enable TPMv2 encryption in the BIOS of each selected host.", "ai:To verify that the agent ran successfully, check the logs:": "To verify that the agent ran successfully, check the logs:", "ai:To view detailed agent logs and communication use following command:": "To view detailed agent logs and communication use following command:", "ai:Total compute": "Total compute", diff --git a/libs/ui-lib/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.tsx b/libs/ui-lib/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.tsx index a304df2540..50cb89d843 100644 --- a/libs/ui-lib/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.tsx +++ b/libs/ui-lib/lib/cim/components/ClusterDeployment/clusterDetails/ClusterDetailsFormFields.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; -import { Alert, AlertVariant, FlexItem, Form } from '@patternfly/react-core'; +import { Form } from '@patternfly/react-core'; import { useFormikContext } from 'formik'; import { ExternalPlatformsDropdown, + isMajorMinorVersionEqualOrGreater, OpenShiftVersionDropdown, OpenShiftVersionModal, } from '../../../../common'; @@ -99,8 +100,13 @@ export const ClusterDetailsFormFields: React.FC = return undefined; }, [allVersions, values.customOpenshiftSelect, versions]); - const isDiskEncryptionEnabled = - values.enableDiskEncryptionOnMasters || values.enableDiskEncryptionOnWorkers; + const allowTNA = React.useMemo(() => { + const current = + values.customOpenshiftSelect || + versions.find((version) => version.value === values.openshiftVersion)?.version; + + return isMajorMinorVersionEqualOrGreater(current, '4.19') && values.platform === 'baremetal'; + }, [values.customOpenshiftSelect, values.openshiftVersion, values.platform, versions]); return (
@@ -162,6 +168,7 @@ export const ClusterDetailsFormFields: React.FC = {!isNutanix && ( @@ -170,39 +177,10 @@ export const ClusterDetailsFormFields: React.FC = {extensionAfter?.['openshiftVersion'] && extensionAfter['openshiftVersion']} + {!isEditFlow && } + {extensionAfter?.['pullSecret'] && extensionAfter['pullSecret']} - {/* */} - {isDiskEncryptionEnabled && values.diskEncryptionMode === 'tpmv2' && ( - - {t( - 'ai:To use this encryption method, enable TPMv2 encryption in the BIOS of each selected host.', - )} - - } - /> - )} - {isDiskEncryptionEnabled && values.diskEncryptionMode === 'tang' && ( - - {t( - 'ai:The use of Tang encryption mode to encrypt your disks is only supported for bare metal or vSphere installations on user-provisioned infrastructure.', - )} - - } - /> - )} ); }; diff --git a/libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts b/libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts index 20cb08b8d0..753d6c9614 100644 --- a/libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts +++ b/libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts @@ -42,6 +42,7 @@ export type AgentClusterInstallK8sResource = K8sResourceCommon & { provisionRequirements: { controlPlaneAgents: number; workerAgents?: number; + arbiterAgents?: number; }; networking: { clusterNetwork?: { diff --git a/libs/ui-lib/lib/common/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx b/libs/ui-lib/lib/common/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx index 6bbb9eea29..79afe36864 100644 --- a/libs/ui-lib/lib/common/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx +++ b/libs/ui-lib/lib/common/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx @@ -12,6 +12,21 @@ import { useTranslation } from '../../hooks/use-translation-wrapper'; import { getFieldId, StaticField } from '../..'; import { useField } from 'formik'; import toNumber from 'lodash-es/toNumber'; +import OcmTNADisclaimer from './OcmTNADisclaimer'; + +const isItemEnabled = (value: number, allowHighlyAvailable?: boolean, allowTNA?: boolean) => { + switch (value) { + case 1: + case 3: + return true; + case 2: + return !!allowTNA; + case 4: + case 5: + return !!allowHighlyAvailable; + } + return false; +}; interface ControlPlaneNodesOption { value: number; @@ -21,9 +36,11 @@ interface ControlPlaneNodesOption { const ControlPlaneNodesDropdown = ({ isDisabled = false, allowHighlyAvailable, + allowTNA, }: { isDisabled?: boolean; allowHighlyAvailable?: boolean; + allowTNA?: boolean; }) => { const { t } = useTranslation(); const [{ name, value: selectedValue }, , { setValue }] = useField('controlPlaneCount'); @@ -32,6 +49,7 @@ const ControlPlaneNodesDropdown = ({ const options: ControlPlaneNodesOption[] = [ { value: 1, label: t('ai:1 (Single Node OpenShift - not highly available cluster)') }, + { value: 2, label: t('ai:2 (Two-Nodes Arbiter)') }, { value: 3, label: t('ai:3 (highly available cluster)') }, { value: 4, label: t('ai:4 (highly available cluster+)') }, { value: 5, label: t('ai:5 (highly available cluster++)') }, @@ -44,7 +62,8 @@ const ControlPlaneNodesDropdown = ({ }, [allowHighlyAvailable, selectedValue, setValue]); const dropdownItems = options.map(({ value, label }) => { - const isItemEnabled = [1, 3].includes(value) || allowHighlyAvailable; + const isEnabled = isItemEnabled(value, allowHighlyAvailable, allowTNA); + const disabledReason = t('ai:This option is not available with the selected OpenShift version'); return ( - @@ -70,36 +89,47 @@ const ControlPlaneNodesDropdown = ({ setControlPlanelOpen(false); }; - return !isDisabled ? ( - - setControlPlanelOpen(!controlPlanelOpen)} - toggle={(toggleRef: React.Ref) => ( - setControlPlanelOpen(!controlPlanelOpen)} - isExpanded={controlPlanelOpen} + return ( + <> + {!isDisabled ? ( + + setControlPlanelOpen(!controlPlanelOpen)} + toggle={(toggleRef: React.Ref) => ( + setControlPlanelOpen(!controlPlanelOpen)} + isExpanded={controlPlanelOpen} + > + {selectedValue ? selectedValue : '3'} + + )} + shouldFocusToggleOnSelect > - {selectedValue ? selectedValue : '3'} - - )} - shouldFocusToggleOnSelect - > - {dropdownItems} - - - ) : ( - - {selectedValue} - + {dropdownItems} + + + ) : ( + + {selectedValue} + + )} + + {selectedValue === 2 && } + ); }; diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/OcmTNADisclaimer.tsx b/libs/ui-lib/lib/common/components/clusterConfiguration/OcmTNADisclaimer.tsx similarity index 87% rename from libs/ui-lib/lib/ocm/components/clusterConfiguration/OcmTNADisclaimer.tsx rename to libs/ui-lib/lib/common/components/clusterConfiguration/OcmTNADisclaimer.tsx index 97bfc76b4c..902c963484 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/OcmTNADisclaimer.tsx +++ b/libs/ui-lib/lib/common/components/clusterConfiguration/OcmTNADisclaimer.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Alert, AlertVariant, List, ListItem } from '@patternfly/react-core'; -import { useTranslation } from '../../../common/hooks/use-translation-wrapper'; +import { useTranslation } from '../../hooks/use-translation-wrapper'; const OcmTNADisclaimer = () => { const { t } = useTranslation(); diff --git a/libs/ui-lib/lib/common/config/constants.ts b/libs/ui-lib/lib/common/config/constants.ts index 6801376c21..c26882478c 100644 --- a/libs/ui-lib/lib/common/config/constants.ts +++ b/libs/ui-lib/lib/common/config/constants.ts @@ -5,12 +5,10 @@ import { ClusterValidationId, DiskRole, Event, - HostRoleUpdateParams, HostValidationId, } from '@openshift-assisted/types/assisted-installer-service'; import { ValidationGroup as ClusterValidationGroup } from '../types/clusters'; import buildManifest from '@openshift-assisted/ui-lib/package.json'; -import { isInOcm } from '../api/axiosClient'; export const DEFAULT_POLLING_INTERVAL = 10 * 1000; export const REDUCED_POLLING_INTERVAL = 10 * 1000 * 6; @@ -35,15 +33,11 @@ export const hostRoles = (t: TFunction): HostRole[] => [ 'ai:Runs application workloads. Connect at least 5 hosts to enable dedicated workers.', ), }, - ...(isInOcm - ? [ - { - value: 'arbiter' as HostRoleUpdateParams, - label: t('ai:Arbiter'), - description: t('ai:Prevents split-brain scenarios and maintains quorum.'), - }, - ] - : []), + { + value: 'arbiter', + label: t('ai:Arbiter'), + description: t('ai:Prevents split-brain scenarios and maintains quorum.'), + }, ]; export const clusterStatusLabels = (t: TFunction): { [key in Cluster['status']]: string } => ({ diff --git a/libs/ui-lib/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx b/libs/ui-lib/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx index a867164809..ea988f35b1 100644 --- a/libs/ui-lib/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx +++ b/libs/ui-lib/lib/ocm/components/clusterConfiguration/ControlPlaneNodesDropdown.tsx @@ -17,7 +17,7 @@ import { useNewFeatureSupportLevel, } from '../../../common/components/newFeatureSupportLevels'; import { isFeatureSupportedAndAvailable } from '../featureSupportLevels/featureStateUtils'; -import OcmTNADisclaimer from './OcmTNADisclaimer'; +import OcmTNADisclaimer from '../../../common/components/clusterConfiguration/OcmTNADisclaimer'; import OcmSNODisclaimer from './OcmSNODisclaimer'; const INPUT_NAME = 'controlPlaneCount';