@openshift-assisted/ui-lib 2.47.5 → 2.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/build/@types/cim/components/ClusterDeployment/wizardTransition.d.ts +1 -1
  2. package/build/@types/cim/components/ClusterDeployment/wizardTransition.d.ts.map +1 -1
  3. package/build/@types/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.d.ts.map +1 -1
  4. package/build/@types/common/api/assisted-service/BundleAPI.d.ts +1 -1
  5. package/build/@types/common/api/assisted-service/BundleAPI.d.ts.map +1 -1
  6. package/build/@types/common/api/assisted-service/ClustersAPI.d.ts +4 -0
  7. package/build/@types/common/api/assisted-service/ClustersAPI.d.ts.map +1 -1
  8. package/build/@types/common/api/assisted-service/HostsAPI.d.ts +2 -1
  9. package/build/@types/common/api/assisted-service/HostsAPI.d.ts.map +1 -1
  10. package/build/@types/common/api/assisted-service/InfraEnvsAPI.d.ts +2 -1
  11. package/build/@types/common/api/assisted-service/InfraEnvsAPI.d.ts.map +1 -1
  12. package/build/@types/common/components/clusterWizard/ReviewValidations.d.ts.map +1 -1
  13. package/build/@types/common/components/operators/operatorDescriptions.d.ts +2 -0
  14. package/build/@types/common/components/operators/operatorDescriptions.d.ts.map +1 -1
  15. package/build/@types/common/components/operators/operatorSpecs.d.ts.map +1 -1
  16. package/build/@types/common/components/ui/formik/PullSecretField.d.ts.map +1 -1
  17. package/build/@types/common/config/constants.d.ts +8 -0
  18. package/build/@types/common/config/constants.d.ts.map +1 -1
  19. package/build/@types/common/config/docs_links.d.ts +2 -0
  20. package/build/@types/common/config/docs_links.d.ts.map +1 -1
  21. package/build/@types/common/reducers/alertsSlice.d.ts +1 -0
  22. package/build/@types/common/reducers/alertsSlice.d.ts.map +1 -1
  23. package/build/@types/ocm/components/HostsClusterDetailTab/utils.d.ts.map +1 -1
  24. package/build/@types/ocm/components/Routes.d.ts.map +1 -1
  25. package/build/@types/ocm/components/clusterConfiguration/operators/bundleSpecs.d.ts +0 -1
  26. package/build/@types/ocm/components/clusterConfiguration/operators/bundleSpecs.d.ts.map +1 -1
  27. package/build/@types/ocm/components/clusterConfiguration/operators/utils.d.ts.map +1 -1
  28. package/build/@types/ocm/components/clusterConfiguration/review/ReviewSummary.d.ts.map +1 -1
  29. package/build/@types/ocm/components/clusterWizard/ClusterDetails.d.ts.map +1 -1
  30. package/build/@types/ocm/components/clusterWizard/ClusterWizardContext.d.ts +3 -0
  31. package/build/@types/ocm/components/clusterWizard/ClusterWizardContext.d.ts.map +1 -1
  32. package/build/@types/ocm/components/clusterWizard/ClusterWizardContextProvider.d.ts.map +1 -1
  33. package/build/@types/ocm/components/clusterWizard/ClusterWizardFooter.d.ts +2 -1
  34. package/build/@types/ocm/components/clusterWizard/ClusterWizardFooter.d.ts.map +1 -1
  35. package/build/@types/ocm/components/clusterWizard/HostDiscovery.d.ts.map +1 -1
  36. package/build/@types/ocm/components/clusterWizard/NewClusterWizard.d.ts.map +1 -1
  37. package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts +2 -1
  38. package/build/@types/ocm/components/clusterWizard/OperatorsBundle.d.ts.map +1 -1
  39. package/build/@types/ocm/components/clusterWizard/OperatorsStep.d.ts.map +1 -1
  40. package/build/@types/ocm/components/clusterWizard/constants.d.ts.map +1 -1
  41. package/build/@types/ocm/components/clusterWizard/disconnected/BasicStep.d.ts.map +1 -1
  42. package/build/@types/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.d.ts +4 -0
  43. package/build/@types/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.d.ts.map +1 -0
  44. package/build/@types/ocm/components/clusterWizard/disconnected/ReviewStep.d.ts.map +1 -1
  45. package/build/@types/ocm/components/clusterWizard/index.d.ts +1 -0
  46. package/build/@types/ocm/components/clusterWizard/index.d.ts.map +1 -1
  47. package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts +2 -2
  48. package/build/@types/ocm/components/clusterWizard/wizardTransition.d.ts.map +1 -1
  49. package/build/@types/ocm/components/hosts/HostsDiscoveryTable.d.ts +3 -2
  50. package/build/@types/ocm/components/hosts/HostsDiscoveryTable.d.ts.map +1 -1
  51. package/build/@types/ocm/hooks/index.d.ts +1 -0
  52. package/build/@types/ocm/hooks/index.d.ts.map +1 -1
  53. package/build/@types/ocm/hooks/useInfraEnvHosts.d.ts +9 -0
  54. package/build/@types/ocm/hooks/useInfraEnvHosts.d.ts.map +1 -0
  55. package/build/@types/ocm/hooks/useInfraEnvId.d.ts.map +1 -1
  56. package/build/@types/ocm/hooks/useLateBinding.d.ts +4 -0
  57. package/build/@types/ocm/hooks/useLateBinding.d.ts.map +1 -0
  58. package/build/@types/ocm/services/BundleService.d.ts +1 -1
  59. package/build/@types/ocm/services/BundleService.d.ts.map +1 -1
  60. package/build/@types/ocm/services/ClustersService.d.ts +5 -1
  61. package/build/@types/ocm/services/ClustersService.d.ts.map +1 -1
  62. package/build/@types/ocm/services/HostsService.d.ts +2 -1
  63. package/build/@types/ocm/services/HostsService.d.ts.map +1 -1
  64. package/build/@types/ocm/services/InfraEnvsService.d.ts +1 -1
  65. package/build/@types/ocm/services/InfraEnvsService.d.ts.map +1 -1
  66. package/build/cjs/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.js +3 -1
  67. package/build/cjs/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.js.map +1 -1
  68. package/build/cjs/common/api/assisted-service/BundleAPI.js +4 -2
  69. package/build/cjs/common/api/assisted-service/BundleAPI.js.map +1 -1
  70. package/build/cjs/common/api/assisted-service/ClustersAPI.js +3 -0
  71. package/build/cjs/common/api/assisted-service/ClustersAPI.js.map +1 -1
  72. package/build/cjs/common/api/assisted-service/HostsAPI.js +8 -0
  73. package/build/cjs/common/api/assisted-service/HostsAPI.js.map +1 -1
  74. package/build/cjs/common/api/assisted-service/InfraEnvsAPI.js +5 -0
  75. package/build/cjs/common/api/assisted-service/InfraEnvsAPI.js.map +1 -1
  76. package/build/cjs/common/components/clusterWizard/ReviewValidations.js +2 -1
  77. package/build/cjs/common/components/clusterWizard/ReviewValidations.js.map +1 -1
  78. package/build/cjs/common/components/operators/operatorDescriptions.js +3 -1
  79. package/build/cjs/common/components/operators/operatorDescriptions.js.map +1 -1
  80. package/build/cjs/common/components/operators/operatorSpecs.js +24 -1
  81. package/build/cjs/common/components/operators/operatorSpecs.js.map +1 -1
  82. package/build/cjs/common/components/ui/WizardFooter.js +1 -1
  83. package/build/cjs/common/components/ui/WizardFooter.js.map +1 -1
  84. package/build/cjs/common/components/ui/formik/PullSecretField.js.map +1 -1
  85. package/build/cjs/common/config/constants.js +14 -2
  86. package/build/cjs/common/config/constants.js.map +1 -1
  87. package/build/cjs/common/config/docs_links.js +5 -1
  88. package/build/cjs/common/config/docs_links.js.map +1 -1
  89. package/build/cjs/common/reducers/alertsSlice.js +1 -1
  90. package/build/cjs/common/reducers/alertsSlice.js.map +1 -1
  91. package/build/cjs/ocm/components/HostsClusterDetailTab/utils.js +18 -11
  92. package/build/cjs/ocm/components/HostsClusterDetailTab/utils.js.map +1 -1
  93. package/build/cjs/ocm/components/Routes.js +2 -1
  94. package/build/cjs/ocm/components/Routes.js.map +1 -1
  95. package/build/cjs/ocm/components/clusterConfiguration/HostInventory.js +1 -1
  96. package/build/cjs/ocm/components/clusterConfiguration/HostInventory.js.map +1 -1
  97. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js +1 -1
  98. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js.map +1 -1
  99. package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js +0 -2
  100. package/build/cjs/ocm/components/clusterConfiguration/operators/bundleSpecs.js.map +1 -1
  101. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js +7 -4
  102. package/build/cjs/ocm/components/clusterConfiguration/operators/utils.js.map +1 -1
  103. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewCluster.css +2 -4
  104. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewPreflightChecks.js +1 -1
  105. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewPreflightChecks.js.map +1 -1
  106. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewSummary.js +2 -1
  107. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewSummary.js.map +1 -1
  108. package/build/cjs/ocm/components/clusterConfiguration/review/TableSummaryExpandable.js +1 -1
  109. package/build/cjs/ocm/components/clusterConfiguration/review/TableSummaryExpandable.js.map +1 -1
  110. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js +14 -3
  111. package/build/cjs/ocm/components/clusterWizard/ClusterDetails.js.map +1 -1
  112. package/build/cjs/ocm/components/clusterWizard/ClusterWizardContext.js.map +1 -1
  113. package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js +4 -0
  114. package/build/cjs/ocm/components/clusterWizard/ClusterWizardContextProvider.js.map +1 -1
  115. package/build/cjs/ocm/components/clusterWizard/ClusterWizardFooter.js +21 -6
  116. package/build/cjs/ocm/components/clusterWizard/ClusterWizardFooter.js.map +1 -1
  117. package/build/cjs/ocm/components/clusterWizard/HostDiscovery.js +3 -0
  118. package/build/cjs/ocm/components/clusterWizard/HostDiscovery.js.map +1 -1
  119. package/build/cjs/ocm/components/clusterWizard/NewClusterWizard.js +3 -0
  120. package/build/cjs/ocm/components/clusterWizard/NewClusterWizard.js.map +1 -1
  121. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js +9 -14
  122. package/build/cjs/ocm/components/clusterWizard/OperatorsBundle.js.map +1 -1
  123. package/build/cjs/ocm/components/clusterWizard/OperatorsStep.js +14 -3
  124. package/build/cjs/ocm/components/clusterWizard/OperatorsStep.js.map +1 -1
  125. package/build/cjs/ocm/components/clusterWizard/constants.js +1 -0
  126. package/build/cjs/ocm/components/clusterWizard/constants.js.map +1 -1
  127. package/build/cjs/ocm/components/clusterWizard/disconnected/BasicStep.js +45 -1
  128. package/build/cjs/ocm/components/clusterWizard/disconnected/BasicStep.js.map +1 -1
  129. package/build/cjs/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.js +128 -0
  130. package/build/cjs/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.js.map +1 -0
  131. package/build/cjs/ocm/components/clusterWizard/disconnected/ReviewStep.js +40 -5
  132. package/build/cjs/ocm/components/clusterWizard/disconnected/ReviewStep.js.map +1 -1
  133. package/build/cjs/ocm/components/clusterWizard/index.js +3 -1
  134. package/build/cjs/ocm/components/clusterWizard/index.js.map +1 -1
  135. package/build/cjs/ocm/components/clusterWizard/wizardTransition.js +3 -0
  136. package/build/cjs/ocm/components/clusterWizard/wizardTransition.js.map +1 -1
  137. package/build/cjs/ocm/components/hosts/HostsDiscoveryTable.js +1 -2
  138. package/build/cjs/ocm/components/hosts/HostsDiscoveryTable.js.map +1 -1
  139. package/build/cjs/ocm/hooks/index.js +3 -1
  140. package/build/cjs/ocm/hooks/index.js.map +1 -1
  141. package/build/cjs/ocm/hooks/useInfraEnvHosts.js +47 -0
  142. package/build/cjs/ocm/hooks/useInfraEnvHosts.js.map +1 -0
  143. package/build/cjs/ocm/hooks/useInfraEnvId.js +11 -2
  144. package/build/cjs/ocm/hooks/useInfraEnvId.js.map +1 -1
  145. package/build/cjs/ocm/hooks/useLateBinding.js +61 -0
  146. package/build/cjs/ocm/hooks/useLateBinding.js.map +1 -0
  147. package/build/cjs/ocm/services/BundleService.js +2 -2
  148. package/build/cjs/ocm/services/BundleService.js.map +1 -1
  149. package/build/cjs/ocm/services/ClustersService.js +10 -2
  150. package/build/cjs/ocm/services/ClustersService.js.map +1 -1
  151. package/build/cjs/ocm/services/HostsService.js +6 -0
  152. package/build/cjs/ocm/services/HostsService.js.map +1 -1
  153. package/build/cjs/ocm/services/InfraEnvsService.js +2 -2
  154. package/build/cjs/ocm/services/InfraEnvsService.js.map +1 -1
  155. package/lib/cim/components/InfraEnv/InfraEnvOpenShiftVersionDropdown.tsx +11 -9
  156. package/lib/common/api/assisted-service/BundleAPI.ts +15 -2
  157. package/lib/common/api/assisted-service/ClustersAPI.ts +6 -0
  158. package/lib/common/api/assisted-service/HostsAPI.ts +13 -0
  159. package/lib/common/api/assisted-service/InfraEnvsAPI.ts +6 -0
  160. package/lib/common/components/clusterWizard/ReviewValidations.tsx +4 -1
  161. package/lib/common/components/operators/operatorDescriptions.tsx +6 -0
  162. package/lib/common/components/operators/operatorSpecs.tsx +34 -1
  163. package/lib/common/components/ui/WizardFooter.tsx +1 -1
  164. package/lib/common/components/ui/formik/PullSecretField.tsx +1 -0
  165. package/lib/common/config/constants.ts +12 -0
  166. package/lib/common/config/docs_links.ts +10 -0
  167. package/lib/common/reducers/alertsSlice.ts +2 -1
  168. package/lib/ocm/components/HostsClusterDetailTab/utils.ts +30 -14
  169. package/lib/ocm/components/Routes.tsx +3 -1
  170. package/lib/ocm/components/clusterConfiguration/HostInventory.tsx +1 -1
  171. package/lib/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.tsx +1 -1
  172. package/lib/ocm/components/clusterConfiguration/operators/bundleSpecs.tsx +0 -3
  173. package/lib/ocm/components/clusterConfiguration/operators/utils.tsx +9 -5
  174. package/lib/ocm/components/clusterConfiguration/review/ReviewCluster.css +2 -4
  175. package/lib/ocm/components/clusterConfiguration/review/ReviewPreflightChecks.tsx +1 -1
  176. package/lib/ocm/components/clusterConfiguration/review/ReviewSummary.tsx +8 -2
  177. package/lib/ocm/components/clusterConfiguration/review/TableSummaryExpandable.tsx +2 -2
  178. package/lib/ocm/components/clusterWizard/ClusterDetails.tsx +23 -5
  179. package/lib/ocm/components/clusterWizard/ClusterWizardContext.tsx +3 -0
  180. package/lib/ocm/components/clusterWizard/ClusterWizardContextProvider.tsx +6 -0
  181. package/lib/ocm/components/clusterWizard/ClusterWizardFooter.tsx +26 -5
  182. package/lib/ocm/components/clusterWizard/HostDiscovery.tsx +3 -0
  183. package/lib/ocm/components/clusterWizard/NewClusterWizard.tsx +3 -0
  184. package/lib/ocm/components/clusterWizard/OperatorsBundle.tsx +6 -9
  185. package/lib/ocm/components/clusterWizard/OperatorsStep.tsx +22 -2
  186. package/lib/ocm/components/clusterWizard/constants.ts +1 -0
  187. package/lib/ocm/components/clusterWizard/disconnected/BasicStep.tsx +52 -1
  188. package/lib/ocm/components/clusterWizard/disconnected/OptionalConfigurationsStep.tsx +200 -0
  189. package/lib/ocm/components/clusterWizard/disconnected/ReviewStep.tsx +39 -7
  190. package/lib/ocm/components/clusterWizard/index.ts +1 -0
  191. package/lib/ocm/components/clusterWizard/wizardTransition.ts +5 -1
  192. package/lib/ocm/components/hosts/HostsDiscoveryTable.tsx +3 -2
  193. package/lib/ocm/hooks/index.ts +1 -0
  194. package/lib/ocm/hooks/useInfraEnvHosts.ts +60 -0
  195. package/lib/ocm/hooks/useInfraEnvId.ts +15 -2
  196. package/lib/ocm/hooks/useLateBinding.ts +71 -0
  197. package/lib/ocm/services/BundleService.ts +12 -2
  198. package/lib/ocm/services/ClustersService.ts +14 -2
  199. package/lib/ocm/services/HostsService.ts +9 -0
  200. package/lib/ocm/services/InfraEnvsService.ts +4 -1
  201. package/package.json +3 -3
