@rancher/shell 0.3.0 → 0.3.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 (322) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_layout.scss +1 -2
  4. package/assets/styles/global/_select.scss +1 -4
  5. package/assets/styles/themes/_dark.scss +4 -4
  6. package/assets/styles/themes/_light.scss +4 -3
  7. package/assets/styles/themes/_suse.scss +1 -1
  8. package/assets/styles/vendor/vue-select.scss +4 -3
  9. package/assets/translations/en-us.yaml +669 -73
  10. package/assets/translations/zh-hans.yaml +547 -165
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/cloud-credential/azure.vue +23 -0
  13. package/cloud-credential/harvester.vue +25 -62
  14. package/cloud-credential/pnap.vue +80 -0
  15. package/components/.DS_Store +0 -0
  16. package/components/AdvancedSection.vue +9 -2
  17. package/components/Alert.vue +2 -2
  18. package/components/ButtonDropdown.vue +0 -2
  19. package/components/ButtonGroup.vue +1 -0
  20. package/components/CollapsibleCard.vue +0 -1
  21. package/components/CruResource.vue +41 -4
  22. package/components/DetailTop.vue +58 -3
  23. package/components/DisableAuthProviderModal.vue +106 -0
  24. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  25. package/components/ExplorerMembers.vue +253 -30
  26. package/components/ExplorerProjectsNamespaces.vue +77 -33
  27. package/components/GrowlManager.vue +3 -3
  28. package/components/IconOrSvg.vue +149 -0
  29. package/components/LogItem.vue +69 -0
  30. package/components/PodSecurityAdmission.vue +302 -0
  31. package/components/PromptModal.vue +1 -0
  32. package/components/ResourceDetail/Masthead.vue +54 -2
  33. package/components/ResourceDetail/index.vue +12 -5
  34. package/components/ResourceList/Masthead.vue +11 -1
  35. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  36. package/components/ResourceList/index.vue +53 -12
  37. package/components/ResourceList/resource-list.config.js +7 -0
  38. package/components/ResourceTable.vue +31 -6
  39. package/components/SimpleBox.vue +1 -1
  40. package/components/SortableTable/THead.vue +15 -5
  41. package/components/SortableTable/index.vue +21 -10
  42. package/components/Tabbed/index.vue +20 -15
  43. package/components/__tests__/.DS_Store +0 -0
  44. package/components/__tests__/AsyncButton.test.ts +140 -0
  45. package/components/__tests__/BackLink.test.ts +33 -0
  46. package/components/__tests__/ButtonGroup.test.ts +124 -0
  47. package/components/__tests__/ClusterBadge.test.ts +32 -0
  48. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  49. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  50. package/components/__tests__/CruResource.test.ts +3 -2
  51. package/components/__tests__/FixedBanner.test.ts +129 -0
  52. package/components/__tests__/GrowlManager.test.ts +147 -0
  53. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  54. package/components/__tests__/PercentageBar.test.ts +32 -0
  55. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  56. package/components/auth/AuthBanner.vue +20 -10
  57. package/components/auth/RoleDetailEdit.vue +26 -17
  58. package/components/auth/SelectPrincipal.vue +36 -5
  59. package/components/form/ArrayList.vue +3 -35
  60. package/components/form/ArrayListGrouped.vue +13 -4
  61. package/components/form/ArrayListSelect.vue +5 -5
  62. package/components/form/Error.vue +8 -0
  63. package/components/form/KeyValue.vue +39 -7
  64. package/components/form/LabeledSelect.vue +5 -2
  65. package/components/form/Labels.vue +46 -16
  66. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  67. package/components/form/Members/MembershipEditor.vue +12 -12
  68. package/components/form/NameNsDescription.vue +1 -1
  69. package/components/form/NodeScheduling.vue +1 -1
  70. package/components/form/Probe.vue +3 -3
  71. package/components/form/ResourceQuota/Project.vue +6 -6
  72. package/components/form/ResourceTabs/index.vue +1 -6
  73. package/components/form/Security.vue +7 -6
  74. package/components/form/Select.vue +3 -2
  75. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  76. package/components/form/ServicePorts.vue +8 -0
  77. package/components/form/WorkloadPorts.vue +7 -1
  78. package/components/form/__tests__/ArrayList.test.ts +74 -0
  79. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  80. package/components/formatter/Checked.vue +1 -1
  81. package/components/formatter/ClusterLink.vue +5 -0
  82. package/components/formatter/IconIsDefault.vue +2 -2
  83. package/components/formatter/InternalExternalIP.vue +11 -8
  84. package/components/formatter/LiveDuration.vue +78 -0
  85. package/components/formatter/WorkloadHealthScale.vue +5 -3
  86. package/components/nav/Header.vue +6 -3
  87. package/components/nav/NamespaceFilter.vue +146 -63
  88. package/components/nav/TopLevelMenu.vue +22 -19
  89. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  90. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  91. package/components/nav/WindowManager/Window.vue +2 -0
  92. package/components/nav/WindowManager/index.vue +10 -0
  93. package/config/elemental-types.js +9 -0
  94. package/config/features.js +2 -0
  95. package/config/home-links.js +4 -1
  96. package/config/pod-security-admission.ts +82 -0
  97. package/config/product/apps.js +1 -1
  98. package/config/product/auth.js +6 -5
  99. package/config/product/explorer.js +6 -6
  100. package/config/product/fleet.js +1 -1
  101. package/config/product/manager.js +6 -2
  102. package/config/secret.js +0 -1
  103. package/config/settings.ts +26 -9
  104. package/config/table-headers.js +22 -11
  105. package/config/types.js +4 -1
  106. package/content/docs/zh-hans/getting-started.md +113 -137
  107. package/content/docs/zh-hans/whats-new.md +8 -46
  108. package/creators/pkg/package-lock.json +37 -0
  109. package/creators/pkg/package.json +1 -1
  110. package/detail/catalog.cattle.io.app.vue +1 -1
  111. package/detail/pod.vue +1 -1
  112. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  113. package/detail/service.vue +2 -9
  114. package/detail/workload/index.vue +0 -1
  115. package/dialog/AddClusterMemberDialog.vue +22 -28
  116. package/dialog/AddProjectMemberDialog.vue +53 -9
  117. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  118. package/dialog/DrainNode.vue +44 -48
  119. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  120. package/dialog/GenericPrompt.vue +15 -20
  121. package/dialog/RollbackWorkloadDialog.vue +15 -46
  122. package/dialog/RotateCertificatesDialog.vue +5 -7
  123. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  124. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  125. package/dialog/ScaleMachineDownDialog.vue +1 -1
  126. package/dialog/ScalePoolDownDialog.vue +121 -0
  127. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  128. package/edit/auth/azuread.vue +16 -16
  129. package/edit/auth/github.vue +8 -0
  130. package/edit/auth/googleoauth.vue +10 -1
  131. package/edit/auth/ldap/index.vue +10 -0
  132. package/edit/auth/oidc.vue +10 -0
  133. package/edit/auth/saml.vue +10 -0
  134. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  135. package/edit/cloudcredential.vue +3 -7
  136. package/edit/logging-flow/Match.vue +39 -8
  137. package/edit/logging-flow/index.vue +27 -4
  138. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  139. package/edit/management.cattle.io.project.vue +8 -1
  140. package/edit/management.cattle.io.setting.vue +5 -2
  141. package/edit/management.cattle.io.user.vue +7 -1
  142. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
  143. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  144. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  145. package/edit/namespace.vue +18 -4
  146. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  147. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  148. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  149. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  150. package/edit/persistentvolume/index.vue +30 -27
  151. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  152. package/edit/persistentvolume/plugins/csi.vue +102 -62
  153. package/edit/persistentvolume/plugins/fc.vue +19 -19
  154. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  155. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  156. package/edit/persistentvolumeclaim.vue +78 -75
  157. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  158. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  159. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  160. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  161. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
  162. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  164. package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
  165. package/edit/secret/index.vue +3 -7
  166. package/edit/service.vue +3 -1
  167. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  168. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  169. package/edit/workload/__tests__/index.test.ts +98 -0
  170. package/edit/workload/index.vue +58 -8
  171. package/edit/workload/mixins/workload.js +107 -70
  172. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  173. package/edit/workload/storage/emptyDir.vue +88 -0
  174. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  175. package/edit/workload/storage/index.vue +8 -0
  176. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  177. package/layouts/default.vue +57 -44
  178. package/list/__tests__/workload.test.ts +5 -2
  179. package/list/catalog.cattle.io.app.vue +1 -0
  180. package/list/cis.cattle.io.clusterscan.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +5 -6
  182. package/list/fleet.cattle.io.cluster.vue +6 -3
  183. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  184. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  185. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  186. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  187. package/list/logging.banzaicloud.io.flow.vue +6 -5
  188. package/list/management.cattle.io.cluster.vue +1 -0
  189. package/list/management.cattle.io.feature.vue +3 -4
  190. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  191. package/list/management.cattle.io.setting.vue +2 -2
  192. package/list/management.cattle.io.user.vue +4 -10
  193. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  194. package/list/node.vue +8 -5
  195. package/list/persistentvolume.vue +3 -3
  196. package/list/persistentvolumeclaim.vue +3 -4
  197. package/list/provisioning.cattle.io.cluster.vue +18 -19
  198. package/list/service.vue +6 -14
  199. package/list/workload.vue +43 -38
  200. package/machine-config/azure.vue +429 -60
  201. package/machine-config/pnap.vue +288 -0
  202. package/mixins/auth-config.js +1 -3
  203. package/mixins/browser-tab-visibility.js +8 -14
  204. package/mixins/chart.js +1 -1
  205. package/mixins/create-edit-view/impl.js +4 -0
  206. package/mixins/create-edit-view/index.js +4 -2
  207. package/mixins/resource-fetch-namespaced.js +98 -0
  208. package/mixins/resource-fetch.js +79 -45
  209. package/mixins/resource-manager.js +1 -23
  210. package/models/apps.controllerrevision.js +7 -0
  211. package/models/apps.daemonset.js +18 -0
  212. package/models/apps.deployment.js +44 -0
  213. package/models/apps.replicaset.js +7 -0
  214. package/models/apps.statefulset.js +18 -0
  215. package/models/batch.job.js +7 -14
  216. package/models/cluster/node.js +10 -2
  217. package/models/cluster.x-k8s.io.machine.js +26 -4
  218. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  219. package/models/event.js +7 -0
  220. package/models/logging.banzaicloud.io.flow.js +4 -0
  221. package/models/management.cattle.io.cluster.js +1 -1
  222. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  223. package/models/management.cattle.io.globalrole.js +2 -2
  224. package/models/management.cattle.io.node.js +37 -2
  225. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  226. package/models/management.cattle.io.project.js +30 -11
  227. package/models/management.cattle.io.setting.js +1 -1
  228. package/models/management.cattle.io.user.js +37 -1
  229. package/models/namespace.js +42 -5
  230. package/models/persistentvolume.js +14 -2
  231. package/models/pod.js +15 -0
  232. package/models/projectroletemplatebinding.js +7 -0
  233. package/models/provisioning.cattle.io.cluster.js +61 -10
  234. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  235. package/models/service.js +14 -13
  236. package/models/storage.k8s.io.storageclass.js +33 -18
  237. package/models/workload.js +38 -7
  238. package/nuxt.config.js +27 -17
  239. package/package.json +7 -7
  240. package/pages/about.vue +14 -2
  241. package/pages/c/_cluster/apps/charts/index.vue +4 -3
  242. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  243. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  244. package/pages/c/_cluster/auth/config/index.vue +8 -6
  245. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  246. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  247. package/pages/c/_cluster/explorer/index.vue +12 -6
  248. package/pages/c/_cluster/longhorn/index.vue +1 -1
  249. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  250. package/pages/c/_cluster/monitoring/index.vue +1 -1
  251. package/pages/c/_cluster/neuvector/index.vue +1 -1
  252. package/pages/c/_cluster/settings/performance.vue +48 -2
  253. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
  254. package/pages/c/_cluster/uiplugins/index.vue +28 -2
  255. package/pages/diagnostic.vue +5 -4
  256. package/pages/home.vue +105 -30
  257. package/pages/prefs.vue +23 -12
  258. package/pages/rio/mesh.vue +1 -1
  259. package/pkg/dynamic-importer.lib.js +8 -0
  260. package/pkg/vue.config.js +4 -0
  261. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  262. package/plugins/dashboard-store/actions.js +32 -25
  263. package/plugins/dashboard-store/getters.js +50 -33
  264. package/plugins/dashboard-store/mutations.js +134 -28
  265. package/plugins/dashboard-store/resource-class.js +21 -41
  266. package/plugins/steve/actions.js +30 -0
  267. package/plugins/steve/caches/resourceCache.js +60 -0
  268. package/plugins/steve/getters.js +44 -1
  269. package/plugins/steve/mutations.js +97 -36
  270. package/plugins/steve/resourceWatcher.js +277 -0
  271. package/plugins/steve/schema.utils.js +25 -0
  272. package/plugins/steve/subscribe.js +288 -115
  273. package/plugins/steve/worker/index.js +17 -0
  274. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  275. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  276. package/rancher-components/Card/Card.vue +3 -3
  277. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  278. package/rancher-components/StringList/StringList.test.ts +45 -420
  279. package/rancher-components/StringList/StringList.vue +1 -10
  280. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  281. package/rancher-components/components/Banner/Banner.vue +129 -61
  282. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  283. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  284. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  285. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  286. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  287. package/rancher-components/components/StringList/StringList.vue +21 -15
  288. package/scripts/test-plugins-build.sh +8 -0
  289. package/static/loading-indicator.html +1 -1
  290. package/store/index.js +54 -3
  291. package/store/plugins.js +0 -17
  292. package/store/pnap.js +128 -0
  293. package/store/prefs.js +4 -2
  294. package/store/type-map.js +55 -13
  295. package/types/pod-security-admission.ts +36 -0
  296. package/types/shell/index.d.ts +496 -396
  297. package/utils/__tests__/object.test.ts +17 -1
  298. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  299. package/utils/async.ts +36 -0
  300. package/utils/color.js +45 -0
  301. package/utils/crypto/browserHashUtils.js +18 -0
  302. package/utils/dynamic-importer.js +8 -0
  303. package/utils/install-redirect.js +1 -1
  304. package/utils/object.js +24 -0
  305. package/utils/pod-security-admission.ts +39 -0
  306. package/utils/socket.js +61 -24
  307. package/utils/string.js +2 -0
  308. package/utils/svg-filter.js +301 -0
  309. package/utils/time.js +49 -0
  310. package/utils/validators/cidr.js +4 -0
  311. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  312. package/utils/validators/formRules/index.ts +14 -0
  313. package/config/product/harvester-manager.js +0 -162
  314. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  315. package/list/harvesterhci.io.management.cluster.vue +0 -241
  316. package/machine-config/harvester.vue +0 -693
  317. package/models/harvesterhci.io.management.cluster.js +0 -228
  318. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  319. package/rancher-components/Card/Card.test.ts +0 -39
  320. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  321. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  322. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -4,7 +4,6 @@ import throttle from 'lodash/throttle';
