@rancher/shell 0.3.4 → 0.3.5

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 (246) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +14 -1
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-routes.ts +23 -0
  86. package/creators/app/app.package.json +2 -1
  87. package/creators/app/files/.eslintrc.js +1 -1
  88. package/creators/app/files/babel.config.js +1 -18
  89. package/creators/app/files/vue.config.js +7 -0
  90. package/creators/app/init +5 -5
  91. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  92. package/creators/pkg/init +35 -4
  93. package/creators/update/init +1 -1
  94. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  95. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  96. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  97. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  98. package/detail/workload/index.vue +3 -3
  99. package/dialog/AddClusterMemberDialog.vue +1 -1
  100. package/dialog/AddProjectMemberDialog.vue +2 -2
  101. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  102. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  103. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  104. package/dialog/GenericPrompt.vue +18 -6
  105. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  106. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  107. package/dialog/ScaleMachineDownDialog.vue +1 -1
  108. package/edit/auth/github.vue +8 -8
  109. package/edit/auth/googleoauth.vue +5 -5
  110. package/edit/auth/ldap/index.vue +1 -1
  111. package/edit/auth/oidc.vue +1 -1
  112. package/edit/auth/saml.vue +1 -1
  113. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  114. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  115. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  116. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  117. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  118. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  119. package/edit/management.cattle.io.setting.vue +1 -1
  120. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  121. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  122. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  124. package/edit/namespace.vue +2 -2
  125. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  126. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  127. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  128. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  129. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  130. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  131. package/edit/resources.cattle.io.backup.vue +1 -1
  132. package/edit/service.vue +1 -1
  133. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  134. package/edit/workload/__tests__/Job.test.ts +3 -1
  135. package/edit/workload/index.vue +8 -3
  136. package/edit/workload/mixins/workload.js +16 -0
  137. package/layouts/default.vue +7 -3
  138. package/list/fleet.cattle.io.bundle.vue +6 -3
  139. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  140. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  141. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  142. package/list/node.vue +69 -16
  143. package/list/provisioning.cattle.io.cluster.vue +30 -1
  144. package/machine-config/azure.vue +97 -38
  145. package/middleware/authenticated.js +34 -0
  146. package/mixins/chart.js +73 -2
  147. package/mixins/resource-fetch.js +2 -2
  148. package/models/apps.statefulset.js +28 -0
  149. package/models/cluster/node.js +23 -2
  150. package/models/cluster.x-k8s.io.machine.js +4 -2
  151. package/models/clusterroletemplatebinding.js +7 -0
  152. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  153. package/models/fleet.cattle.io.cluster.js +19 -10
  154. package/models/fleet.cattle.io.gitrepo.js +7 -2
  155. package/models/management.cattle.io.cluster.js +1 -1
  156. package/models/management.cattle.io.fleetworkspace.js +12 -0
  157. package/models/management.cattle.io.gitreporestriction.js +5 -0
  158. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  159. package/models/provisioning.cattle.io.cluster.js +7 -5
  160. package/nuxt/App.js +210 -0
  161. package/nuxt/axios.js +186 -0
  162. package/nuxt/client.js +817 -0
  163. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  164. package/nuxt/components/nuxt-child.js +122 -0
  165. package/nuxt/components/nuxt-error.vue +98 -0
  166. package/nuxt/components/nuxt-link.client.js +98 -0
  167. package/nuxt/components/nuxt-link.server.js +16 -0
  168. package/nuxt/components/nuxt-loading.vue +154 -0
  169. package/nuxt/components/nuxt.js +101 -0
  170. package/nuxt/cookie-universal-nuxt.js +9 -0
  171. package/nuxt/empty.js +1 -0
  172. package/nuxt/index.js +365 -0
  173. package/nuxt/jsonp.js +82 -0
  174. package/nuxt/loading.html +39 -0
  175. package/nuxt/middleware.js +12 -0
  176. package/nuxt/mixins/fetch.client.js +90 -0
  177. package/nuxt/mixins/fetch.server.js +69 -0
  178. package/nuxt/portal-vue.js +4 -0
  179. package/nuxt/server.js +312 -0
  180. package/nuxt/store.js +178 -0
  181. package/nuxt/utils.js +630 -0
  182. package/nuxt/views/app.template.html +9 -0
  183. package/nuxt/views/error.html +23 -0
  184. package/package.json +5 -9
  185. package/pages/auth/setup.vue +2 -2
  186. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  187. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  188. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  189. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  190. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  191. package/pages/c/_cluster/explorer/index.vue +29 -25
  192. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  193. package/pages/c/_cluster/fleet/index.vue +95 -34
  194. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  195. package/pages/c/_cluster/istio/index.vue +5 -5
  196. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  197. package/pages/c/_cluster/monitoring/index.vue +7 -0
  198. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  199. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  201. package/pages/home.vue +9 -4
  202. package/pages/index.vue +10 -1
  203. package/plugins/clean-html-directive.js +31 -0
  204. package/plugins/dashboard-store/actions.js +32 -9
  205. package/plugins/dashboard-store/mutations.js +5 -2
  206. package/plugins/dashboard-store/resource-class.js +8 -1
  207. package/plugins/steve/mutations.js +3 -2
  208. package/plugins/steve/steve-description-class.js +5 -1
  209. package/plugins/steve/subscribe.js +63 -54
  210. package/plugins/steve-create-worker.js +14 -0
  211. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  212. package/promptRemove/management.cattle.io.project.vue +2 -2
  213. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  214. package/promptRemove/pod.vue +1 -1
  215. package/public/index.html +65 -0
  216. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  217. package/rancher-components/components/Banner/Banner.vue +1 -1
  218. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  219. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  220. package/scripts/build-pkg.sh +1 -0
  221. package/scripts/clean +6 -0
  222. package/scripts/extension/bundle +58 -0
  223. package/scripts/extension/helmpatch +89 -0
  224. package/scripts/extension/publish +314 -0
  225. package/scripts/test-plugins-build.sh +4 -0
  226. package/store/__tests__/index.test.ts +110 -0
  227. package/store/index.js +145 -58
  228. package/store/type-map.js +5 -1
  229. package/tsconfig.default.json +36 -0
  230. package/tsconfig.json +24 -0
  231. package/types/shell/index.d.ts +420 -343
  232. package/utils/__tests__/string.test.ts +12 -0
  233. package/utils/auth.js +65 -0
  234. package/utils/monitoring.js +2 -1
  235. package/utils/position.js +5 -8
  236. package/utils/router.scrollBehavior.js +80 -0
  237. package/utils/select.js +1 -3
  238. package/utils/socket.js +1 -0
  239. package/utils/string.js +13 -0
  240. package/utils/time.js +9 -0
  241. package/vue.config.js +679 -0
  242. package/chart/rancher-alerting-drivers.vue +0 -53
  243. package/chart/rancher-gatekeeper.vue +0 -37
  244. package/creators/app/files/nuxt.config.js +0 -6
  245. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  246. package/nuxt.config.js +0 -798