@@ -6,6 +6,7 @@ export type AlertPayload = {
6
6
  title: string;
7
7
  message?: string;
8
8
  variant?: AlertVariant;
9
+ key?: string;
9
10
  };
10
11
 
11
12
  export type AlertProps = {
@@ -22,7 +23,7 @@ export const alertsSlice = createSlice({
22
23
  name: 'alerts',
23
24
  reducers: {
24
25
  addAlert: (state, action: PayloadAction<AlertPayload>) => [
25
- { key: uuidv4(), variant: AlertVariant.danger, ...action.payload },
26
+ { key: action.payload.key || uuidv4(), variant: AlertVariant.danger, ...action.payload },
26
27
  ...state,
27
28
  ],
28
29
  removeAlert: (state, action: PayloadAction<string>) =>
@@ -46,20 +46,36 @@ export const getAddHostsTabState = (cluster: OcmClusterType): AddHostsTabState =
46
46
  // Checking if the Day1 cluster has reported metrics, so it can be determined if it's an SNO / multi node and has required information
47
47
  const day1ClusterHostCount = cluster.metrics?.nodes?.total || 0;
48
48
 
49
- if (isClusterStateReady && wasInstalledUsingAssistedInstaller) {
50
- let tabState = makeState('visible');
51
- if (day1ClusterHostCount === 1 && !isSNOExpansionAllowed(cluster)) {
52
- // The cluster has metrics etc., but it's an SNO with an OpenshiftVersion that doesn't support Day2 flow
53
- tabState = makeState(
54
- 'disabled',
55
- 'OpenShift version not supported for SNO expansion. Hosts cannot be added to an existing SNO cluster that was installed with any OpenShift version older than 4.11. Upgrade to a newer OpenShift version and try again.',
56
- );
57
- }
49
+ // Disable Add Hosts with the following priority:
50
+ // 1) Cluster is not ready
51
+ // 2) Cluster was not installed using Assisted Installer
52
+ // 3) Cluster has no metrics
53
+ if (!isClusterStateReady) {
54
+ return makeState(
55
+ 'disabled',
56
+ 'Cluster is not ready. Please wait for the cluster to be ready and try again.',
57
+ );
58
+ } else if (!wasInstalledUsingAssistedInstaller) {
59
+ return makeState(
60
+ 'disabled',
61
+ 'Hosts cannot be added to an existing cluster that was not installed using Assisted Installer. Install a new cluster and try again.',
62
+ );
63
+ } else if (!cluster.metrics) {
64
+ return makeState(
65
+ 'disabled',
66
+ 'Cluster has no metrics. Please wait for the cluster to have metrics and try again.',
67
+ );
68
+ }
58
69
 
59
- return tabState;
60
- } else {
61
- // The cluster is not ready or was not installed using Assisted Installer.
62
- // (see: https://issues.redhat.com/browse/HAC-3989)
63
- return makeState('hidden');
70
+ // At this point the cluster is ready, installed using Assisted Installer, and has metrics
71
+ let tabState = makeState('visible');
72
+ if (day1ClusterHostCount === 1 && !isSNOExpansionAllowed(cluster)) {
73
+ // The cluster has metrics etc., but it's an SNO with an OpenshiftVersion that doesn't support Day2 flow
74
+ tabState = makeState(
75
+ 'disabled',
76
+ 'OpenShift version not supported for SNO expansion. Hosts cannot be added to an existing SNO cluster that was installed with any OpenShift version older than 4.11. Upgrade to a newer OpenShift version and try again.',
77
+ );
64
78
  }
79
+
80
+ return tabState;
65
81
  };
@@ -34,7 +34,9 @@ export const UILibRoutes = ({
34
34
  <>
35
35
  <Routes>
36
36
  <Route path="assisted-installer/clusters" element={<Outlet />}>
37
- <Route path="~new" element={<NewClusterPage />} />
37
+ <Route path="~new" element={<NewClusterPage />}>
38
+ <Route path=":clusterId" element={<NewClusterPage />} />
39
+ </Route>
38
40
  <Route path=":clusterId" element={<ClusterPage />} />
39
41
  <Route index element={<Clusters />} />
40
42
  </Route>
@@ -78,7 +78,7 @@ const HostInventory = ({ cluster }: { cluster: Cluster }) => {
78
78
  <Content component="h3">Host Inventory</Content>
79
79
  </StackItem>
80
80
  <StackItem data-testid="hosts-discovery-table-wrapper">
81
- <HostsDiscoveryTable cluster={cluster} />
81
+ <HostsDiscoveryTable cluster={cluster} hosts={cluster.hosts || []} />
82
82
  </StackItem>
83
83
  </Stack>
84
84
  );
@@ -92,7 +92,7 @@ const NetworkConfigurationForm: React.FC<{
92
92
  JSON.stringify(
93
93
  JSON.stringify({
94
94
  featureSet: 'CustomNoUpgrade',
95
- featureGates: ['NoRegistryClusterOperations=true'],
95
+ featureGates: ['NoRegistryClusterInstall=true'],
96
96
  }),
97
97
  ),
98
98
  );
@@ -2,7 +2,6 @@ import * as React from 'react';
2
2
  import { List, ListItem } from '@patternfly/react-core';
3
3
 
4
4
  export type BundleSpec = {
5
- noSNO?: boolean;
6
5
  incompatibleBundles?: string[];
7
6
  Description: React.ComponentType;
8
7
  docsLink?: string;
@@ -10,7 +9,6 @@ export type BundleSpec = {
10
9
 
11
10
  export const bundleSpecs: { [key: string]: BundleSpec } = {
12
11
  virtualization: {
13
- noSNO: true,
14
12
  Description: () => (
15
13
  <List>
16
14
  <ListItem>
@@ -29,7 +27,6 @@ export const bundleSpecs: { [key: string]: BundleSpec } = {
29
27
  ),
30
28
  },
31
29
  'openshift-ai': {
32
- noSNO: true,
33
30
  incompatibleBundles: [],
34
31
  Description: () => (
35
32
  <List>
@@ -40,13 +40,17 @@ export const getNewOperators = (
40
40
  }
41
41
 
42
42
  const newOperators = currentOperators.filter((op) => op !== operatorId);
43
- // uncheck unneeded not-standalone dependencies too
44
43
  const notStandaloneDeps = dependencies
45
44
  .filter((dep) => opSpecs[dep]?.notStandalone)
46
- .filter((dep) =>
47
- // some other operator may still depend on the not-standalone operator
48
- newOperators.every((op) => !getOperatorDependencies(op, preflightRequirements).includes(dep)),
49
- );
45
+ .filter((dep) => {
46
+ const hasDependency = newOperators.some((op) =>
47
+ getOperatorDependencies(op, preflightRequirements).includes(dep),
48
+ );
49
+ if (!hasDependency) {
50
+ newOperators.splice(newOperators.indexOf(dep), 1);
51
+ }
52
+ return !hasDependency;
53
+ });
50
54
 
51
55
  return currentOperators.filter((op) => op !== operatorId && !notStandaloneDeps.includes(op));
52
56
  };
@@ -18,14 +18,12 @@
18
18
  width: 100%;
19
19
  }
20
20
 
21
- .summary-expandable .pf-v6-c-expandable-section__toggle,
21
+ #summary-expandable > .pf-v6-c-expandable-section__toggle .pf-v6-c-button__text,
22
22
  .review-expandable > .pf-v6-c-expandable-section__toggle {
23
23
  color: initial;
24
24
  text-align: left;
25
25
  }
26
26
 
27
- .summary-expandable
28
- > .pf-v6-c-expandable-section__toggle
29
- > .pf-v6-c-expandable-section__toggle-icon {
27
+ #summary-expandable > .pf-v6-c-expandable-section__toggle .pf-v6-c-button__icon {
30
28
  visibility: hidden;
31
29
  }
@@ -182,7 +182,7 @@ const ReviewPreflightChecks = ({ cluster }: { cluster: Cluster }) => {
182
182
  <ExpandableSection
183
183
  toggleContent={
184
184
  <Grid>
185
- <GridItem span={2} className="pf-v6-u-text-wrap">
185
+ <GridItem span={2} className="pf-v6-u-text-wrap pf-v6-u-text-align-start">
186
186
  Preflight checks
187
187
  </GridItem>
188
188
  {!isChecksExpanded && <PreflightChecksDetailCollapsed cluster={cluster} />}
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { ExpandableSection } from '@patternfly/react-core';
2
3
  import {
3
4
  DetailItem,
4
5
  DetailList,
@@ -67,9 +68,14 @@ export const ReviewSummaryContent = ({ cluster }: { cluster: Cluster }) => {
67
68
 
68
69
  const ReviewSummary = ({ cluster }: { cluster: Cluster }) => {
69
70
  return (
70
- <TableSummaryExpandable title={'Cluster summary'} id={'summary-expandable'}>
71
+ <ExpandableSection
72
+ toggleContent={'Cluster summary'}
73
+ id={'summary-expandable'}
74
+ isExpanded={true}
75
+ isIndented
76
+ >
71
77
  <ReviewSummaryContent cluster={cluster} />
72
- </TableSummaryExpandable>
78
+ </ExpandableSection>
73
79
  );
74
80
  };
75
81
 
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { ExpandableSection } from '@patternfly/react-core';
2
+ import { ExpandableSection, Content } from '@patternfly/react-core';
3
3
 
4
4
  export const TableSummaryExpandable = ({
5
5
  title,
@@ -13,7 +13,7 @@ export const TableSummaryExpandable = ({
13
13
  const [isExpanded, setExpanded] = React.useState(true);
14
14
  return (
15
15
  <ExpandableSection
16
- toggleContent={<b>{title}</b>}
16
+ toggleContent={<Content className="pf-v6-u-font-weight-bold">{title}</Content>}
17
17
  isExpanded={isExpanded}
18
18
  onToggle={() => setExpanded(!isExpanded)}
19
19
  isIndented
@@ -25,6 +25,7 @@ import {
25
25
  } from '../../services';
26
26
  import { Cluster, InfraEnv } from '@openshift-assisted/types/assisted-installer-service';
27
27
  import BundleService from '../../services/BundleService';
28
+ import { useFeature } from '../../hooks/use-feature';
28
29
 
29
30
  type ClusterDetailsProps = {
30
31
  cluster?: Cluster;
@@ -45,6 +46,7 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => {
45
46
  latestVersions: versions,
46
47
  } = useOpenShiftVersionsContext();
47
48
  const location = useLocation();
49
+ const isSingleClusterFeatureEnabled = useFeature('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
48
50
 
49
51
  const handleClusterUpdate = React.useCallback(
50
52
  async (
@@ -85,16 +87,24 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => {
85
87
  //For Assisted Migration we need the LVMs operator and also the virtualization bundle operators
86
88
  if (isAssistedMigration) {
87
89
  params.olmOperators = [{ name: 'lvm' }];
88
- const selectedBundle = (await BundleService.listBundles()).find(
89
- (b) => b.id === 'virtualization',
90
- );
90
+ const selectedBundle = (
91
+ await BundleService.listBundles(
92
+ params.openshiftVersion,
93
+ params.cpuArchitecture,
94
+ params.platform?.type,
95
+ )
96
+ ).find((b) => b.id === 'virtualization');
91
97
  const virtOperators = selectedBundle?.operators;
92
98
  params.olmOperators = [
93
99
  ...params.olmOperators,
94
100
  ...(virtOperators ? virtOperators.map((op) => ({ name: op })) : []),
95
101
  ];
96
102
  }
97
- const cluster = await ClustersService.create(params, isAssistedMigration);
103
+ const cluster = await ClustersService.create(
104
+ params,
105
+ isAssistedMigration,
106
+ isSingleClusterFeatureEnabled,
107
+ );
98
108
  navigate(`../${cluster.id}`, { state: ClusterWizardFlowStateNew });
99
109
 
100
110
  const uiPatch: UISettingsValues = { addCustomManifests };
@@ -114,7 +124,15 @@ const ClusterDetails = ({ cluster, infraEnv }: ClusterDetailsProps) => {
114
124
  }
115
125
  }
116
126
  },
117
- [clearAlerts, location.search, navigate, clusterWizardContext, addAlert, dispatch],
127
+ [
128
+ clearAlerts,
129
+ location.search,
130
+ isSingleClusterFeatureEnabled,
131
+ navigate,
132
+ clusterWizardContext,
133
+ addAlert,
134
+ dispatch,
135
+ ],
118
136
  );
119
137
 
120
138
  const navigation = <ClusterWizardNavigation cluster={cluster} />;
@@ -3,6 +3,7 @@ import { HostsNetworkConfigurationType } from '../../services';
3
3
  import { StaticIpView } from '../clusterConfiguration/staticIp/data/dataTypes';
4
4
  import { ClusterWizardStepsType } from './wizardTransition';
5
5
  import { UISettingsValues } from '../../../common';
6
+ import { InfraEnv } from '@openshift-assisted/types/assisted-installer-service';
6
7
 
7
8
  export type ClusterWizardContextType = {
8
9
  currentStepId: ClusterWizardStepsType;
@@ -20,6 +21,8 @@ export type ClusterWizardContextType = {
20
21
  uiSettings?: UISettingsValues;
21
22
  installDisconnected: boolean;
22
23
  setInstallDisconnected: (enabled: boolean) => void;
24
+ disconnectedInfraEnv?: InfraEnv;
25
+ setDisconnectedInfraEnv: (infraEnv: InfraEnv | undefined) => void;
23
26
  };
24
27
 
25
28
  export const ClusterWizardContext = React.createContext<ClusterWizardContextType | null>(null);
@@ -92,6 +92,9 @@ const ClusterWizardContextProvider = ({
92
92
  const [wizardPerPage, setWizardPerPage] = React.useState(10);
93
93
  const [customManifestsStep, setCustomManifestsStep] = React.useState<boolean>(false);
94
94
  const [installDisconnected, setInstallDisconnected] = React.useState(false);
95
+ const [disconnectedInfraEnv, setDisconnectedInfraEnv] = React.useState<InfraEnv | undefined>(
96
+ infraEnv,
97
+ );
95
98
  const location = useLocation();
96
99
  const locationState = location.state as ClusterWizardFlowStateType | undefined;
97
100
  const {
@@ -259,6 +262,8 @@ const ClusterWizardContextProvider = ({
259
262
  connectedWizardStepIds?.length && onSetCurrentStepId(connectedWizardStepIds[0]);
260
263
  }
261
264
  },
265
+ disconnectedInfraEnv,
266
+ setDisconnectedInfraEnv,
262
267
  };
263
268
  }, [
264
269
  wizardStepIds,
@@ -273,6 +278,7 @@ const ClusterWizardContextProvider = ({
273
278
  installDisconnected,
274
279
  setInstallDisconnected,
275
280
  connectedWizardStepIds,
281
+ disconnectedInfraEnv,
276
282
  ]);
277
283
 
278
284
  if (!contextValue) {
@@ -17,6 +17,8 @@ import { onFetchEvents } from '../fetching/fetchEvents';
17
17
  import { Cluster } from '@openshift-assisted/types/assisted-installer-service';
18
18
  import { useFeature } from '../../hooks/use-feature';
19
19
  import { useModalDialogsContext } from '../hosts/ModalDialogsContext';
20
+ import ClustersService from '../../services/ClustersService';
21
+ import { handleApiError, getApiErrorMessage } from '../../../common/api';
20
22
 
21
23
  type ClusterValidationSectionProps = {
22
24
  cluster?: Cluster;
@@ -71,6 +73,7 @@ type ClusterWizardFooterProps = WizardFooterGenericProps & {
71
73
  errorFields?: string[];
72
74
  alertTitle?: string;
73
75
  alertContent?: string | null;
76
+ disconnectedClusterId?: string;
74
77
  };
75
78
 
76
79
  const ClusterWizardFooter = ({
@@ -80,19 +83,37 @@ const ClusterWizardFooter = ({
80
83
  alertTitle,
81
84
  alertContent,
82
85
  onCancel,
86
+ disconnectedClusterId,
83
87
  ...rest
84
88
  }: ClusterWizardFooterProps) => {
85
- const { alerts } = useAlerts();
89
+ const { alerts, addAlert } = useAlerts();
86
90
  const navigate = useNavigate();
87
91
  const isSingleClusterFeatureEnabled = useFeature('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
88
92
  const { currentStepId } = useClusterWizardContext();
89
93
  const { resetSingleClusterDialog } = useModalDialogsContext();
94
+ const { setDisconnectedInfraEnv } = useClusterWizardContext();
90
95
 
91
- const handleCancel = React.useCallback(() => navigate('/cluster-list'), [navigate]);
96
+ const handleCancel = React.useCallback(async () => {
97
+ if (disconnectedClusterId) {
98
+ try {
99
+ await ClustersService.remove(disconnectedClusterId);
100
+ } catch (e) {
101
+ handleApiError(e, () =>
102
+ addAlert({
103
+ title: 'Failed to remove cluster',
104
+ message: getApiErrorMessage(e),
105
+ }),
106
+ );
107
+ }
108
+ }
109
+ setDisconnectedInfraEnv(undefined);
110
+ navigate('/cluster-list');
111
+ }, [navigate, setDisconnectedInfraEnv, addAlert, disconnectedClusterId]);
92
112
 
93
- const handleReset = React.useCallback(() => {
94
- resetSingleClusterDialog.open({ cluster });
95
- }, [resetSingleClusterDialog, cluster]);
113
+ const handleReset = React.useCallback(
114
+ () => resetSingleClusterDialog.open({ cluster }),
115
+ [resetSingleClusterDialog, cluster],
116
+ );
96
117
 
97
118
  const alertsSection = alerts.length ? <Alerts /> : undefined;
98
119
 
@@ -22,6 +22,7 @@ import {
22
22
  Cluster,
23
23
  V2ClusterUpdateParams,
24
24
  } from '@openshift-assisted/types/assisted-installer-service';
25
+ import useLateBinding from '../../hooks/useLateBinding';
25
26
 
26
27
  const HostDiscoveryForm = ({ cluster }: { cluster: Cluster }) => {
27
28
  const { alerts } = useAlerts();
@@ -29,12 +30,14 @@ const HostDiscoveryForm = ({ cluster }: { cluster: Cluster }) => {
29
30
  const clusterWizardContext = useClusterWizardContext();
30
31
  const isAutoSaveRunning = useFormikAutoSave();
31
32
  const errorFields = getFormikErrorFields(errors, touched);
33
+ const isBinding = useLateBinding(cluster);
32
34
 
33
35
  const isNextDisabled =
34
36
  !isValid ||
35
37
  !!alerts.length ||
36
38
  isAutoSaveRunning ||
37
39
  isSubmitting ||
40
+ isBinding ||
38
41
  !canNextHostDiscovery({ cluster });
39
42
 
40
43
  const footer = (
@@ -4,6 +4,7 @@ import ClusterDetails from './ClusterDetails';
4
4
  import { useClusterWizardContext } from './ClusterWizardContext';
5
5
  import ReviewStep from './disconnected/ReviewStep';
6
6
  import BasicStep from './disconnected/BasicStep';
7
+ import OptionalConfigurationsStep from './disconnected/OptionalConfigurationsStep';
7
8
  import { ClusterWizardStepsType } from './wizardTransition';
8
9
 
9
10
  const getCurrentStep = (currentStepId: ClusterWizardStepsType) => {
@@ -12,6 +13,8 @@ const getCurrentStep = (currentStepId: ClusterWizardStepsType) => {
12
13
  return <ReviewStep />;
13
14
  case 'disconnected-basic':
14
15
  return <BasicStep />;
16
+ case 'disconnected-optional-configurations':
17
+ return <OptionalConfigurationsStep />;
15
18
  default:
16
19
  return <ClusterDetails />;
17
20
  }
@@ -21,8 +21,6 @@ import { ExternalLink, OperatorsValues, PopoverIcon, singleClusterBundles } from
21
21
  import { useFormikContext } from 'formik';
22
22
  import { useNewFeatureSupportLevel } from '../../../common/components/newFeatureSupportLevels';
23
23
  import { useFeature } from '../../hooks/use-feature';
24
- import { useSelector } from 'react-redux';
25
- import { selectIsCurrentClusterSNO } from '../../store/slices/current-cluster/selectors';
26
24
  import { getNewBundleOperators } from '../clusterConfiguration/operators/utils';
27
25
  import { bundleSpecs } from '../clusterConfiguration/operators/bundleSpecs';
28
26
  import {
@@ -84,7 +82,6 @@ const BundleCard = ({
84
82
  searchTerm?: string;
85
83
  }) => {
86
84
  const { values, setFieldValue } = useFormikContext<OperatorsValues>();
87
- const isSNO = useSelector(selectIsCurrentClusterSNO);
88
85
  const { isFeatureSupported } = useNewFeatureSupportLevel();
89
86
  const { byKey: opSpecs } = useOperatorSpecs();
90
87
  const { uiSettings } = useClusterWizardContext();
@@ -105,16 +102,14 @@ const BundleCard = ({
105
102
  const isAssistedMigration = uiSettings?.isAssistedMigration;
106
103
  const disabledReason = hasUnsupportedOperators
107
104
  ? 'Some operators in this bundle are not supported with the current configuration.'
108
- : isSNO && bundleSpec?.noSNO
109
- ? bundle.id === 'openshift-ai'
110
- ? 'This bundle is not available when deploying a Single Node OpenShift, but you can use the standalone operator instead.'
111
- : 'This bundle is not available when deploying a Single Node OpenShift.'
112
105
  : incompatibleBundle
113
106
  ? `Bundle cannot be installed together with ${
114
107
  bundles.find(({ id }) => id === incompatibleBundle)?.title || incompatibleBundle
115
108
  }`
116
109
  : isAssistedMigration
117
110
  ? 'This bundle needs to be selected for clusters created from Migration Assessment'
111
+ : !bundles.some((b) => b.id === bundle.id)
112
+ ? 'This bundle is not available for the current configuration, you might be able to use the standalone operators instead.'
118
113
  : undefined;
119
114
 
120
115
  const onSelect = (checked: boolean) => {
@@ -172,10 +167,12 @@ const BundleCard = ({
172
167
 
173
168
  const OperatorsBundle = ({
174
169
  bundles,
170
+ allBundles,
175
171
  preflightRequirements,
176
172
  searchTerm,
177
173
  }: {
178
174
  bundles: Bundle[];
175
+ allBundles: Bundle[];
179
176
  preflightRequirements: PreflightHardwareRequirements | undefined;
180
177
  searchTerm?: string;
181
178
  }) => {
@@ -191,8 +188,8 @@ const OperatorsBundle = ({
191
188
  <StackItem>
192
189
  <Gallery hasGutter minWidths={{ default: '350px' }}>
193
190
  {(isSingleClusterFeatureEnabled
194
- ? bundles.filter((b) => b.id && singleClusterBundles.includes(b.id))
195
- : bundles
191
+ ? allBundles.filter((b) => b.id && singleClusterBundles.includes(b.id))
192
+ : allBundles
196
193
  ).map((bundle) => (
197
194
  <GalleryItem key={bundle.id}>
198
195
  <BundleCard
@@ -18,13 +18,26 @@ export const OperatorsStep = ({ cluster }: ClusterOperatorProps) => {
18
18
  const { addAlert } = useAlerts();
19
19
  const [bundlesLoading, setBundlesLoading] = React.useState(true);
20
20
  const [bundles, setBundles] = React.useState<Bundle[]>([]);
21
+ const [allBundles, setAllBundles] = React.useState<Bundle[]>([]);
21
22
  const { preflightRequirements, isLoading } = useClusterPreflightRequirements(cluster.id);
22
23
  const [searchTerm, setSearchTerm] = React.useState('');
23
24
  React.useEffect(() => {
24
25
  const fetchBundles = async () => {
25
26
  try {
26
- const fetchedBundles = await BundleService.listBundles();
27
+ const fetchedBundles = await BundleService.listBundles(
28
+ cluster?.openshiftVersion || '',
29
+ cluster?.cpuArchitecture || '',
30
+ cluster?.platform?.type || '',
31
+ cluster?.controlPlaneCount === 1 ? 'SNO' : undefined,
32
+ );
33
+ const allBundles = await BundleService.listBundles(
34
+ cluster?.openshiftVersion || '',
35
+ cluster?.cpuArchitecture || '',
36
+ cluster?.platform?.type || '',
37
+ undefined,
38
+ );
27
39
  setBundles(fetchedBundles);
40
+ setAllBundles(allBundles);
28
41
  } catch (error) {
29
42
  handleApiError(error, () =>
30
43
  addAlert({
@@ -38,7 +51,13 @@ export const OperatorsStep = ({ cluster }: ClusterOperatorProps) => {
38
51
  };
39
52
 
40
53
  void fetchBundles();
41
- }, [addAlert]);
54
+ }, [
55
+ addAlert,
56
+ cluster.cpuArchitecture,
57
+ cluster.openshiftVersion,
58
+ cluster.platform?.type,
59
+ cluster.controlPlaneCount,
60
+ ]);
42
61
 
43
62
  const filteredBundles = bundles.filter(
44
63
  (bundle) =>
@@ -75,6 +94,7 @@ export const OperatorsStep = ({ cluster }: ClusterOperatorProps) => {
75
94
  bundles={filteredBundles}
76
95
  preflightRequirements={preflightRequirements}
77
96
  searchTerm={searchTerm}
97
+ allBundles={allBundles}
78
98
  />
79
99
  </StackItem>
80
100
  <StackItem>
@@ -14,6 +14,7 @@ export const wizardStepNames: { [key in ClusterWizardStepsType]: string } = {
14
14
  'credentials-download': 'Download credentials',
15
15
  'disconnected-review': 'Review and download ISO',
16
16
  'disconnected-basic': 'Basic information',
17
+ 'disconnected-optional-configurations': 'Optional configurations',
17
18
  };
18
19
 
19
20
  export const defaultWizardSteps: ClusterWizardStepsType[] = [
@@ -15,10 +15,53 @@ import ClusterWizardNavigation from '../ClusterWizardNavigation';
15
15
  import { WithErrorBoundary } from '../../../../common/components/ErrorHandling/WithErrorBoundary';
16
16
  import InstallDisconnectedSwitch from './InstallDisconnectedSwitch';
17
17
  import { Formik } from 'formik';
18
+ import ClustersService from '../../../services/ClustersService';
19
+ import { handleApiError, getApiErrorMessage } from '../../../../common/api';
20
+ import { useAlerts } from '../../../../common/components/AlertsContextProvider';
21
+ import { AlertVariant } from '@patternfly/react-core';
22
+ import { ClusterWizardFlowStateNew } from '../wizardTransition';
23
+ import { useLocation, useNavigate } from 'react-router-dom-v5-compat';
24
+ import { AxiosResponse } from 'axios';
25
+ import { Cluster } from '@openshift-assisted/types//assisted-installer-service';
18
26
 
19
27
  const BasicStep = () => {
20
28
  const { t } = useTranslation();
21
29
  const { moveNext } = useClusterWizardContext();
30
+ const { addAlert } = useAlerts();
31
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
32
+ const navigate = useNavigate();
33
+ const location = useLocation();
34
+ const currentPath = location.pathname;
35
+ let disconnectedClusterId: string | undefined;
36
+
37
+ const onNext = async () => {
38
+ try {
39
+ setIsSubmitting(true);
40
+ // Create cluster only - infraEnv will be created in OptionalConfigurationsStep
41
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
42
+ const { data: disconnectedCluster }: AxiosResponse<Cluster> =
43
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
44
+ await ClustersService.registerDisconnected({
45
+ name: 'disconnected-cluster',
46
+ openshiftVersion: '4.19',
47
+ });
48
+ disconnectedClusterId = disconnectedCluster.id;
49
+ navigate(`${currentPath}/${disconnectedClusterId}`, {
50
+ state: ClusterWizardFlowStateNew,
51
+ });
52
+ moveNext();
53
+ } catch (error: unknown) {
54
+ handleApiError(error, () => {
55
+ addAlert({
56
+ title: 'Failed to create disconnected cluster',
57
+ message: getApiErrorMessage(error),
58
+ variant: AlertVariant.danger,
59
+ });
60
+ });
61
+ } finally {
62
+ setIsSubmitting(false);
63
+ }
64
+ };
22
65
 
23
66
  return (
24
67
  <Formik
@@ -29,7 +72,15 @@ const BasicStep = () => {
29
72
  >
30
73
  <ClusterWizardStep
31
74
  navigation={<ClusterWizardNavigation />}
32
- footer={<ClusterWizardFooter onNext={moveNext} />}
75
+ footer={
76
+ <ClusterWizardFooter
77
+ onNext={() => {
78
+ void onNext();
79
+ }}
80
+ isSubmitting={isSubmitting}
81
+ disconnectedClusterId={disconnectedClusterId}
82
+ />
83
+ }
33
84
  >
34
85
  <WithErrorBoundary title="Failed to load Basic step">
35
86
  <Grid hasGutter>