4
4
  import isArray from 'lodash/isArray';
5
5
  import merge from 'lodash/merge';
6
6
  import { mapGetters } from 'vuex';
7
-
8
7
  import CreateEditView from '@shell/mixins/create-edit-view';
9
8
  import FormValidation from '@shell/mixins/form-validation';
10
9
 
@@ -29,6 +28,7 @@ import { sortBy } from '@shell/utils/sort';
29
28
  import { camelToTitle, nlToBr } from '@shell/utils/string';
30
29
  import { compare, sortable } from '@shell/utils/version';
31
30
  import { isHarvesterSatisfiesVersion } from '@shell/utils/cluster';
31
+ import * as VERSION from '@shell/utils/version';
32
32
 
33
33
  import ArrayList from '@shell/components/form/ArrayList';
34
34
  import ArrayListGrouped from '@shell/components/form/ArrayListGrouped';
@@ -66,6 +66,8 @@ import RegistryConfigs from './RegistryConfigs';
66
66
  import RegistryMirrors from './RegistryMirrors';
67
67
  import S3Config from './S3Config';
68
68
  import SelectCredential from './SelectCredential';
69
+ import AdvancedSection from '@shell/components/AdvancedSection.vue';
70
+ import { ELEMENTAL_SCHEMA_IDS, KIND, ELEMENTAL_CLUSTER_PROVIDER } from '../../config/elemental-types';
69
71
 