@@ -15,6 +15,7 @@ import {
15
15
  DEFAULT_WORKSPACE,
16
16
  SECRET,
17
17
  HCI,
18
+ PSPS,
18
19
  } from '@shell/config/types';
19
20
  import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
20
21
 
@@ -129,6 +130,9 @@ export default {
129
130
  },
130
131
 
131
132
  async fetch() {
133
+ // Check presence of PSP in RKE2, which is where we show the templates
134
+ this.psps = await this.checkPsps();
135
+
132
136
  if ( !this.rke2Versions ) {
133
137
  const hash = {
134
138
  rke2Versions: this.$store.dispatch('management/request', { url: '/v1-rke2-release/releases' }),
@@ -312,14 +316,17 @@ export default {
312
316
  path: 'metadata.name', rules: ['subDomain'], translationKey: 'nameNsDescription.name.label'
313
317
  }],
314
318
  harvesterVersionRange: {},
315
- lastDefaultPodSecurityPolicyTemplateName,
319
+ lastDefaultPodSecurityPolicyTemplateName, // Used for reset on k8s version changes
316
320
  previousKubernetesVersion,
317
- harvesterVersion: ''
321
+ cisOverride: false,
322
+ cisPsaChangeBanner: false,
323
+ psps: null, // List of policies if any
318
324
  };
319
325
  },
320
326
 
