@openshift-assisted/ui-lib 2.18.0-cim → 2.18.2-cim

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 (138) hide show
  1. package/build/@types/cim/components/ClusterDeployment/NetworkConfiguration.d.ts +1 -1
  2. package/build/@types/cim/components/ClusterDeployment/NetworkConfiguration.d.ts.map +1 -1
  3. package/build/@types/cim/components/ClusterDeployment/customManifests/ClusterDeploymentCustomManifestsStep.d.ts.map +1 -1
  4. package/build/@types/cim/components/ClusterDeployment/networkConfigurationValidation.d.ts +1 -1
  5. package/build/@types/cim/components/ClusterDeployment/networkConfigurationValidation.d.ts.map +1 -1
  6. package/build/@types/cim/components/ClusterDeployment/networking/NetworkTypeDropdown.d.ts +5 -0
  7. package/build/@types/cim/components/ClusterDeployment/networking/NetworkTypeDropdown.d.ts.map +1 -0
  8. package/build/@types/cim/components/ClusterDeployment/use-networking-formik.d.ts +4 -4
  9. package/build/@types/cim/components/ClusterDeployment/use-networking-formik.d.ts.map +1 -1
  10. package/build/@types/cim/components/featureSupportLevels/ACMFeatureSupportLevelProvider.d.ts.map +1 -1
  11. package/build/@types/cim/components/helpers/versions.d.ts +2 -2
  12. package/build/@types/cim/components/helpers/versions.d.ts.map +1 -1
  13. package/build/@types/cim/components/helpers/versions.test.d.ts +2 -0
  14. package/build/@types/cim/components/helpers/versions.test.d.ts.map +1 -0
  15. package/build/@types/cim/components/modals/CimConfiguration/CimConfigurationModal.d.ts.map +1 -1
  16. package/build/@types/cim/components/modals/CimConfiguration/persist.d.ts +14 -17
  17. package/build/@types/cim/components/modals/CimConfiguration/persist.d.ts.map +1 -1
  18. package/build/@types/cim/types/k8s/agent-cluster-install.d.ts +1 -1
  19. package/build/@types/cim/types/k8s/agent-cluster-install.d.ts.map +1 -1
  20. package/build/@types/common/components/clusterWizard/customManifests/CustomManifestsAlert.d.ts +6 -0
  21. package/build/@types/common/components/clusterWizard/customManifests/CustomManifestsAlert.d.ts.map +1 -0
  22. package/build/@types/common/components/clusterWizard/customManifests/index.d.ts +2 -0
  23. package/build/@types/common/components/clusterWizard/customManifests/index.d.ts.map +1 -0
  24. package/build/@types/common/components/clusterWizard/index.d.ts +2 -0
  25. package/build/@types/common/components/clusterWizard/index.d.ts.map +1 -1
  26. package/build/@types/common/components/clusterWizard/networkingSteps/AvailableSubnetsControl.d.ts +2 -1
  27. package/build/@types/common/components/clusterWizard/networkingSteps/AvailableSubnetsControl.d.ts.map +1 -1
  28. package/build/@types/common/components/clusterWizard/networkingSteps/StackTypeControlGroup.d.ts +2 -1
  29. package/build/@types/common/components/clusterWizard/networkingSteps/StackTypeControlGroup.d.ts.map +1 -1
  30. package/build/@types/common/components/clusterWizard/networkingSteps/ThirdPartyCNIBanner.d.ts +3 -0
  31. package/build/@types/common/components/clusterWizard/networkingSteps/ThirdPartyCNIBanner.d.ts.map +1 -0
  32. package/build/@types/common/components/clusterWizard/networkingSteps/index.d.ts +1 -0
  33. package/build/@types/common/components/clusterWizard/networkingSteps/index.d.ts.map +1 -1
  34. package/build/@types/common/components/ui/formik/utils.d.ts +1 -0
  35. package/build/@types/common/components/ui/formik/utils.d.ts.map +1 -1
  36. package/build/@types/common/config/constants.d.ts +2 -2
  37. package/build/@types/common/config/constants.d.ts.map +1 -1
  38. package/build/@types/common/types/networkType.d.ts +2 -1
  39. package/build/@types/common/types/networkType.d.ts.map +1 -1
  40. package/build/@types/common/validationSchemas/networkingValidation.d.ts +10 -0
  41. package/build/@types/common/validationSchemas/networkingValidation.d.ts.map +1 -1
  42. package/build/@types/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.d.ts.map +1 -1
  43. package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/NetworkTypeDropdown.d.ts.map +1 -1
  44. package/build/@types/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.d.ts.map +1 -1
  45. package/build/@types/ocm/components/clusterConfiguration/review/ReviewNetworkingTable.d.ts.map +1 -1
  46. package/build/@types/ocm/components/clusterDetail/ClusterProperties.d.ts +2 -1
  47. package/build/@types/ocm/components/clusterDetail/ClusterProperties.d.ts.map +1 -1
  48. package/build/cjs/cim/components/ClusterDeployment/NetworkConfiguration.js +46 -7
  49. package/build/cjs/cim/components/ClusterDeployment/NetworkConfiguration.js.map +1 -1
  50. package/build/cjs/cim/components/ClusterDeployment/customManifests/ClusterDeploymentCustomManifestsStep.js +24 -23
  51. package/build/cjs/cim/components/ClusterDeployment/customManifests/ClusterDeploymentCustomManifestsStep.js.map +1 -1
  52. package/build/cjs/cim/components/ClusterDeployment/networkConfigurationValidation.js +25 -9
  53. package/build/cjs/cim/components/ClusterDeployment/networkConfigurationValidation.js.map +1 -1
  54. package/build/cjs/cim/components/ClusterDeployment/networking/NetworkTypeDropdown.js +35 -0
  55. package/build/cjs/cim/components/ClusterDeployment/networking/NetworkTypeDropdown.js.map +1 -0
  56. package/build/cjs/cim/components/ClusterDeployment/use-networking-formik.js +13 -18
  57. package/build/cjs/cim/components/ClusterDeployment/use-networking-formik.js.map +1 -1
  58. package/build/cjs/cim/components/Hypershift/modals/NodePoolForm.js +1 -1
  59. package/build/cjs/cim/components/Hypershift/modals/NodePoolForm.js.map +1 -1
  60. package/build/cjs/cim/components/featureSupportLevels/ACMFeatureSupportLevelProvider.js +1 -4
  61. package/build/cjs/cim/components/featureSupportLevels/ACMFeatureSupportLevelProvider.js.map +1 -1
  62. package/build/cjs/cim/components/helpers/versions.js +39 -28
  63. package/build/cjs/cim/components/helpers/versions.js.map +1 -1
  64. package/build/cjs/cim/components/helpers/versions.test.js +423 -0
  65. package/build/cjs/cim/components/helpers/versions.test.js.map +1 -0
  66. package/build/cjs/cim/components/modals/CimConfiguration/CimConfigurationModal.js +39 -16
  67. package/build/cjs/cim/components/modals/CimConfiguration/CimConfigurationModal.js.map +1 -1
  68. package/build/cjs/cim/components/modals/CimConfiguration/persist.js +95 -135
  69. package/build/cjs/cim/components/modals/CimConfiguration/persist.js.map +1 -1
  70. package/build/cjs/common/components/clusterWizard/customManifests/CustomManifestsAlert.js +32 -0
  71. package/build/cjs/common/components/clusterWizard/customManifests/CustomManifestsAlert.js.map +1 -0
  72. package/build/cjs/common/components/clusterWizard/customManifests/index.js +5 -0
  73. package/build/cjs/common/components/clusterWizard/customManifests/index.js.map +1 -0
  74. package/build/cjs/common/components/clusterWizard/index.js +2 -0
  75. package/build/cjs/common/components/clusterWizard/index.js.map +1 -1
  76. package/build/cjs/common/components/clusterWizard/networkingSteps/AvailableSubnetsControl.js +8 -2
  77. package/build/cjs/common/components/clusterWizard/networkingSteps/AvailableSubnetsControl.js.map +1 -1
  78. package/build/cjs/common/components/clusterWizard/networkingSteps/StackTypeControlGroup.js +29 -19
  79. package/build/cjs/common/components/clusterWizard/networkingSteps/StackTypeControlGroup.js.map +1 -1
  80. package/build/cjs/common/components/clusterWizard/networkingSteps/ThirdPartyCNIBanner.js +20 -0
  81. package/build/cjs/common/components/clusterWizard/networkingSteps/ThirdPartyCNIBanner.js.map +1 -0
  82. package/build/cjs/common/components/clusterWizard/networkingSteps/index.js +3 -4
  83. package/build/cjs/common/components/clusterWizard/networkingSteps/index.js.map +1 -1
  84. package/build/cjs/common/components/ui/formik/utils.js +5 -1
  85. package/build/cjs/common/components/ui/formik/utils.js.map +1 -1
  86. package/build/cjs/common/config/constants.js +9 -2
  87. package/build/cjs/common/config/constants.js.map +1 -1
  88. package/build/cjs/common/types/networkType.js +9 -8
  89. package/build/cjs/common/types/networkType.js.map +1 -1
  90. package/build/cjs/common/validationSchemas/networkingValidation.js +19 -1
  91. package/build/cjs/common/validationSchemas/networkingValidation.js.map +1 -1
  92. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.js +1 -20
  93. package/build/cjs/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.js.map +1 -1
  94. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js +1 -1
  95. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.js.map +1 -1
  96. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkTypeDropdown.js +6 -9
  97. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/NetworkTypeDropdown.js.map +1 -1
  98. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.js +4 -4
  99. package/build/cjs/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.js.map +1 -1
  100. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewNetworkingTable.js +3 -2
  101. package/build/cjs/ocm/components/clusterConfiguration/review/ReviewNetworkingTable.js.map +1 -1
  102. package/build/cjs/ocm/components/clusterDetail/ClusterProperties.js +3 -3
  103. package/build/cjs/ocm/components/clusterDetail/ClusterProperties.js.map +1 -1
  104. package/lib/cim/components/ClusterDeployment/NetworkConfiguration.tsx +55 -6
  105. package/lib/cim/components/ClusterDeployment/customManifests/ClusterDeploymentCustomManifestsStep.tsx +18 -2
  106. package/lib/cim/components/ClusterDeployment/networkConfigurationValidation.ts +22 -8
  107. package/lib/cim/components/ClusterDeployment/networking/NetworkTypeDropdown.tsx +81 -0
  108. package/lib/cim/components/ClusterDeployment/use-networking-formik.ts +14 -22
  109. package/lib/cim/components/Hypershift/modals/NodePoolForm.tsx +2 -2
  110. package/lib/cim/components/featureSupportLevels/ACMFeatureSupportLevelProvider.tsx +2 -5
  111. package/lib/cim/components/helpers/versions.test.ts +465 -0
  112. package/lib/cim/components/helpers/versions.ts +37 -31
  113. package/lib/cim/components/modals/CimConfiguration/CimConfigurationModal.tsx +45 -18
  114. package/lib/cim/components/modals/CimConfiguration/persist.ts +97 -199
  115. package/lib/cim/types/k8s/agent-cluster-install.ts +1 -1
  116. package/lib/common/components/clusterWizard/customManifests/CustomManifestsAlert.tsx +39 -0
  117. package/lib/common/components/clusterWizard/customManifests/index.tsx +1 -0
  118. package/lib/common/components/clusterWizard/index.ts +2 -0
  119. package/lib/common/components/clusterWizard/networkingSteps/AvailableSubnetsControl.tsx +8 -1
  120. package/lib/common/components/clusterWizard/networkingSteps/StackTypeControlGroup.tsx +36 -26
  121. package/lib/common/components/clusterWizard/networkingSteps/ThirdPartyCNIBanner.tsx +28 -0
  122. package/lib/common/components/clusterWizard/networkingSteps/index.ts +1 -0
  123. package/lib/common/components/ui/formik/utils.ts +6 -0
  124. package/lib/common/config/constants.ts +10 -1
  125. package/lib/common/types/networkType.ts +9 -8
  126. package/lib/common/validationSchemas/networkingValidation.tsx +39 -1
  127. package/lib/ocm/components/clusterConfiguration/manifestsConfiguration/CustomManifestsPage.tsx +10 -45
  128. package/lib/ocm/components/clusterConfiguration/networkConfiguration/NetworkConfigurationForm.tsx +2 -2
  129. package/lib/ocm/components/clusterConfiguration/networkConfiguration/NetworkTypeDropdown.tsx +7 -24
  130. package/lib/ocm/components/clusterConfiguration/networkConfiguration/networkConfigurationValidation.ts +6 -5
  131. package/lib/ocm/components/clusterConfiguration/review/ReviewNetworkingTable.tsx +9 -3
  132. package/lib/ocm/components/clusterDetail/ClusterProperties.tsx +7 -3
  133. package/package.json +3 -3
  134. package/build/@types/common/components/clusterWizard/networkingSteps/NetworkTypeControlGroup.d.ts +0 -7
  135. package/build/@types/common/components/clusterWizard/networkingSteps/NetworkTypeControlGroup.d.ts.map +0 -1
  136. package/build/cjs/common/components/clusterWizard/networkingSteps/NetworkTypeControlGroup.js +0 -33
  137. package/build/cjs/common/components/clusterWizard/networkingSteps/NetworkTypeControlGroup.js.map +0 -1
  138. package/lib/common/components/clusterWizard/networkingSteps/NetworkTypeControlGroup.tsx +0 -74