70
72
  const PUBLIC = 'public';
71
73
  const PRIVATE = 'private';
@@ -77,6 +79,7 @@ const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
77
79
  export default {
78
80
  components: {
79
81
  ACE,
82
+ AdvancedSection,
80
83
  AgentEnv,
81
84
  ArrayList,
82
85
  ArrayListGrouped,
@@ -136,6 +139,10 @@ export default {
136
139
  hash.allPSPs = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.POD_SECURITY_POLICY_TEMPLATE });
137
140
  }
138
141
 
142
+ if (this.$store.getters['management/canList'](MANAGEMENT.PSA)) {
143
+ hash.allPSAs = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PSA });
144
+ }
145
+
139
146
  // Get the latest versions from the global settings if possible
140
147
  const globalSettings = await this.$store.getters['management/all'](MANAGEMENT.SETTING) || [];
141
148
  const defaultRke2Setting = globalSettings.find(setting => setting.id === 'rke2-default-version') || {};
@@ -157,6 +164,7 @@ export default {
157
164
  const res = await allHash(hash);
158
165
 
159
166
  this.allPSPs = res.allPSPs || [];
167
+ this.allPSAs = res.allPSAs || [];
160
168
  this.rke2Versions = res.rke2Versions.data || [];
161
169
  this.k3sVersions = res.k3sVersions.data || [];
162
170
 
@@ -230,6 +238,10 @@ export default {
230
238
  set(this.value.spec, 'defaultPodSecurityPolicyTemplateName', '');
231
239
  }
232
240
 
241
+ if ( this.value.spec.defaultPodSecurityAdmissionConfigurationTemplateName === undefined ) {
242
+ set(this.value.spec, 'defaultPodSecurityAdmissionConfigurationTemplateName', '');
243
+ }
244
+
233
245
  await this.initAddons();
234
246
  await this.initRegistry();
235
247
 
@@ -266,34 +278,42 @@ export default {
266
278
  set(this.value.spec, 'rkeConfig.machineSelectorConfig', [{ config: {} }]);
267
279
  }
268
280
 
281
+ // Store the initial PSP template name, so we can set it back if needed
282
+ const lastDefaultPodSecurityPolicyTemplateName = this.value.spec.defaultPodSecurityPolicyTemplateName;
283
+ const previousKubernetesVersion = this.value.spec.kubernetesVersion;
284
+
269
285
  return {
270
- loadedOnce: false,
271
- lastIdx: 0,
272
- allPSPs: null,
273
- nodeComponent: null,
274
- credentialId: null,
275
- credential: null,
276
- machinePools: null,
277
- rke2Versions: null,
278
- k3sVersions: null,
279
- defaultRke2: '',
280
- defaultK3s: '',
281
- s3Backup: false,
282
- versionInfo: {},
283
- membershipUpdate: {},
284
- showDeprecatedPatchVersions: false,
285
- systemRegistry: null,
286
- registryHost: null,
287
- registryMode: null,
288
- registrySecret: null,
289
- userChartValues: {},
290
- userChartValuesTemp: {},
291
- addonsRev: 0,
292
- clusterIsAlreadyCreated: !!this.value.id,
293
- fvFormRuleSets: [{
286
+ loadedOnce: false,
287
+ lastIdx: 0,
288
+ allPSPs: null,
289
+ allPSAs: [],
290
+ nodeComponent: null,
291
+ credentialId: null,
292
+ credential: null,
293
+ machinePools: null,
294
+ rke2Versions: null,
295
+ k3sVersions: null,
296
+ defaultRke2: '',
297
+ defaultK3s: '',
298
+ s3Backup: false,
299
+ versionInfo: {},
300
+ membershipUpdate: {},
301
+ showDeprecatedPatchVersions: false,
302
+ systemRegistry: null,
303
+ registryHost: null,
304
+ showCustomRegistryInput: false,
305
+ showCustomRegistryAdvancedInput: false,
306
+ registrySecret: null,
307
+ userChartValues: {},
308
+ userChartValuesTemp: {},
309
+ addonsRev: 0,
310
+ clusterIsAlreadyCreated: !!this.value.id,
311
+ fvFormRuleSets: [{
294
312
  path: 'metadata.name', rules: ['subDomain'], translationKey: 'nameNsDescription.name.label'
295
313
  }],
296
314
  harvesterVersionRange: {},
315
+ lastDefaultPodSecurityPolicyTemplateName,
316
+ previousKubernetesVersion,
297
317
  };
298
318
  },
299
319
 
@@ -309,6 +329,10 @@ export default {
309
329
  return this.value.spec.rkeConfig;
310
330
  },
311
331
 
332
+ isElementalCluster() {
333
+ return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
334
+ },
335
+
312
336
  advancedTitleAlt() {
313
337
  const machineSelectorLength = this.rkeConfig.machineSelectorConfig.length;
314
338
 
@@ -327,9 +351,35 @@ export default {
327
351
  return this.value.agentConfig;
328
352
  },
329
353
 
354
+ /**
355
+ * Return need of PSA if RKE and min k8s version
356
+ */
357
+ needsPSA() {
358
+ const release = this.value?.spec?.kubernetesVersion || '';
359
+ const isRKE2 = release.includes('rke2');
360
+ const version = release.match(/\d+/g);
361
+ const isRequiredVersion = version?.length ? +version[0] > 1 || +version[1] >= 23 : false;
362
+
363
+ return isRKE2 && isRequiredVersion;
364
+ },
365
+
366
+ /**
367
+ * Restrict use of PSP based on min k8s version
368
+ */
369
+ needsPSP() {
370
+ const release = this.value?.spec?.kubernetesVersion || '';
371
+ const version = release.match(/\d+/g);
372
+ const isRequiredVersion = version?.length ? +version[0] === 1 && +version[1] < 25 : false;
373
+
374
+ return isRequiredVersion;
375
+ },
376
+
330
377
  // kubeletConfigs() {
331
378
  // return this.value.spec.rkeConfig.machineSelectorConfig.filter(x => !!x.machineLabelSelector);
332
379
  // },
380
+ /**
381
+ * Check if k8s release version used is RKE2 ^1.25
382
+ */
333
383
 
334
384
  unsupportedSelectorConfig() {
335
385
  let global = 0;
@@ -419,7 +469,10 @@ export default {
419
469
  return { label: x, value: x };
420
470
  });
421
471
 
422
- out.unshift({ label: '(None)', value: '' });
472
+ out.unshift({
473
+ label: this.$store.getters['i18n/t']('cluster.rke2.cisProfile.option'),
474
+ value: ''
475
+ });
423
476
 
424
477
  return out;
425
478
  },
@@ -429,7 +482,10 @@ export default {
429
482
  return null;
430
483
  }
431
484
 
432
- const out = [{ label: 'RKE2 Default', value: '' }];
485
+ const out = [{
486
+ label: this.$store.getters['i18n/t']('cluster.rke2.defaultPodSecurityPolicyTemplateName.option'),
487
+ value: ''
488
+ }];
433
489
 
434
490
  if ( this.allPSPs ) {
435
491
  for ( const pspt of this.allPSPs ) {
@@ -449,6 +505,35 @@ export default {
449
505
  return out;
450
506
  },
451
507
 
508
+ /**
509
+ * Convert PSA templates into options, sorting and flagging if any selected
510
+ */
511
+ psaOptions() {
512
+ if ( !this.needsPSA ) {
513
+ return [];
514
+ }
515
+ const out = [{
516
+ label: this.$store.getters['i18n/t']('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.option'),
517
+ value: ''
518
+ }];
519
+
520
+ if ( this.allPSAs ) {
521
+ for ( const psa of this.allPSAs ) {
522
+ out.push({
523
+ label: psa.nameDisplay,
524
+ value: psa.id,
525
+ });
526
+ }
527
+ }
528
+ const cur = this.value.spec.defaultPodSecurityAdmissionConfigurationTemplateName;
529
+
530
+ if ( cur && !out.find(x => x.value === cur) ) {
531
+ out.unshift({ label: `${ cur } (Current)`, value: cur });
532
+ }
533
+
534
+ return out;
535
+ },
536
+
452
537
  disableOptions() {
453
538
  return this.serverArgs.disable.options.map((value) => {
454
539
  return {
@@ -459,7 +544,10 @@ export default {
459
544
  },
460
545
 
461
546
  cloudProviderOptions() {
462
- const out = [{ label: '(None)', value: '' }];
547
+ const out = [{
548
+ label: this.$store.getters['i18n/t']('cluster.rke2.cloudProvider.defaultValue.label'),
549
+ value: '',
550
+ }];
463
551
 
464
552
  const preferred = this.$store.getters['plugins/cloudProviderForDriver'](this.provider);
465
553
 
@@ -506,11 +594,7 @@ export default {
506
594
  },
507
595
 
508
596
  haveArgInfo() {
509
- if ( this.selectedVersion?.serverArgs && this.selectedVersion?.agentArgs ) {
510
- return true;
511
- }
512
-
513
- return false;
597
+ return Boolean(this.selectedVersion?.serverArgs && this.selectedVersion?.agentArgs);
514
598
  },
515
599
 
516
600
  serverArgs() {
@@ -526,20 +610,11 @@ export default {
526
610
  },
527
611
 
528
612
  showCisProfile() {
529
- return this.provider === 'custom' && ( this.serverArgs.profile || this.agentArgs.profile );
530
- },
531
-
532
- registryOptions() {
533
- return [PUBLIC, PRIVATE, ADVANCED].map((opt) => {
534
- return {
535
- label: this.$store.getters['i18n/withFallback'](`cluster.privateRegistry.mode."${ opt }"`, null, opt),
536
- value: opt,
537
- };
538
- });
613
+ return (this.provider === 'custom' || this.isElementalCluster) && ( this.serverArgs.profile || this.agentArgs.profile );
539
614
  },
540
615
 
541
616
  needCredential() {
542
- if ( this.provider === 'custom' || this.provider === 'import' || this.mode === _VIEW ) {
617
+ if ( this.provider === 'custom' || this.provider === 'import' || this.isElementalCluster || this.mode === _VIEW ) {
543
618
  return false;
544
619
  }
545
620
 
@@ -559,13 +634,17 @@ export default {
559
634
  },
560
635
 
561
636
  machineConfigSchema() {
637
+ let schema;
638
+
562
639
  if ( !this.hasMachinePools ) {
563
640
  return null;
641
+ } else if (this.isElementalCluster) {
642
+ schema = ELEMENTAL_SCHEMA_IDS.MACHINE_INV_SELECTOR_TEMPLATES;
643
+ } else {
644
+ schema = `${ CAPI.MACHINE_CONFIG_GROUP }.${ this.provider }config`;
564
645
  }
565
646
 
566
- const schema = this.$store.getters['management/schemaFor'](`${ CAPI.MACHINE_CONFIG_GROUP }.${ this.provider }config`);
567
-
568
- return schema;
647
+ return this.$store.getters['management/schemaFor'](schema);
569
648
  },
570
649
 
571
650
  nodeTotals() {
@@ -849,6 +928,19 @@ export default {
849
928
  return false;
850
929
  }
851
930
  },
931
+
932
+ displayInvalidPspsBanner() {
933
+ const version = VERSION.parse(this.value.spec.kubernetesVersion);
934
+
935
+ const major = parseInt(version?.[0] || 0);
936
+ const minor = parseInt(version?.[1] || 0);
937
+
938
+ if (major === 1 && minor >= 25) {
939
+ return this.allPSPs?.length > 0;
940
+ }
941
+
942
+ return false;
943
+ }
852
944
  },
853
945
 
854
946
  watch: {
@@ -943,8 +1035,16 @@ export default {
943
1035
 
944
1036
  if ( existing?.length ) {
945
1037
  for ( const pool of existing ) {
946
- const type = `${ CAPI.MACHINE_CONFIG_GROUP }.${ pool.machineConfigRef.kind.toLowerCase() }`;
1038
+ let type;
1039
+
1040
+ if (this.isElementalCluster) {
1041
+ type = ELEMENTAL_SCHEMA_IDS.MACHINE_INV_SELECTOR_TEMPLATES;
1042
+ } else {
1043
+ type = `${ CAPI.MACHINE_CONFIG_GROUP }.${ pool.machineConfigRef.kind.toLowerCase() }`;
1044
+ }
1045
+
947
1046
  let config;
1047
+ let configMissing = false;
948
1048
 
949
1049
  if ( this.$store.getters['management/canList'](type) ) {
950
1050
  try {
@@ -954,6 +1054,12 @@ export default {
954
1054
  });
955
1055
  } catch (e) {
956
1056
  // Some users can't see the config, that's ok.
1057
+ // we will display a banner for a 404 only for elemental
1058
+ if (e?.status === 404) {
1059
+ if (this.isElementalCluster) {
1060
+ configMissing = true;
1061
+ }
1062
+ }
957
1063
  }
958
1064
  }
959
1065
 
@@ -967,6 +1073,7 @@ export default {
967
1073
  update: true,
968
1074
  pool: clone(pool),
969
1075
  config: config ? await this.$store.dispatch('management/clone', { resource: config }) : null,
1076
+ configMissing
970
1077
  });
971
1078
  }
972
1079
  }
@@ -1014,6 +1121,11 @@ export default {
1014
1121
  if (this.provider === 'vmwarevsphere') {
1015
1122
  pool.pool.machineOS = 'linux';
1016
1123
  }
1124
+
1125
+ if (this.isElementalCluster) {
1126
+ pool.pool.machineConfigRef.apiVersion = `${ this.machineConfigSchema.attributes.group }/${ this.machineConfigSchema.attributes.version }`;
1127
+ }
1128
+
1017
1129
  this.machinePools.push(pool);
1018
1130
 
1019
1131
  this.$nextTick(() => {
@@ -1086,6 +1198,11 @@ export default {
1086
1198
  entry.config = await entry.config.save();
1087
1199
  }
1088
1200
 
1201
+ // Ensure Elemental clusters have a hostname prefix
1202
+ if (this.isElementalCluster && !entry.pool.hostnamePrefix ) {
1203
+ entry.pool.hostnamePrefix = `${ prefix }-`;
1204
+ }
1205
+
1089
1206
  finalPools.push(entry.pool);
1090
1207
  }
1091
1208
 
@@ -1111,7 +1228,7 @@ export default {
1111
1228
  },
1112
1229
 
1113
1230
  validationPassed() {
1114
- return (this.provider === 'custom' || !!this.credentialId);
1231
+ return (this.provider === 'custom' || this.isElementalCluster || !!this.credentialId);
1115
1232
  },
1116
1233
 
1117
1234
  cancelCredential() {
@@ -1205,6 +1322,7 @@ export default {
1205
1322
  url: `/k8s/clusters/${ clusterId }/v1/harvester/kubeconfig`,
1206
1323
  method: 'POST',
1207
1324
  data: {
1325
+ csiClusterRoleName: 'harvesterhci.io:csi-driver',
1208
1326
  clusterRoleName: 'harvesterhci.io:cloudprovider',
1209
1327
  namespace,
1210
1328
  serviceAccountName: this.value.metadata.name,
@@ -1393,13 +1511,23 @@ export default {
1393
1511
  },
1394
1512
 
1395
1513
  async initRegistry() {
1396
- let registryMode = PUBLIC;
1397
- let registryHost = this.agentConfig?.['system-default-registry'] || '';
1398
- let registrySecret = null;
1399
- let regs = this.rkeConfig.registries;
1514
+ // Check for an existing cluster scoped registry
1515
+ const clusterRegistry = this.agentConfig?.['system-default-registry'] || '';
1400
1516
 
1517
+ // Check for the global registry
1401
1518
  this.systemRegistry = (await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.SYSTEM_DEFAULT_REGISTRY })).value || '';
1402
1519
 
1520
+ // The order of precedence is to use the cluster scoped registry
1521
+ // if it exists, then use the global scoped registry as a fallback
1522
+ if (clusterRegistry) {
1523
+ this.registryHost = clusterRegistry;
1524
+ } else {
1525
+ this.registryHost = this.systemRegistry;
1526
+ }
1527
+
1528
+ let registrySecret = null;
1529
+ let regs = this.rkeConfig.registries;
1530
+
1403
1531
  if ( !regs ) {
1404
1532
  regs = {};
1405
1533
  set(this.rkeConfig, 'registries', regs);
@@ -1413,75 +1541,85 @@ export default {
1413
1541
  set(regs, 'mirrors', {});
1414
1542
  }
1415
1543
 
1416
- if ( registryHost ) {
1417
- registryMode = PRIVATE;
1418
- } else if ( this.systemRegistry ) {
1419
- registryHost = this.systemRegistry;
1420
- registryMode = PRIVATE;
1544
+ const hostname = Object.keys(regs.configs)[0];
1545
+ const config = regs.configs[hostname];
1546
+
1547
+ if ( config ) {
1548
+ registrySecret = config.authConfigSecretName;
1421
1549
  }
1422
1550
 
1423
- if ( Object.keys(regs.mirrors || {}).length || Object.keys(regs.configs || {}).length > 1 ) {
1424
- registryMode = ADVANCED;
1425
- } else {
1426
- const hostname = Object.keys(regs.configs)[0];
1427
- const config = regs.configs[hostname];
1551
+ this.registrySecret = registrySecret;
1428
1552
 
1429
- if ( config ) {
1430
- if ( hostname !== registryHost || config.caBundle || config.insecureSkipVerify || config.tlsSecretName ) {
1431
- registryMode = ADVANCED;
1432
- } else {
1433
- registryMode = PRIVATE;
1434
- registrySecret = config.authConfigSecretName;
1435
- }
1553
+ const hasMirrorsOrAuthConfig = Object.keys(regs.configs).length > 0 || Object.keys(regs.mirrors).length > 0;
1554
+
1555
+ if (this.registryHost || registrySecret || hasMirrorsOrAuthConfig) {
1556
+ this.showCustomRegistryInput = true;
1557
+
1558
+ if (hasMirrorsOrAuthConfig) {
1559
+ this.showCustomRegistryAdvancedInput = true;
1436
1560
  }
1437
1561
  }
1438
-
1439
- this.registryHost = registryHost;
1440
- this.registryMode = registryMode;
1441
- this.registrySecret = registrySecret;
1442
1562
  },
1443
1563
 
1444
1564
  setRegistryConfig() {
1445
1565
  const hostname = (this.registryHost || '').trim();
1446
1566
 
1447
- if ( this.registryMode === PUBLIC ) {
1448
- if ( this.systemRegistry ) {
1449
- // Empty string overrides the system default to nothing
1450
- set(this.agentConfig, 'system-default-registry', '');
1451
- } else {
1452
- // No need to set anything
1453
- set(this.agentConfig, 'system-default-registry', undefined);
1454
- }
1455
- } else if ( !hostname || hostname === this.systemRegistry ) {
1567
+ if ( this.systemRegistry ) {
1568
+ // Empty string overrides the system default to nothing
1569
+ set(this.agentConfig, 'system-default-registry', '');
1570
+ } else {
1571
+ // No need to set anything
1572
+ set(this.agentConfig, 'system-default-registry', undefined);
1573
+ }
1574
+ if ( !hostname || hostname === this.systemRegistry ) {
1456
1575
  // Undefined removes the key which uses the global setting without hardcoding it into the config
1457
1576
  set(this.agentConfig, 'system-default-registry', undefined);
1458
1577
  } else {
1459
1578
  set(this.agentConfig, 'system-default-registry', hostname);
1460
1579
  }
1461
1580
 
1462
- if ( this.registryMode === ADVANCED ) {
1463
- // Leave it alone...
1464
- } else if ( this.registryMode === PRIVATE ) {
1465
- set(this.rkeConfig.registries, 'mirrors', {});
1581
+ if ( hostname && this.registrySecret ) {
1582
+ // For a registry with basic auth, but no mirrors,
1583
+ // add a single registry config with the basic auth secret.
1584
+ const basicAuthConfig = {
1585
+ [hostname]: {
1586
+ authConfigSecretName: this.registrySecret,
1587
+ caBundle: null,
1588
+ insecureSkipVerify: false,
1589
+ tlsSecretName: null,
1590
+ }
1591
+ };
1466
1592
 
1467
- if ( this.registrySecret ) {
1468
- set(this.rkeConfig.registries, 'configs', {
1469
- [hostname]: {
1470
- authConfigSecretName: this.registrySecret,
1471
- caBundle: null,
1472
- insecureSkipVerify: false,
1473
- tlsSecretName: null,
1474
- }
1475
- });
1593
+ const rkeConfig = this.value.spec.rkeConfig;
1594
+
1595
+ if (!rkeConfig) {
1596
+ this.value.spec.rkeConfig = { registries: { configs: basicAuthConfig } };
1597
+ } else if (rkeConfig.registries.configs && Object.keys(rkeConfig.registries.configs).length > 0) {
1598
+ // If some existing authentication secrets are already configured
1599
+ // for registry mirrors, the basic auth is added to the existing ones.
1600
+ const existingConfigs = rkeConfig.registries.configs;
1601
+
1602
+ this.value.spec.rkeConfig.registries.configs = { ...basicAuthConfig, ...existingConfigs };
1476
1603
  } else {
1477
- set(this.rkeConfig.registries, 'configs', {});
1604
+ const existingMirrorAndAuthConfig = this.value.spec.rkeConfig.registries;
1605
+
1606
+ this.value.spec.rkeConfig.registries = {
1607
+ ...existingMirrorAndAuthConfig,
1608
+ configs: basicAuthConfig
1609
+ };
1478
1610
  }
1479
- } else {
1480
- set(this.rkeConfig.registries, 'configs', {});
1481
- set(this.rkeConfig.registries, 'mirrors', {});
1482
1611
  }
1483
1612
  },
1484
1613
 
1614
+ updateConfigs(configs) {
1615
+ // Update authentication configuration
1616
+ // for each mirror
1617
+ if (!this.value.spec?.rkeConfig) {
1618
+ this.value.spec.rkeConfig = { registries: {} };
1619
+ }
1620
+ set(this.value.spec.rkeConfig.registries, 'configs', configs);
1621
+ },
1622
+
1485
1623
  getAllOptionsAfterMinVersion(versions, minVersion, defaultVersion) {
1486
1624
  const out = (versions || []).filter(obj => !!obj.serverArgs).map((obj) => {
1487
1625
  let disabled = false;
@@ -1623,6 +1761,64 @@ export default {
1623
1761
  }
1624
1762
  this.setHarvesterDefaultCloudProvider();
1625
1763
  },
1764
+ toggleCustomRegistry(e) {
1765
+ if (this.registryHost) {
1766
+ this.registryHost = null;
1767
+ this.registrySecret = null;
1768
+ } else {
1769
+ this.initRegistry();
1770
+ }
1771
+ },
1772
+ updateCisProfile() {
1773
+ // If the user selects any Worker CIS Profile,
1774
+ // protect-kernel-defaults should be set to false
1775
+ // in the RKE2 worker/agent config.
1776
+ const selectedCisProfile = this.agentConfig?.profile;
1777
+
1778
+ if (selectedCisProfile) {
1779
+ set(this.agentConfig, 'protect-kernel-defaults', true);
1780
+ } else {
1781
+ set(this.agentConfig, 'protect-kernel-defaults', false);
1782
+ }
1783
+ },
1784
+
1785
+ /**
1786
+ * Handle k8s changes side effects, like PSP and PSA resets
1787
+ */
1788
+ handleKubernetesChange(value) {
1789
+ if (value) {
1790
+ const version = VERSION.parse(value);
1791
+ const major = parseInt(version?.[0] || 0);
1792
+ const minor = parseInt(version?.[1] || 0);
1793
+
1794
+ // If the new version is 1.25 or greater, set the PSP Policy to 'RKE2 Default' (empty string)
1795
+ if (major === 1 && minor >= 25) {
1796
+ set(this.value.spec, 'defaultPodSecurityPolicyTemplateName', '');
1797
+ } else {
1798
+ const previous = VERSION.parse(this.previousKubernetesVersion);
1799
+ const major = parseInt(previous?.[0] || 0);
1800
+ const minor = parseInt(previous?.[1] || 0);
1801
+
1802
+ if (major === 1 && minor >= 25) {
1803
+ // Previous value was 1.25 or greater, so reset back
1804
+ set(this.value.spec, 'defaultPodSecurityPolicyTemplateName', this.lastDefaultPodSecurityPolicyTemplateName);
1805
+ }
1806
+ }
1807
+
1808
+ this.previousKubernetesVersion = value;
1809
+ set(this.value.spec, 'defaultPodSecurityAdmissionConfigurationTemplateName', '');
1810
+ }
1811
+ },
1812
+
1813
+ /**
1814
+ * Handle PSP changes side effects, like PSA resets
1815
+ */
1816
+ handlePspChange(value) {
1817
+ if (value) {
1818
+ this.lastDefaultPodSecurityPolicyTemplateName = value;
1819
+ }
1820
+ },
1821
+
1626
1822
  },
1627
1823
  };
1628
1824
  </script>
@@ -1652,12 +1848,14 @@ export default {
1652
1848
  @cancel="cancel"
1653
1849
  @error="fvUnreportedValidationErrors"
1654
1850
  >
1655
- <Banner
1656
- v-if="isEdit"
1657
- color="warning"
1658
- >
1659
- <span v-html="t('cluster.banner.rke2-k3-reprovisioning', {}, true)" />
1660
- </Banner>
1851
+ <div class="header-warnings">
1852
+ <Banner
1853
+ v-if="isEdit"
1854
+ color="warning"
1855
+ >
1856
+ <span v-html="t('cluster.banner.rke2-k3-reprovisioning', {}, true)" />
1857
+ </Banner>
1858
+ </div>
1661
1859
  <SelectCredential
1662
1860
  v-if="needCredential"
1663
1861
  v-model="credentialId"
@@ -1690,6 +1888,7 @@ export default {
1690
1888
  {{ appsOSWarning }}
1691
1889
  </Banner>
1692
1890
 
1891
+ <!-- Pools Extras -->
1693
1892
  <template v-if="hasMachinePools">
1694
1893
  <div class="clearfix">
1695
1894
  <h2
@@ -1723,6 +1922,7 @@ export default {
1723
1922
  </div>
1724
1923
  </div>
1725
1924
 
1925
+ <!-- Extra Tabs for Machine Pool -->
1726
1926
  <Tabbed
1727
1927
  ref="pools"
1728
1928
  :side-tabs="true"
@@ -1752,17 +1952,19 @@ export default {
1752
1952
  </Tab>
1753
1953
  </template>
1754
1954
  <div v-if="!unremovedMachinePools.length">
1755
- You do not have any machine pools defined, click the plus to add one.
1955
+ {{ t('cluster.machinePool.noPoolsDisclaimer') }}
1756
1956
  </div>
1757
1957
  </Tabbed>
1758
1958
  <div class="spacer" />
1759
1959
  </template>
1760
1960
 
1961
+ <!-- Cluster Tabs -->
1761
1962
  <h2 v-t="'cluster.tabs.cluster'" />
1762
1963
  <Tabbed
1763
1964
  :side-tabs="true"
1764
1965
  class="min-height"
1765
1966
  >
1967
+ <!-- Basic -->
1766
1968
  <Tab
1767
1969
  name="basic"
1768
1970
  label-key="cluster.tabs.basic"
@@ -1772,7 +1974,7 @@ export default {
1772
1974
  <Banner
1773
1975
  v-if="!haveArgInfo"
1774
1976
  color="warning"
1775
- label="Configuration information is not available for the selected Kubernetes version. The options available in this screen will be limited, you may want to use the YAML editor."
1977
+ :label="t('cluster.banner.haveArgInfo')"
1776
1978
  />
1777
1979
  <Banner
1778
1980
  v-if="showk8s21LegacyWarning"
@@ -1794,6 +1996,7 @@ export default {
1794
1996
  :mode="mode"
1795
1997
  :options="versionOptions"
1796
1998
  label-key="cluster.kubernetesVersion.label"
1999
+ @input="handleKubernetesChange($event)"
1797
2000
  />
1798
2001
  <Checkbox
1799
2002
  v-model="showDeprecatedPatchVersions"
@@ -1868,16 +2071,56 @@ export default {
1868
2071
  <h3>
1869
2072
  {{ t('cluster.rke2.security.header') }}
1870
2073
  </h3>
1871
- <div class="row">
2074
+ <Banner
2075
+ v-if="isEdit && displayInvalidPspsBanner"
2076
+ color="warning"
2077
+ >
2078
+ <span v-html="t('cluster.banner.invalidPsps', {}, true)" />
2079
+ </Banner>
2080
+ <Banner
2081
+ v-else-if="isCreate && !needsPSP"
2082
+ color="info"
2083
+ >
2084
+ <span v-html="t('cluster.banner.removedPsp', {}, true)" />
2085
+ </Banner>
2086
+ <Banner
2087
+ v-else-if="isCreate"
2088
+ color="info"
2089
+ >
2090
+ <span v-html="t('cluster.banner.deprecatedPsp', {}, true)" />
2091
+ </Banner>
2092
+ <div
2093
+ v-if="needsPSA"
2094
+ class="row mb-10"
2095
+ >
1872
2096
  <div class="col span-6">
2097
+ <!-- PSA template selector -->
2098
+ <LabeledSelect
2099
+ v-model="value.spec.defaultPodSecurityAdmissionConfigurationTemplateName"
2100
+ :mode="mode"
2101
+ data-testid="rke2-custom-edit-psa"
2102
+ :options="psaOptions"
2103
+ :label="t('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.label')"
2104
+ />
2105
+ </div>
2106
+ </div>
2107
+
2108
+ <div class="row">
2109
+ <div
2110
+ v-if="pspOptions && needsPSP"
2111
+ class="col span-6"
2112
+ >
2113
+ <!-- PSP template selector -->
1873
2114
  <LabeledSelect
1874
- v-if="pspOptions"
1875
2115
  v-model="value.spec.defaultPodSecurityPolicyTemplateName"
2116
+ data-testid="rke2-custom-edit-psp"
1876
2117
  :mode="mode"
1877
2118
  :options="pspOptions"
1878
2119
  :label="t('cluster.rke2.defaultPodSecurityPolicyTemplateName.label')"
2120
+ @input="handlePspChange($event)"
1879
2121
  />
1880
2122
  </div>
2123
+
1881
2124
  <div
1882
2125
  v-if="showCisProfile"
1883
2126
  class="col span-6"
@@ -1894,7 +2137,8 @@ export default {
1894
2137
  v-model="agentConfig.profile"
1895
2138
  :mode="mode"
1896
2139
  :options="profileOptions"
1897
- label="Worker CIS Profile"
2140
+ :label="t('cis.workerProfile')"
2141
+ @input="updateCisProfile"
1898
2142
  />
1899
2143
  </div>
1900
2144
  </div>
@@ -1951,6 +2195,7 @@ export default {
1951
2195
  </div>
1952
2196
  </Tab>
1953
2197
 
2198
+ <!-- Member Roles -->
1954
2199
  <Tab
1955
2200
  v-if="canManageMembers"
1956
2201
  name="memberRoles"
@@ -1970,6 +2215,7 @@ export default {
1970
2215
  />
1971
2216
  </Tab>
1972
2217
 
2218
+ <!-- etcd -->
1973
2219
  <Tab
1974
2220
  name="etcd"
1975
2221
  label-key="cluster.tabs.etcd"
@@ -2047,6 +2293,7 @@ export default {
2047
2293
  </div>
2048
2294
  </Tab>
2049
2295
 
2296
+ <!-- Networking -->
2050
2297
  <Tab
2051
2298
  v-if="haveArgInfo"
2052
2299
  name="networking"
@@ -2148,6 +2395,7 @@ export default {
2148
2395
  />
2149
2396
  </Tab>
2150
2397
 
2398
+ <!-- Upgrade -->
2151
2399
  <Tab
2152
2400
  name="upgrade"
2153
2401
  label-key="cluster.tabs.upgrade"
@@ -2192,55 +2440,91 @@ export default {
2192
2440
  </div>
2193
2441
  </Tab>
2194
2442
 
2443
+ <!-- Registries -->
2195
2444
  <Tab
2196
2445
  name="registry"
2197
2446
  label-key="cluster.tabs.registry"
2198
2447
  >
2199
- <RadioGroup
2200
- v-model="registryMode"
2201
- name="registry-mode"
2202
- :options="registryOptions"
2203
- :mode="mode"
2204
- />
2205
-
2206
- <LabeledInput
2207
- v-if="registryMode !== PUBLIC"
2208
- v-model="registryHost"
2209
- class="mt-20"
2210
- :mode="mode"
2211
- :required="true"
2212
- :label="t('cluster.privateRegistry.systemDefaultRegistry.label')"
2213
- />
2214
-
2215
- <SelectOrCreateAuthSecret
2216
- v-if="registryMode === PRIVATE"
2217
- v-model="registrySecret"
2218
- :register-before-hook="registerBeforeHook"
2219
- :hook-priority="1"
2220
- :mode="mode"
2221
- in-store="management"
2222
- :allow-ssh="false"
2223
- :allow-rke="true"
2224
- :vertical="true"
2225
- :namespace="value.metadata.namespace"
2226
- generate-name="registryconfig-auth-"
2227
- />
2228
- <template v-else-if="registryMode === ADVANCED">
2229
- <RegistryMirrors
2230
- v-model="value"
2231
- class="mt-20"
2232
- :mode="mode"
2233
- />
2234
-
2235
- <RegistryConfigs
2236
- v-model="value"
2237
- class="mt-20"
2238
- :mode="mode"
2239
- :cluster-register-before-hook="registerBeforeHook"
2448
+ <div class="row">
2449
+ <h3>Registry for Rancher System Container Images</h3>
2450
+ </div>
2451
+ <div class="row">
2452
+ <div class="col span-12">
2453
+ <Banner
2454
+ :closable="false"
2455
+ class="cluster-tools-tip"
2456
+ color="info"
2457
+ label-key="cluster.privateRegistry.description"
2458
+ />
2459
+ </div>
2460
+ </div>
2461
+ <div class="row">
2462
+ <Checkbox
2463
+ v-model="showCustomRegistryInput"
2464
+ class="mb-20"
2465
+ :label="t('cluster.privateRegistry.label')"
2466
+ @input="toggleCustomRegistry"
2240
2467
  />
2468
+ </div>
2469
+ <div
2470
+ v-if="showCustomRegistryInput"
2471
+ class="row"
2472
+ >
2473
+ <div class="col span-6">
2474
+ <LabeledInput
2475
+ v-model="registryHost"
2476
+ label-key="catalog.chart.registry.custom.inputLabel"
2477
+ placeholder-key="catalog.chart.registry.custom.placeholder"
2478
+ :min-height="30"
2479
+ />
2480
+ <SelectOrCreateAuthSecret
2481
+ v-model="registrySecret"
2482
+ :register-before-hook="registerBeforeHook"
2483
+ :hook-priority="1"
2484
+ :mode="mode"
2485
+ in-store="management"
2486
+ :allow-ssh="false"
2487
+ :allow-rke="true"
2488
+ :vertical="true"
2489
+ :namespace="value.metadata.namespace"
2490
+ generate-name="registryconfig-auth-"
2491
+ />
2492
+ </div>
2493
+ </div>
2494
+ <template>
2495
+ <div
2496
+ v-if="showCustomRegistryInput"
2497
+ class="row"
2498
+ >
2499
+ <AdvancedSection
2500
+ class="col span-12 advanced"
2501
+ :is-open-by-default="showCustomRegistryAdvancedInput"
2502
+ :mode="mode"
2503
+ >
2504
+ <Banner
2505
+ :closable="false"
2506
+ class="cluster-tools-tip"
2507
+ color="info"
2508
+ :label-key="isK3s ? 'cluster.privateRegistry.docsLinkK3s' : 'cluster.privateRegistry.docsLinkRke2'"
2509
+ />
2510
+ <RegistryMirrors
2511
+ v-model="value"
2512
+ class="mt-20"
2513
+ :mode="mode"
2514
+ />
2515
+ <RegistryConfigs
2516
+ v-model="value"
2517
+ class="mt-20"
2518
+ :mode="mode"
2519
+ :cluster-register-before-hook="registerBeforeHook"
2520
+ @updateConfigs="updateConfigs"
2521
+ />
2522
+ </AdvancedSection>
2523
+ </div>
2241
2524
  </template>
2242
2525
  </Tab>
2243
2526
 
2527
+ <!-- Add-on Config -->
2244
2528
  <Tab
2245
2529
  name="addons"
2246
2530
  label-key="cluster.tabs.addons"
@@ -2304,6 +2588,7 @@ export default {
2304
2588
  </div>
2305
2589
  </Tab>
2306
2590
 
2591
+ <!-- Advanced -->
2307
2592
  <Tab
2308
2593
  v-if="haveArgInfo || agentArgs['protect-kernel-defaults']"
2309
2594
  name="advanced"
@@ -2420,4 +2705,7 @@ export default {
2420
2705
  .patch-version {
2421
2706
  margin-top: 5px;
2422
2707
  }
2708
+ .header-warnings .banner {
2709
+ margin-bottom: 0;
2710
+ }
2423
2711
  </style>