321
327
  computed: {
322
328
  ...mapGetters({ allCharts: 'catalog/charts' }),
329
+ ...mapGetters(['currentCluster']),
323
330
  ...mapGetters({ features: 'features/get' }),
324
331
 
325
332
  PUBLIC: () => PUBLIC,
@@ -330,6 +337,13 @@ export default {
330
337
  return this.value.spec.rkeConfig;
331
338
  },
332
339
 
340
+ /**
341
+ * Check presence of PSPs as template or CLI creation
342
+ */
343
+ hasPsps() {
344
+ return !!this.psps?.count;
345
+ },
346
+
333
347
  isElementalCluster() {
334
348
  return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
335
349
  },
@@ -353,7 +367,7 @@ export default {
353
367
  },
354
368
 
355
369
  /**
356
- * Return need of PSA if RKE and min k8s version
370
+ * Define introduction of PSA and return need of PSA templates based on min k8s version
357
371
  */
358
372
  needsPSA() {
359
373
  const release = this.value?.spec?.kubernetesVersion || '';
@@ -364,22 +378,18 @@ export default {
364
378
  },
365
379
 
366
380
  /**
367
- * Restrict use of PSP based on min k8s version
381
+ * Define PSP deprecation and restrict use of PSP based on min k8s version
368
382
  */
369
383
  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;
384
+ return this.getNeedsPSP();
375
385
  },
376
386
 
377
- // kubeletConfigs() {
378
- // return this.value.spec.rkeConfig.machineSelectorConfig.filter(x => !!x.machineLabelSelector);
379
- // },
380
387
  /**
381
- * Check if k8s release version used is RKE2 ^1.25
388
+ * Define introduction of Rancher defined PSA templates
382
389
  */
390
+ hasPsaTemplates() {
391
+ return !this.needsPSP;
392
+ },
383
393
 
384
394
  unsupportedSelectorConfig() {
385
395
  let global = 0;
@@ -416,8 +426,8 @@ export default {
416
426
  const existingRke2 = this.mode === _EDIT && cur.includes('rke2');
417
427
  const existingK3s = this.mode === _EDIT && cur.includes('k3s');
418
428
 
419
- let allValidRke2Versions = this.getAllOptionsAfterMinVersion(this.rke2Versions, (existingRke2 ? cur : null), this.defaultRke2);
420
- let allValidK3sVersions = this.getAllOptionsAfterMinVersion(this.k3sVersions, (existingK3s ? cur : null), this.defaultK3s);
429
+ let allValidRke2Versions = this.getAllOptionsAfterCurrentVersion(this.rke2Versions, (existingRke2 ? cur : null), this.defaultRke2);
430
+ let allValidK3sVersions = this.getAllOptionsAfterCurrentVersion(this.k3sVersions, (existingK3s ? cur : null), this.defaultK3s);
421
431
 
422
432
  if (!this.showDeprecatedPatchVersions) {
423
433
  // Normally, we only want to show the most recent patch version
@@ -452,8 +462,6 @@ export default {
452
462
 
453
463
  if ( existing ) {
454
464
  existing.disabled = false;
455
- } else {
456
- out.unshift({ label: `${ cur } (current)`, value: cur });
457
465
  }
458
466
  }
459
467
 
@@ -465,7 +473,7 @@ export default {
465
473
  },
466
474
 
467
475
  profileOptions() {
468
- const out = (this.agentArgs.profile?.options || []).map((x) => {
476
+ const out = (this.agentArgs?.profile?.options || []).map((x) => {
469
477
  return { label: x, value: x };
470
478
  });
471
479
 
@@ -477,6 +485,15 @@ export default {
477
485
  return out;
478
486
  },
479
487
 
488
+ /**
489
+ * Allow to display override if PSA is needed and profile is set
490
+ */
491
+ hasCisOverride() {
492
+ return (this.serverConfig?.profile || this.agentConfig?.profile) && this.needsPSA &&
493
+ // Also check other cases on when to display the override
494
+ this.hasPsaTemplates && this.showCisProfile && this.isCisSupported;
495
+ },
496
+
480
497
  pspOptions() {
481
498
  if ( this.isK3s ) {
482
499
  return null;
@@ -505,6 +522,24 @@ export default {
505
522
  return out;
506
523
  },
507
524
 
525
+ /**
526
+ * Disable PSA if CIS hardening is enabled, except override
527
+ */
528
+ isPsaDisabled() {
529
+ const cisValue = this.agentConfig?.profile || this.serverConfig?.profile;
530
+
531
+ return !(!cisValue || this.cisOverride) && this.hasPsaTemplates && this.isCisSupported;
532
+ },
533
+
534
+ /**
535
+ * Get the default label for the PSA template option
536
+ */
537
+ defaultPsaOptionLabel() {
538
+ const optionCase = !this.needsPSP && !this.isK3s ? 'default' : 'none';
539
+
540
+ return this.$store.getters['i18n/t'](`cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.option.${ optionCase }`);
541
+ },
542
+
508
543
  /**
509
544
  * Convert PSA templates into options, sorting and flagging if any selected
510
545
  */
@@ -513,7 +548,7 @@ export default {
513
548
  return [];
514
549
  }
515
550
  const out = [{
516
- label: this.$store.getters['i18n/t']('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.option'),
551
+ label: this.defaultPsaOptionLabel,
517
552
  value: ''
518
553
  }];
519
554
 
@@ -534,6 +569,15 @@ export default {
534
569
  return out;
535
570
  },
536
571
 
572
+ /**
573
+ * Check if current CIS profile is required and listed in the options
574
+ */
575
+ isCisSupported() {
576
+ const cisProfile = this.serverConfig.profile || this.agentConfig.profile;
577
+
578
+ return !cisProfile || this.profileOptions.map(option => option.value).includes(cisProfile);
579
+ },
580
+
537
581
  disableOptions() {
538
582
  return this.serverArgs.disable.options.map((value) => {
539
583
  return {
@@ -610,7 +654,7 @@ export default {
610
654
  },
611
655
 
612
656
  showCisProfile() {
613
- return (this.provider === 'custom' || this.isElementalCluster) && ( this.serverArgs.profile || this.agentArgs.profile );
657
+ return (this.provider === 'custom' || this.isElementalCluster) && ( this.serverArgs?.profile || this.agentArgs?.profile );
614
658
  },
615
659
 
616
660
  needCredential() {
@@ -816,7 +860,7 @@ export default {
816
860
  const first = all[0]?.value;
817
861
  const preferred = all.find(x => x.value === this.defaultRke2)?.value;
818
862
 
819
- const rke2 = this.getAllOptionsAfterMinVersion(this.rke2Versions, null);
863
+ const rke2 = this.getAllOptionsAfterCurrentVersion(this.rke2Versions, null);
820
864
  const showRke2 = rke2.length;
821
865
  let out;
822
866
 
@@ -903,7 +947,6 @@ export default {
903
947
  },
904
948
 
905
949
  isHarvesterIncompatible() {
906
- const CompareVersion = '<v1.2';
907
950
  let ccmRke2Version = (this.chartVersions['harvester-cloud-provider'] || {})['version'];
908
951
  let csiRke2Version = (this.chartVersions['harvester-csi-driver'] || {})['version'];
909
952
 
@@ -919,11 +962,7 @@ export default {
919
962
  }
920
963
 
921
964
  if (ccmVersion && csiVersion) {
922
- if (semver.satisfies(this.harvesterVersion, CompareVersion) || !(this.harvesterVersion || '').startsWith('v')) {
923
- // When harveste version is less than `CompareVersion`, compatibility is not determined,
924
- // At the same time, version numbers like this will not be checked: master-14bbee2c-head
925
- return false;
926
- } else if (semver.satisfies(ccmRke2Version, ccmVersion) &&
965
+ if (semver.satisfies(ccmRke2Version, ccmVersion) &&
927
966
  semver.satisfies(csiRke2Version, csiVersion)) {
928
967
  return false;
929
968
  } else {
@@ -933,19 +972,6 @@ export default {
933
972
  return false;
934
973
  }
935
974
  },
936
-
937
- displayInvalidPspsBanner() {
938
- const version = VERSION.parse(this.value.spec.kubernetesVersion);
939
-
940
- const major = parseInt(version?.[0] || 0);
941
- const minor = parseInt(version?.[1] || 0);
942
-
943
- if (major === 1 && minor >= 25) {
944
- return this.allPSPs?.length > 0;
945
- }
946
-
947
- return false;
948
- }
949
975
  },
950
976
 
951
977
  watch: {
@@ -1035,6 +1061,17 @@ export default {
1035
1061
  nlToBr,
1036
1062
  set,
1037
1063
 
1064
+ /**
1065
+ * Define PSP deprecation and restrict use of PSP based on min k8s version and current/edited mode
1066
+ */
1067
+ getNeedsPSP(value = this.value) {
1068
+ const release = value?.spec?.kubernetesVersion || '';
1069
+ const version = release.match(/\d+/g);
1070
+ const isRequiredVersion = version?.length ? +version[0] === 1 && +version[1] < 25 : false;
1071
+
1072
+ return isRequiredVersion;
1073
+ },
1074
+
1038
1075
  async initMachinePools(existing) {
1039
1076
  const out = [];
1040
1077
 
@@ -1264,7 +1301,27 @@ export default {
1264
1301
 
1265
1302
  showAddonConfirmation() {
1266
1303
  return new Promise((resolve, reject) => {
1267
- this.$store.dispatch('cluster/promptModal', { component: 'AddonConfigConfirmationDialog', resources: [value => resolve(value)] });
1304
+ this.$store.dispatch('cluster/promptModal', {
1305
+ component: 'AddonConfigConfirmationDialog',
1306
+ resources: [value => resolve(value)]
1307
+ });
1308
+ });
1309
+ },
1310
+
1311
+ /**
1312
+ * Inform user to remove PSP for current cluster due deprecation
1313
+ */
1314
+ showPspConfirmation() {
1315
+ return new Promise((resolve, reject) => {
1316
+ this.$store.dispatch('cluster/promptModal', {
1317
+ component: 'GenericPrompt',
1318
+ componentProps: {
1319
+ title: this.t('cluster.rke2.modal.pspChange.title'),
1320
+ body: this.t('cluster.rke2.modal.pspChange.body'),
1321
+ applyMode: 'continue',
1322
+ confirm: resolve
1323
+ },
1324
+ });
1268
1325
  });
1269
1326
  },
1270
1327
 
@@ -1273,7 +1330,16 @@ export default {
1273
1330
  clear(this.errors);
1274
1331
  }
1275
1332
 
1276
- if (this.isEdit && this.liveValue?.spec?.kubernetesVersion !== this.value?.spec?.kubernetesVersion) {
1333
+ const isEditVersion = this.isEdit && this.liveValue?.spec?.kubernetesVersion !== this.value?.spec?.kubernetesVersion;
1334
+ const hasPspManuallyAdded = !!this.value.spec.rkeConfig?.machineGlobalConfig?.['kube-apiserver-arg'];
1335
+
1336
+ if (isEditVersion && !this.needsPSP && hasPspManuallyAdded) {
1337
+ if (!await this.showPspConfirmation()) {
1338
+ return btnCb('cancelled');
1339
+ }
1340
+ }
1341
+
1342
+ if (isEditVersion) {
1277
1343
  const shouldContinue = await this.showAddonConfirmation();
1278
1344
 
1279
1345
  if (!shouldContinue) {
@@ -1350,6 +1416,11 @@ export default {
1350
1416
  return;
1351
1417
  }
1352
1418
 
1419
+ // Remove null profile on machineGlobalConfig - https://github.com/rancher/dashboard/issues/8480
1420
+ if (this.value.spec?.rkeConfig?.machineGlobalConfig?.profile === null) {
1421
+ delete this.value.spec.rkeConfig.machineGlobalConfig.profile;
1422
+ }
1423
+
1353
1424
  await this.save(btnCb);
1354
1425
  },
1355
1426
  // create a secret to reference the harvester cluster kubeconfig in rkeConfig
@@ -1496,7 +1567,7 @@ export default {
1496
1567
  }
1497
1568
  }
1498
1569
 
1499
- if ( !this.serverConfig.profile ) {
1570
+ if ( !this.serverConfig?.profile ) {
1500
1571
  set(this.serverConfig, 'profile', null);
1501
1572
  }
1502
1573
  },
@@ -1625,21 +1696,32 @@ export default {
1625
1696
  set(this.value.spec.rkeConfig.registries, 'configs', configs);
1626
1697
  },
1627
1698
 
1628
- getAllOptionsAfterMinVersion(versions, minVersion, defaultVersion) {
1699
+ getAllOptionsAfterCurrentVersion(versions, currentVersion, defaultVersion) {
1629
1700
  const out = (versions || []).filter(obj => !!obj.serverArgs).map((obj) => {
1630
1701
  let disabled = false;
1631
1702
  let experimental = false;
1703
+ let isCurrentVersion = false;
1704
+ let label = obj.id;
1632
1705
 
1633
- if ( minVersion ) {
1634
- disabled = compare(obj.id, minVersion) < 0;
1706
+ if ( currentVersion ) {
1707
+ disabled = compare(obj.id, currentVersion) < 0;
1708
+ isCurrentVersion = compare(obj.id, currentVersion) === 0;
1635
1709
  }
1636
1710
 
1637
1711
  if ( defaultVersion ) {
1638
1712
  experimental = compare(defaultVersion, obj.id) < 0;
1639
1713
  }
1640
1714
 
1715
+ if (isCurrentVersion) {
1716
+ label = `${ label } ${ this.t('cluster.kubernetesVersion.current') }`;
1717
+ }
1718
+
1719
+ if (experimental) {
1720
+ label = `${ label } ${ this.t('cluster.kubernetesVersion.experimental') }`;
1721
+ }
1722
+
1641
1723
  return {
1642
- label: obj.id + (experimental ? ` (${ this.t('cluster.kubernetesVersion.experimental') })` : ''),
1724
+ label,
1643
1725
  value: obj.id,
1644
1726
  sort: sortable(obj.id),
1645
1727
  serverArgs: obj.serverArgs,
@@ -1648,6 +1730,15 @@ export default {
1648
1730
  disabled,
1649
1731
  };
1650
1732
  });
1733
+
1734
+ if (currentVersion && !out.find(obj => obj.value === currentVersion)) {
1735
+ out.push({
1736
+ label: `${ currentVersion } ${ this.t('cluster.kubernetesVersion.current') }`,
1737
+ value: currentVersion,
1738
+ sort: sortable(currentVersion),
1739
+ });
1740
+ }
1741
+
1651
1742
  const sorted = sortBy(out, 'sort:desc');
1652
1743
 
1653
1744
  const mostRecentPatchVersions = this.getMostRecentPatchVersions(sorted);
@@ -1661,7 +1752,7 @@ export default {
1661
1752
 
1662
1753
  return {
1663
1754
  ...optionData,
1664
- label: `${ optionData.label } (${ this.t('cluster.kubernetesVersion.deprecated') })`
1755
+ label: `${ optionData.label } ${ this.t('cluster.kubernetesVersion.deprecated') }`
1665
1756
  };
1666
1757
  });
1667
1758
 
@@ -1699,7 +1790,7 @@ export default {
1699
1790
  const majorMinor = `${ semver.major(version.value) }.${ semver.minor(version.value) }`;
1700
1791
 
1701
1792
  // Always show current version, else show if we haven't shown anything for this major.minor version yet
1702
- if (version === currentVersion || mostRecentPatchVersions[majorMinor] === version.value) {
1793
+ if (version.value === currentVersion || mostRecentPatchVersions[majorMinor] === version.value) {
1703
1794
  return true;
1704
1795
  }
1705
1796
 
@@ -1757,10 +1848,7 @@ export default {
1757
1848
  const res = await this.$store.dispatch('cluster/request', { url: `${ url }/${ HCI.SETTING }s` });
1758
1849
 
1759
1850
  const version = (res?.data || []).find(s => s.id === 'harvester-csi-ccm-versions');
1760
- // get harvester server-version
1761
- const serverVersion = (res?.data || []).find(s => s.id === 'server-version');
1762
1851
 
1763
- this.harvesterVersion = serverVersion.value;
1764
1852
  if (version) {
1765
1853
  this.harvesterVersionRange = JSON.parse(version.value || version.default || '{}');
1766
1854
  } else {
@@ -1777,6 +1865,52 @@ export default {
1777
1865
  this.initRegistry();
1778
1866
  }
1779
1867
  },
1868
+
1869
+ /**
1870
+ * Check if current cluster has PSP enabled
1871
+ * Consider exclusively RKE2 provisioned clusters in edit mode
1872
+ */
1873
+ async checkPsps() {
1874
+ // As server returns 500 we exclude all the possible cases
1875
+ if (
1876
+ this.mode !== _CREATE &&
1877
+ !this.isK3s &&
1878
+ this.value.state !== 'reconciling' &&
1879
+ this.getNeedsPSP(this.liveValue) // We consider editing only possible PSP cases
1880
+ ) {
1881
+ const clusterId = this.value.mgmtClusterId;
1882
+ const url = `/k8s/clusters/${ clusterId }/v1/${ PSPS }`;
1883
+
1884
+ try {
1885
+ return await this.$store.dispatch('cluster/request', { url });
1886
+ } catch (error) {
1887
+ // PSP may not exists for this cluster and an error is returned without need to handle
1888
+ }
1889
+ }
1890
+ },
1891
+
1892
+ /**
1893
+ * Reset PSA on several input changes for given conditions
1894
+ */
1895
+ togglePsaDefault() {
1896
+ // This option is created from the server and is guaranteed to exist #8032
1897
+ const hardcodedTemplate = 'rancher-restricted';
1898
+ const cisValue = this.agentConfig?.profile || this.serverConfig?.profile;
1899
+
1900
+ if (!this.cisOverride) {
1901
+ if (this.hasPsaTemplates && cisValue) {
1902
+ set(this.value.spec, 'defaultPodSecurityAdmissionConfigurationTemplateName', hardcodedTemplate);
1903
+ }
1904
+
1905
+ this.cisPsaChangeBanner = this.hasPsaTemplates;
1906
+ }
1907
+ },
1908
+
1909
+ handleCisChange() {
1910
+ this.togglePsaDefault();
1911
+ this.updateCisProfile();
1912
+ },
1913
+
1780
1914
  updateCisProfile() {
1781
1915
  // If the user selects any Worker CIS Profile,
1782
1916
  // protect-kernel-defaults should be set to false
@@ -1795,6 +1929,7 @@ export default {
1795
1929
  */
1796
1930
  handleKubernetesChange(value) {
1797
1931
  if (value) {
1932
+ this.togglePsaDefault();
1798
1933
  const version = VERSION.parse(value);
1799
1934
  const major = parseInt(version?.[0] || 0);
1800
1935
  const minor = parseInt(version?.[1] || 0);
@@ -1856,7 +1991,7 @@ export default {
1856
1991
  v-if="isEdit"
1857
1992
  color="warning"
1858
1993
  >
1859
- <span v-html="t('cluster.banner.rke2-k3-reprovisioning', {}, true)" />
1994
+ <span v-clean-html="t('cluster.banner.rke2-k3-reprovisioning', {}, true)" />
1860
1995
  </Banner>
1861
1996
  </div>
1862
1997
  <SelectCredential
@@ -1989,7 +2124,7 @@ export default {
1989
2124
  color="warning"
1990
2125
  >
1991
2126
  <span
1992
- v-html="t('cluster.harvester.warning.cloudProvider.incompatible', null, true)"
2127
+ v-clean-html="t('cluster.harvester.warning.cloudProvider.incompatible', null, true)"
1993
2128
  />
1994
2129
  </Banner>
1995
2130
  <div class="row mb-10">
@@ -2075,40 +2210,29 @@ export default {
2075
2210
  {{ t('cluster.rke2.security.header') }}
2076
2211
  </h3>
2077
2212
  <Banner
2078
- v-if="isEdit && displayInvalidPspsBanner"
2213
+ v-if="isEdit && !needsPSP && hasPsps"
2079
2214
  color="warning"
2080
- >
2081
- <span v-html="t('cluster.banner.invalidPsps', {}, true)" />
2082
- </Banner>
2215
+ :label="t('cluster.banner.invalidPsps')"
2216
+ />
2083
2217
  <Banner
2084
2218
  v-else-if="isCreate && !needsPSP"
2085
2219
  color="info"
2086
- >
2087
- <span v-html="t('cluster.banner.removedPsp', {}, true)" />
2088
- </Banner>
2220
+ :label="t('cluster.banner.removedPsp')"
2221
+ />
2222
+ <Banner
2223
+ v-else-if="isCreate && hasPsps"
2224
+ color="info"
2225
+ :label="t('cluster.banner.deprecatedPsp')"
2226
+ />
2227
+
2089
2228
  <Banner
2090
- v-else-if="isCreate"
2229
+ v-if="showCisProfile && !isCisSupported && isEdit"
2091
2230
  color="info"
2092
2231
  >
2093
- <span v-html="t('cluster.banner.deprecatedPsp', {}, true)" />
2232
+ <p v-clean-html="t('cluster.rke2.banner.cisUnsupported', {cisProfile: serverConfig.profile || agentConfig.profile}, true)" />
2094
2233
  </Banner>
2095
- <div
2096
- v-if="needsPSA"
2097
- class="row mb-10"
2098
- >
2099
- <div class="col span-6">
2100
- <!-- PSA template selector -->
2101
- <LabeledSelect
2102
- v-model="value.spec.defaultPodSecurityAdmissionConfigurationTemplateName"
2103
- :mode="mode"
2104
- data-testid="rke2-custom-edit-psa"
2105
- :options="psaOptions"
2106
- :label="t('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.label')"
2107
- />
2108
- </div>
2109
- </div>
2110
2234
 
2111
- <div class="row">
2235
+ <div class="row mb-10">
2112
2236
  <div
2113
2237
  v-if="pspOptions && needsPSP"
2114
2238
  class="col span-6"
@@ -2129,22 +2253,62 @@ export default {
2129
2253
  class="col span-6"
2130
2254
  >
2131
2255
  <LabeledSelect
2132
- v-if="serverArgs.profile"
2256
+ v-if="serverArgs && serverArgs.profile"
2133
2257
  v-model="serverConfig.profile"
2134
2258
  :mode="mode"
2135
2259
  :options="profileOptions"
2136
- label="Server CIS Profile"
2260
+ :label="t('cluster.rke2.cis.sever')"
2261
+ @input="handleCisChange"
2137
2262
  />
2138
2263
  <LabeledSelect
2139
- v-else-if="agentArgs.profile"
2264
+ v-else-if="agentArgs && agentArgs.profile"
2140
2265
  v-model="agentConfig.profile"
2266
+ data-testid="rke2-custom-edit-cis-agent"
2141
2267
  :mode="mode"
2142
2268
  :options="profileOptions"
2143
- :label="t('cis.workerProfile')"
2144
- @input="updateCisProfile"
2269
+ :label="t('cluster.rke2.cis.agent')"
2270
+ @input="handleCisChange"
2145
2271
  />
2146
2272
  </div>
2147
2273
  </div>
2274
+
2275
+ <template v-if="hasCisOverride">
2276
+ <Checkbox
2277
+ v-model="cisOverride"
2278
+ :mode="mode"
2279
+ :label="t('cluster.rke2.cis.override')"
2280
+ @input="togglePsaDefault"
2281
+ />
2282
+
2283
+ <Banner
2284
+ v-if="cisOverride"
2285
+ color="warning"
2286
+ :label="t('cluster.rke2.banner.cisOverride')"
2287
+ />
2288
+ <Banner
2289
+ v-if="cisPsaChangeBanner && !cisOverride"
2290
+ color="info"
2291
+ :label="t('cluster.rke2.banner.psaChange')"
2292
+ />
2293
+ </template>
2294
+
2295
+ <div
2296
+ v-if="needsPSA"
2297
+ class="row mb-10 mt-10"
2298
+ >
2299
+ <div class="col span-6">
2300
+ <!-- PSA template selector -->
2301
+ <LabeledSelect
2302
+ v-model="value.spec.defaultPodSecurityAdmissionConfigurationTemplateName"
2303
+ :mode="mode"
2304
+ data-testid="rke2-custom-edit-psa"
2305
+ :options="psaOptions"
2306
+ :disabled="isPsaDisabled"
2307
+ :label="t('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.label')"
2308
+ />
2309
+ </div>
2310
+ </div>
2311
+
2148
2312
  <div class="row">
2149
2313
  <div class="col span-12 mt-20">
2150
2314
  <Checkbox
@@ -296,7 +296,7 @@ export default {
296
296
  v-else
297
297
  color="error"
298
298
  >
299
- <span v-html="t('backupRestoreOperator.noResourceSet')" />
299
+ <span v-clean-html="t('backupRestoreOperator.noResourceSet')" />
300
300
  </Banner>
301
301
  </template>
302
302
  </CruResource>
package/edit/service.vue CHANGED
@@ -390,7 +390,7 @@ export default {
390
390
  <div class="row">
391
391
  <div class="col span-12">
392
392
  <Banner :color="(matchingPods.none ? 'warning' : 'success')">
393
- <span v-html="t('servicesPage.selectors.matchingPods.matchesSome', matchingPods)" />
393
+ <span v-clean-html="t('servicesPage.selectors.matchingPods.matchesSome', matchingPods)" />
394
394
  </Banner>
395
395
  </div>
396
396
  </div>
@@ -45,10 +45,10 @@ export default {
45
45
  ...mapGetters(['currentCluster']),
46
46
 
47
47
  isSatisfiesVersion() {
48
- const kubernetesVersion = this.currentCluster.kubernetesVersion;
48
+ const kubernetesVersion = this.currentCluster.kubernetesVersion || '';
49
49
  const kubernetesVersionExtension = this.currentCluster.kubernetesVersionExtension;
50
50
 
51
- if (kubernetesVersionExtension.startsWith('rke2')) {
51
+ if (kubernetesVersionExtension.startsWith('+rke2')) {
52
52
  const charts = ((this.rke2Versions?.data || []).find(v => v.id === kubernetesVersion) || {}).charts;
53
53
  let csiVersion = charts?.['harvester-csi-driver']?.version || '';
54
54
 
@@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils';
2
2
  import Job from '@shell/edit/workload/Job.vue';
3
3
  import { _EDIT } from '@shell/config/query-params';
4
4
  import { WORKLOAD_TYPES } from '@shell/config/types';
5
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
5
6
 
6
7
  describe('component: Job', () => {
7
8
  describe('given CronJob types', () => {
@@ -10,7 +11,8 @@ describe('component: Job', () => {
10
11
  'failed',
11
12
  ])('should emit an update on %p input', (field) => {
12
13
  const wrapper = mount(Job, {
13
- propsData: {
14
+ directives: { cleanHtmlDirective },
15
+ propsData: {
14
16
  mode: _EDIT,
15
17
  type: WORKLOAD_TYPES.CRON_JOB
16
18
  }
@@ -36,9 +36,15 @@ export default {
36
36
  * Find error exceptions to be mapped for each case
37
37
  */
38
38
  mapError(error) {
39
+ const isObject = error && typeof error === 'object' && !Array.isArray(error);
40
+ // We have just 2 cases, so we'll set a ternary operation:
41
+ // - one is for when we submit a YAML edited form (object - YAMLexceptions)
42
+ // - other is for a string message
43
+ const errorMessage = isObject ? error.message || '' : error || '';
44
+
39
45
  switch (true) {
40
- case error.includes('violates PodSecurity'): {
41
- const match = error.match(/\"(.*?)\"/gi);
46
+ case errorMessage.includes('violates PodSecurity'): {
47
+ const match = errorMessage.match(/\"(.*?)\"/gi);
42
48
  const name = match[0];
43
49
  const policy = match[1];
44
50
 
@@ -47,7 +53,6 @@ export default {
47
53
  icon: 'icon-pod_security'
48
54
  };
49
55
  }
50
-
51
56
  default:
52
57
  break;
53
58
  }