@@ -0,0 +1,465 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { CpuArchitecture } from '../../../common/types/cpuArchitecture';
3
+ import { ClusterImageSetK8sResource } from '../../types/k8s/cluster-image-set';
4
+ import { AgentClusterInstallK8sResource } from '../../types/k8s/agent-cluster-install';
5
+ import { ClusterVersionK8sResource } from '../../types/k8s/cluster-version';
6
+ import { OsImage } from '../../types/k8s/agent-service-config';
7
+ import {
8
+ getCurrentClusterVersion,
9
+ getNetworkType,
10
+ getOCPVersions,
11
+ getSelectedVersion,
12
+ getVersionFromClusterImageSet,
13
+ } from './versions';
14
+ import { OpenshiftVersionOptionType } from '../../../common/types/versions';
15
+
16
+ const ClusterImageSetApiVersion = 'hive.openshift.io/v1';
17
+ const ClusterImageSetKind = 'ClusterImageSet';
18
+
19
+ function makeClusterImageSet(
20
+ overrides: Partial<ClusterImageSetK8sResource> & {
21
+ metadata: NonNullable<ClusterImageSetK8sResource['metadata']>;
22
+ },
23
+ ): ClusterImageSetK8sResource {
24
+ return {
25
+ apiVersion: ClusterImageSetApiVersion,
26
+ kind: ClusterImageSetKind,
27
+ ...overrides,
28
+ };
29
+ }
30
+
31
+ function makeOsImage(overrides: Partial<OsImage> & Pick<OsImage, 'openshiftVersion'>): OsImage {
32
+ const { openshiftVersion, ...rest } = overrides;
33
+ return {
34
+ cpuArchitecture: 'x86_64',
35
+ openshiftVersion,
36
+ url: 'https://example.com',
37
+ version: '1',
38
+ ...rest,
39
+ };
40
+ }
41
+
42
+ describe('getVersionFromClusterImageSet', () => {
43
+ test('uses releaseTag when releaseImage is digest-only', () => {
44
+ const cis = makeClusterImageSet({
45
+ metadata: {
46
+ name: 'img4.21.3-multi-appsub',
47
+ labels: { visible: 'true', releaseTag: '4.21.3-multi' },
48
+ },
49
+ spec: {
50
+ releaseImage: 'quay.io/openshift-release-dev/ocp-release@sha256:abc123',
51
+ },
52
+ });
53
+ expect(getVersionFromClusterImageSet(cis)).toBe('4.21.3-multi');
54
+ });
55
+
56
+ test('falls back to releaseImage when releaseTag is absent', () => {
57
+ const cis = makeClusterImageSet({
58
+ metadata: { name: 'img4.15.36-multi-appsub', labels: { visible: 'true' } },
59
+ spec: {
60
+ releaseImage: 'quay.io/openshift-release-dev/ocp-release:4.15.36-multi',
61
+ },
62
+ });
63
+ expect(getVersionFromClusterImageSet(cis)).toBe('4.15.36-multi');
64
+ });
65
+
66
+ test('falls back to metadata.name when tag and image do not parse', () => {
67
+ const cis = makeClusterImageSet({
68
+ metadata: {
69
+ name: 'img4.18.10-multi-appsub',
70
+ labels: { visible: 'true' },
71
+ },
72
+ spec: {
73
+ releaseImage: 'quay.io/openshift-release-dev/ocp-release@sha256:abc123',
74
+ },
75
+ });
76
+ expect(getVersionFromClusterImageSet(cis)).toBe('img4.18.10-multi-appsub');
77
+ });
78
+ });
79
+
80
+ describe('getOCPVersions', () => {
81
+ test('excludes image sets without visible true when extended is false', () => {
82
+ const hidden = makeClusterImageSet({
83
+ metadata: {
84
+ name: '4.16.1',
85
+ labels: { visible: 'false', releaseTag: '4.16.1' },
86
+ },
87
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.1-x86_64' },
88
+ });
89
+ expect(getOCPVersions([hidden])).toEqual([]);
90
+ });
91
+
92
+ test('includes image sets without visible true when extended is true', () => {
93
+ const hidden = makeClusterImageSet({
94
+ metadata: {
95
+ name: '4.16.2',
96
+ labels: { releaseTag: '4.16.2' },
97
+ },
98
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.2-x86_64' },
99
+ });
100
+ const result = getOCPVersions([hidden], undefined, undefined, true);
101
+ expect(result).toHaveLength(1);
102
+ expect(result[0]?.version).toBe('4.16.2');
103
+ expect(result[0]?.default).toBe(true);
104
+ });
105
+
106
+ test('sorts by label descending', () => {
107
+ const a = makeClusterImageSet({
108
+ metadata: {
109
+ name: 'img-a',
110
+ labels: { visible: 'true', releaseTag: '4.15.0' },
111
+ },
112
+ spec: { releaseImage: 'quay.io/ocp/release:4.15.0-x86_64' },
113
+ });
114
+ const b = makeClusterImageSet({
115
+ metadata: {
116
+ name: 'img-b',
117
+ labels: { visible: 'true', releaseTag: '4.21.0' },
118
+ },
119
+ spec: { releaseImage: 'quay.io/ocp/release:4.21.0-x86_64' },
120
+ });
121
+ const result = getOCPVersions([a, b]);
122
+ expect(result.map((v) => v.version)).toEqual(['4.21.0', '4.15.0']);
123
+ });
124
+
125
+ test('marks only the first sorted option as default', () => {
126
+ const first = makeClusterImageSet({
127
+ metadata: {
128
+ name: 'first',
129
+ labels: { visible: 'true', releaseTag: '4.14.0' },
130
+ },
131
+ spec: { releaseImage: 'quay.io/ocp/release:4.14.0-x86_64' },
132
+ });
133
+ const second = makeClusterImageSet({
134
+ metadata: {
135
+ name: 'second',
136
+ labels: { visible: 'true', releaseTag: '4.16.0' },
137
+ },
138
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.0-x86_64' },
139
+ });
140
+ const result = getOCPVersions([first, second]);
141
+ expect(result[0]?.default).toBe(true);
142
+ expect(result[1]?.default).toBe(false);
143
+ });
144
+
145
+ test('dedupes by version string keeping first in sorted order', () => {
146
+ const dupA = makeClusterImageSet({
147
+ metadata: {
148
+ name: 'dup-a',
149
+ labels: { visible: 'true', releaseTag: '4.17.0' },
150
+ },
151
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-x86_64' },
152
+ });
153
+ const dupB = makeClusterImageSet({
154
+ metadata: {
155
+ name: 'dup-b',
156
+ labels: { visible: 'true', releaseTag: '4.17.0' },
157
+ },
158
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-x86_64' },
159
+ });
160
+ const other = makeClusterImageSet({
161
+ metadata: {
162
+ name: 'other',
163
+ labels: { visible: 'true', releaseTag: '4.16.0' },
164
+ },
165
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.0-x86_64' },
166
+ });
167
+ const result = getOCPVersions([dupA, dupB, other]);
168
+ expect(result.map((v) => v.value)).toEqual(['dup-a', 'other']);
169
+ expect(result.map((v) => v.version)).toEqual(['4.17.0', '4.16.0']);
170
+ });
171
+
172
+ test('when isNutanix, keeps only x86_64 or x86-64 release images or matching architecture label', () => {
173
+ const x86 = makeClusterImageSet({
174
+ metadata: {
175
+ name: 'nut-x86',
176
+ labels: { visible: 'true', releaseTag: '4.16.0' },
177
+ },
178
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.0-x86_64' },
179
+ });
180
+ const multi = makeClusterImageSet({
181
+ metadata: {
182
+ name: 'nut-multi',
183
+ labels: { visible: 'true', releaseTag: '4.16.1-mutli', architecture: 'multi' },
184
+ },
185
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.1-multi' },
186
+ });
187
+ const result = getOCPVersions([x86, multi], true);
188
+ expect(result.map((v) => v.value)).toEqual(['nut-x86']);
189
+ });
190
+
191
+ test('when isNutanix, allows architecture label x86_64 even if release image suffix differs', () => {
192
+ const cis = makeClusterImageSet({
193
+ metadata: {
194
+ name: 'nut-label',
195
+ labels: { visible: 'true', releaseTag: '4.16.2-multi', architecture: 'x86_64' },
196
+ },
197
+ spec: { releaseImage: 'quay.io/ocp/release:4.16.2-multi' },
198
+ });
199
+ const result = getOCPVersions([cis], true);
200
+ expect(result).toHaveLength(1);
201
+ expect(result[0]?.value).toBe('nut-label');
202
+ });
203
+
204
+ test('filters by osImages openshiftVersion major.minor', () => {
205
+ const inRange = makeClusterImageSet({
206
+ metadata: {
207
+ name: 'in',
208
+ labels: { visible: 'true', releaseTag: '4.18.55' },
209
+ },
210
+ spec: { releaseImage: 'quay.io/ocp/release:4.18.55-x86_64' },
211
+ });
212
+ const outRange = makeClusterImageSet({
213
+ metadata: {
214
+ name: 'out',
215
+ labels: { visible: 'true', releaseTag: '4.19.0' },
216
+ },
217
+ spec: { releaseImage: 'quay.io/ocp/release:4.19.0-x86_64' },
218
+ });
219
+ const osImages = [makeOsImage({ openshiftVersion: '4.18' })];
220
+ const result = getOCPVersions([inRange, outRange], false, osImages);
221
+ expect(result.map((v) => v.value)).toEqual(['in']);
222
+ });
223
+
224
+ test('cpuArchitectures from labels.architecture x86_64', () => {
225
+ const cis = makeClusterImageSet({
226
+ metadata: {
227
+ name: 'arch-x86',
228
+ labels: { visible: 'true', releaseTag: '4.17.0-multi', architecture: 'x86_64' },
229
+ },
230
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-multi' },
231
+ });
232
+ const result = getOCPVersions([cis]);
233
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.x86]);
234
+ });
235
+
236
+ test('cpuArchitectures from labels.architecture arm64', () => {
237
+ const cis = makeClusterImageSet({
238
+ metadata: {
239
+ name: 'arch-arm',
240
+ labels: { visible: 'true', releaseTag: '4.17.0-multi', architecture: 'arm64' },
241
+ },
242
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-multi' },
243
+ });
244
+ const result = getOCPVersions([cis]);
245
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.ARM]);
246
+ });
247
+
248
+ test('cpuArchitectures from labels.architecture multi', () => {
249
+ const cis = makeClusterImageSet({
250
+ metadata: {
251
+ name: 'arch-multi',
252
+ labels: { visible: 'true', releaseTag: '4.17.0-multi', architecture: 'multi' },
253
+ },
254
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-multi' },
255
+ });
256
+ const result = getOCPVersions([cis]);
257
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.MULTI]);
258
+ });
259
+
260
+ test('cpuArchitectures from labels.architecture s390x', () => {
261
+ const cis = makeClusterImageSet({
262
+ metadata: {
263
+ name: 'arch-s390x',
264
+ labels: { visible: 'true', releaseTag: '4.17.0-multi', architecture: 's390x' },
265
+ },
266
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0-multi' },
267
+ });
268
+ const result = getOCPVersions([cis]);
269
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.s390x]);
270
+ });
271
+
272
+ test('cpuArchitectures normalizes x86-64 from release string when tag and image agree', () => {
273
+ const cis = makeClusterImageSet({
274
+ metadata: {
275
+ name: 'img4.17.1-x86-64-appsub',
276
+ labels: {
277
+ visible: 'true',
278
+ releaseTag: '4.17.1-x86-64',
279
+ },
280
+ },
281
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.1-x86-64' },
282
+ });
283
+ const result = getOCPVersions([cis]);
284
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.x86]);
285
+ });
286
+
287
+ test('labels.architecture takes precedence over releaseTag arch segment', () => {
288
+ const cis = makeClusterImageSet({
289
+ metadata: {
290
+ name: 'prec',
291
+ labels: {
292
+ visible: 'true',
293
+ releaseTag: '4.19.0-multi',
294
+ architecture: 'x86_64',
295
+ },
296
+ },
297
+ spec: { releaseImage: 'quay.io/ocp/release:4.19.0-multi' },
298
+ });
299
+ const result = getOCPVersions([cis]);
300
+ expect(result[0]?.cpuArchitectures).toEqual([CpuArchitecture.x86]);
301
+ });
302
+
303
+ test('cpuArchitectures undefined when no arch in labels or release strings', () => {
304
+ const cis = makeClusterImageSet({
305
+ metadata: {
306
+ name: 'ocp-release4.17.0',
307
+ labels: { visible: 'true', releaseTag: '4.17.0' },
308
+ },
309
+ spec: { releaseImage: 'quay.io/ocp/release:4.17.0' },
310
+ });
311
+ const result = getOCPVersions([cis]);
312
+ expect(result[0]?.cpuArchitectures).toBeUndefined();
313
+ });
314
+ });
315
+
316
+ describe('getSelectedVersion', () => {
317
+ test('returns parsed version when cluster image matches imageSetRef', () => {
318
+ const cis = makeClusterImageSet({
319
+ metadata: {
320
+ name: 'my-imageset',
321
+ labels: { visible: 'true', releaseTag: '4.18.10' },
322
+ },
323
+ spec: { releaseImage: 'quay.io/ocp/release:4.18.10-x86_64' },
324
+ });
325
+ const aci = {
326
+ apiVersion: 'extensions.hive.openshift.io/v1beta1',
327
+ kind: 'AgentClusterInstall',
328
+ metadata: { name: 'aci', namespace: 'ns' },
329
+ spec: { imageSetRef: { name: 'my-imageset' } },
330
+ } as AgentClusterInstallK8sResource;
331
+ expect(getSelectedVersion([cis], aci)).toBe('4.18.10');
332
+ });
333
+
334
+ test('returns imageSetRef name when no cluster image matches', () => {
335
+ const aci = {
336
+ apiVersion: 'extensions.hive.openshift.io/v1beta1',
337
+ kind: 'AgentClusterInstall',
338
+ metadata: { name: 'aci', namespace: 'ns' },
339
+ spec: { imageSetRef: { name: 'missing' } },
340
+ } as AgentClusterInstallK8sResource;
341
+ expect(getSelectedVersion([], aci)).toBe('missing');
342
+ });
343
+
344
+ test('returns undefined when imageSetRef is missing', () => {
345
+ const aci = {
346
+ apiVersion: 'extensions.hive.openshift.io/v1beta1',
347
+ kind: 'AgentClusterInstall',
348
+ metadata: { name: 'aci', namespace: 'ns' },
349
+ spec: {},
350
+ } as AgentClusterInstallK8sResource;
351
+ expect(getSelectedVersion([], aci)).toBeUndefined();
352
+ });
353
+ });
354
+
355
+ describe('getCurrentClusterVersion', () => {
356
+ test('prefers status.history[0].version', () => {
357
+ const cv = {
358
+ apiVersion: 'config.openshift.io/v1',
359
+ kind: 'ClusterVersion',
360
+ metadata: { name: 'version' },
361
+ spec: {
362
+ channel: 'fast-4.18',
363
+ clusterID: 'id',
364
+ desiredUpdate: { version: '4.18.99', image: 'img' },
365
+ },
366
+ status: {
367
+ desired: { version: '4.18.0', image: 'img' },
368
+ history: [
369
+ {
370
+ version: '4.18.5',
371
+ state: 'Completed' as const,
372
+ startedTime: '',
373
+ completionTime: '',
374
+ image: '',
375
+ verified: true,
376
+ },
377
+ ],
378
+ observedGeneration: 1,
379
+ versionHash: 'h',
380
+ availableUpdates: [],
381
+ },
382
+ } as ClusterVersionK8sResource;
383
+ expect(getCurrentClusterVersion(cv)).toBe('4.18.5');
384
+ });
385
+
386
+ test('falls back to spec.desiredUpdate.version when history is empty', () => {
387
+ const cv = {
388
+ apiVersion: 'config.openshift.io/v1',
389
+ kind: 'ClusterVersion',
390
+ metadata: { name: 'version' },
391
+ spec: {
392
+ channel: 'fast-4.18',
393
+ clusterID: 'id',
394
+ desiredUpdate: { version: '4.18.99', image: 'img' },
395
+ },
396
+ status: {
397
+ desired: { version: '4.18.0', image: 'img' },
398
+ history: [],
399
+ observedGeneration: 1,
400
+ versionHash: 'h',
401
+ availableUpdates: [],
402
+ },
403
+ } as ClusterVersionK8sResource;
404
+ expect(getCurrentClusterVersion(cv)).toBe('4.18.99');
405
+ });
406
+
407
+ test('returns undefined when no version is available', () => {
408
+ const cv = {
409
+ apiVersion: 'config.openshift.io/v1',
410
+ kind: 'ClusterVersion',
411
+ metadata: { name: 'version' },
412
+ spec: {
413
+ channel: 'fast-4.18',
414
+ clusterID: 'id',
415
+ },
416
+ status: {
417
+ desired: { version: '4.18.0', image: 'img' },
418
+ history: [],
419
+ observedGeneration: 1,
420
+ versionHash: 'h',
421
+ availableUpdates: [],
422
+ },
423
+ } as ClusterVersionK8sResource;
424
+ expect(getCurrentClusterVersion(cv)).toBeUndefined();
425
+ });
426
+ });
427
+
428
+ describe('getNetworkType', () => {
429
+ test('returns OpenShiftSDN when version is below 4.12', () => {
430
+ const v: OpenshiftVersionOptionType = {
431
+ label: 'OpenShift 4.11.5',
432
+ version: '4.11.5',
433
+ value: 'x',
434
+ default: false,
435
+ supportLevel: 'production',
436
+ };
437
+ expect(getNetworkType(v)).toBe('OpenShiftSDN');
438
+ });
439
+
440
+ test('returns OVNKubernetes when version is 4.12 or higher', () => {
441
+ const v: OpenshiftVersionOptionType = {
442
+ label: 'OpenShift 4.12.0',
443
+ version: '4.12.0',
444
+ value: 'x',
445
+ default: false,
446
+ supportLevel: 'production',
447
+ };
448
+ expect(getNetworkType(v)).toBe('OVNKubernetes');
449
+ });
450
+
451
+ test('returns OVNKubernetes when ocpVersion is undefined', () => {
452
+ expect(getNetworkType(undefined)).toBe('OVNKubernetes');
453
+ });
454
+
455
+ test('returns OVNKubernetes when version string is empty', () => {
456
+ const v: OpenshiftVersionOptionType = {
457
+ label: 'OpenShift ',
458
+ version: '',
459
+ value: 'x',
460
+ default: false,
461
+ supportLevel: 'production',
462
+ };
463
+ expect(getNetworkType(v)).toBe('OVNKubernetes');
464
+ });
465
+ });
@@ -7,44 +7,52 @@ import {
7
7
  OsImage,
8
8
  } from '../../types';
9
9
  import { CpuArchitecture, OpenshiftVersionOptionType } from '../../../common';
10
- import { OpenshiftVersion } from '@openshift-assisted/types/assisted-installer-service';
11
10
  import { getComparableVersionInt } from '../../../common/utils';
12
11
 
13
- export const getVersionFromReleaseImage = (releaseImage = '') => {
14
- const match = /.+:(\d+\.\d+(?:\.\d+)?(?:-\w+)?)/gm.exec(releaseImage);
12
+ export const getVersionFromReleaseString = (value = '') => {
13
+ const match = /(\d+\.\d+(?:\.\d+)?(?:-\w+)?)/gm.exec(value);
15
14
  if (match && match.length > 1 && match[1]) {
16
15
  return match[1];
17
16
  }
18
17
  };
19
18
 
20
- const getCPUArchFromReleaseImage = (releaseImage = '') => {
21
- const match = /.+:.*-(.*)/gm.exec(releaseImage);
19
+ export const getVersionFromClusterImageSet = (clusterImageSet?: ClusterImageSetK8sResource) => {
20
+ return (
21
+ getVersionFromReleaseString(clusterImageSet?.metadata?.labels?.['releaseTag']) ||
22
+ getVersionFromReleaseString(clusterImageSet?.spec?.releaseImage) ||
23
+ clusterImageSet?.metadata?.name ||
24
+ ''
25
+ );
26
+ };
27
+
28
+ const getCPUArchFromReleaseString = (value = '') => {
29
+ const match = /(?:\d+\.)+\d+-(x86-64|[\w_]+)/gm.exec(value);
22
30
  if (match && match.length > 1 && match[1]) {
23
31
  return match[1];
24
32
  }
25
33
  };
26
34
 
27
- // eslint-disable-next-line
28
- const getSupportLevelFromChannel = (
29
- channel?: string,
30
- ): OpenshiftVersion['supportLevel'] | 'custom' => {
31
- if (!channel) {
32
- return 'maintenance';
33
- }
34
-
35
- if (channel.startsWith('fast')) {
36
- return 'beta'; // TODO(mlibra): Is this correct?
37
- }
35
+ const getCPUArchFromClusterImageSet = (clusterImageSet?: ClusterImageSetK8sResource) => {
36
+ const cpuArch =
37
+ clusterImageSet?.metadata?.labels?.architecture ||
38
+ getCPUArchFromReleaseString(clusterImageSet?.metadata?.labels?.['releaseTag']) ||
39
+ getCPUArchFromReleaseString(clusterImageSet?.spec?.releaseImage) ||
40
+ getCPUArchFromReleaseString(clusterImageSet?.metadata?.name) ||
41
+ '';
38
42
 
39
- if (channel.startsWith('stable')) {
40
- return 'production';
43
+ switch (cpuArch) {
44
+ case CpuArchitecture.x86:
45
+ case CpuArchitecture.ARM:
46
+ case CpuArchitecture.s390x:
47
+ case CpuArchitecture.MULTI:
48
+ return cpuArch as CpuArchitecture;
49
+ case 'x86-64':
50
+ return CpuArchitecture.x86;
51
+ default:
52
+ return undefined;
41
53
  }
42
-
43
- return 'beta';
44
54
  };
45
55
 
46
- export const supportedNutanixPlatforms = ['x86_64', 'x86-64'];
47
-
48
56
  export const isValidImageSet = (
49
57
  cis: ClusterImageSetK8sResource,
50
58
  architectures?: string[],
@@ -71,20 +79,16 @@ const extractMajorMinor = (version: string): string => {
71
79
  const toVersionOption = (
72
80
  clusterImageSet: ClusterImageSetK8sResource,
73
81
  ): OpenshiftVersionOptionType => {
74
- const version =
75
- getVersionFromReleaseImage(clusterImageSet.spec?.releaseImage) ||
76
- clusterImageSet.metadata?.name ||
77
- '';
78
- const cpuArch = getCPUArchFromReleaseImage(clusterImageSet.spec?.releaseImage);
82
+ const version = getVersionFromClusterImageSet(clusterImageSet);
83
+ const cpuArch = getCPUArchFromClusterImageSet(clusterImageSet);
84
+
79
85
  return {
80
86
  label: `OpenShift ${version}`,
81
87
  version,
82
88
  value: clusterImageSet.metadata?.name as string,
83
89
  default: false,
84
- // (rawagner) ACM does not have the warning so changing to 'production'
85
- // supportLevel : getSupportLevelFromChannel(clusterImageSet.metadata?.labels?.channel)
86
- supportLevel: 'production',
87
- cpuArchitectures: cpuArch ? [cpuArch as CpuArchitecture] : undefined,
90
+ supportLevel: 'production', // ACM doesn't have feature support levels
91
+ cpuArchitectures: cpuArch ? [cpuArch] : undefined,
88
92
  };
89
93
  };
90
94
 
@@ -101,6 +105,8 @@ const hasMatchingOsImage = (
101
105
  return osImageVersions.includes(extractMajorMinor(version.version));
102
106
  };
103
107
 
108
+ const supportedNutanixPlatforms = ['x86_64', 'x86-64'];
109
+
104
110
  export const getOCPVersions = (
105
111
  clusterImageSets: ClusterImageSetK8sResource[],
106
112
  isNutanix?: boolean,
@@ -20,12 +20,18 @@ import parseUrl from 'parse-url';
20
20
  import { useTranslation } from '../../../../common/hooks/use-translation-wrapper';
21
21
  import { getStorageSizeGiB } from '../../helpers';
22
22
  import { AlertPayload } from '../../../../common';
23
+ import { getErrorMessage } from '../../../../common/utils';
23
24
 
24
25
  import { CimConfigurationModalProps, CimConfigurationValues } from './types';
25
- import { onEnableCIM } from './persist';
26
+ import {
27
+ patchProvisioning,
28
+ createAgentServiceConfig,
29
+ editAgentServiceConfig,
30
+ configureIngressLoadBalancer,
31
+ } from './persist';
26
32
  import { CimConfigDisconnectedAlert } from './CimConfigDisconnectedAlert';
27
33
  import { MIN_DB_VOL_SIZE, MIN_FS_VOL_SIZE, MIN_IMG_VOL_SIZE } from './constants';
28
- import { isCIMConfigProgressing } from './utils';
34
+ import { isCIMConfigProgressing, LOCAL_STORAGE_ID_LAST_UPDATE_TIMESTAMP } from './utils';
29
35
  import { resetCimConfigProgressAlertSuccessStatus } from './CimConfigProgressAlert';
30
36
  import { CimConfigurationFormFields } from './CimConfigurationFormFields';
31
37
 
@@ -52,24 +58,45 @@ export const CimConfigurationModal: React.FC<CimConfigurationModalProps> = ({
52
58
  helpers.setSubmitting(true);
53
59
  resetCimConfigProgressAlertSuccessStatus();
54
60
 
55
- if (
56
- await onEnableCIM({
57
- t,
58
- setError,
59
- agentServiceConfig,
60
- platform,
61
- dbVolSizeGiB: values.dbVolSize,
62
- fsVolSizeGiB: values.fsVolSize,
63
- imgVolSizeGiB: values.imgVolSize,
64
- configureLoadBalancer: values.configureLoadBalancer,
65
- ciscoIntersightURL: values.addCiscoIntersightURL ? values.ciscoIntersightURL : undefined,
66
- })
67
- ) {
68
- // successfully persisted
61
+ try {
62
+ if (['none', 'baremetal', 'openstack', 'vsphere'].includes(platform.toLocaleLowerCase())) {
63
+ try {
64
+ await patchProvisioning();
65
+ } catch (e) {
66
+ setError({
67
+ title: t('ai:Failed to configure provisioning to enable registering hosts via BMC.'),
68
+ message: getErrorMessage(e),
69
+ variant: AlertVariant.warning,
70
+ });
71
+ setConfigureLoadBalancerInitial(values.configureLoadBalancer);
72
+ return;
73
+ }
74
+ }
75
+
76
+ if (isEdit && agentServiceConfig) {
77
+ await editAgentServiceConfig({
78
+ t,
79
+ agentServiceConfig,
80
+ values,
81
+ });
82
+ } else {
83
+ await createAgentServiceConfig({ t, values });
84
+ }
85
+
86
+ window.localStorage.setItem(LOCAL_STORAGE_ID_LAST_UPDATE_TIMESTAMP, new Date().toISOString());
87
+
88
+ if (values.configureLoadBalancer) {
89
+ await configureIngressLoadBalancer({ t });
90
+ }
91
+
69
92
  onClose();
70
- } else {
71
- // keep modal open and show error
93
+ } catch (err) {
94
+ setError({
95
+ title: t('ai:Failed to save configuration'),
96
+ message: getErrorMessage(err),
97
+ });
72
98
  setConfigureLoadBalancerInitial(values.configureLoadBalancer);
99
+ } finally {
73
100
  helpers.setSubmitting(false);
74
101
  }
75
102
  };