@rancher/shell 0.3.24 → 0.3.25

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 (111) hide show
  1. package/assets/styles/themes/_light.scss +1 -1
  2. package/assets/translations/en-us.yaml +29 -7
  3. package/assets/translations/zh-hans.yaml +1 -1
  4. package/components/ClusterIconMenu.vue +143 -0
  5. package/components/CruResource.vue +7 -1
  6. package/components/ExplorerProjectsNamespaces.vue +11 -1
  7. package/components/FixedBanner.vue +17 -1
  8. package/components/Markdown.vue +1 -1
  9. package/components/Questions/__tests__/Yaml.test.ts +3 -2
  10. package/components/SortableTable/index.vue +3 -2
  11. package/components/auth/RoleDetailEdit.vue +15 -2
  12. package/components/auth/login/saml.vue +12 -1
  13. package/components/form/LabeledSelect.vue +12 -5
  14. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  15. package/components/form/Members/MembershipEditor.vue +6 -1
  16. package/components/form/__tests__/KeyValue.test.ts +6 -3
  17. package/components/form/__tests__/LabeledSelect.test.ts +18 -0
  18. package/components/formatter/PodsUsage.vue +11 -36
  19. package/components/formatter/PrincipalGroupBindings.vue +8 -5
  20. package/components/formatter/__tests__/PodsUsage.test.ts +36 -19
  21. package/components/nav/Group.vue +25 -27
  22. package/components/nav/Header.vue +12 -5
  23. package/components/nav/Pinned.vue +47 -0
  24. package/components/nav/TopLevelMenu.vue +233 -60
  25. package/components/nav/Type.vue +57 -3
  26. package/config/home-links.js +1 -1
  27. package/config/product/istio.js +15 -5
  28. package/config/router.js +3 -9
  29. package/config/table-headers.js +5 -6
  30. package/config/uiplugins.js +1 -0
  31. package/core/plugin-helpers.js +3 -0
  32. package/core/types.ts +6 -1
  33. package/creators/app/files/.vscode/settings.json +0 -1
  34. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +118 -0
  35. package/detail/autoscaling.horizontalpodautoscaler/index.vue +4 -4
  36. package/detail/provisioning.cattle.io.cluster.vue +7 -5
  37. package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +58 -0
  38. package/edit/__tests__/namespace.test.ts +5 -3
  39. package/edit/management.cattle.io.clusterroletemplatebinding.vue +3 -11
  40. package/edit/namespace.vue +8 -4
  41. package/edit/provisioning.cattle.io.cluster/Basics.vue +662 -0
  42. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +6 -0
  43. package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +13 -8
  44. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -2
  45. package/edit/provisioning.cattle.io.cluster/MemberRoles.vue +40 -0
  46. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  47. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +71 -23
  48. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +52 -0
  49. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -142
  50. package/edit/provisioning.cattle.io.cluster/rke2.vue +194 -598
  51. package/edit/workload/storage/__tests__/Storage.test.ts +2 -2
  52. package/edit/workload/storage/persistentVolumeClaim/__tests__/persistentvolumeclaim.test.ts +36 -0
  53. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +15 -7
  54. package/initialize/index.js +5 -5
  55. package/layouts/default.vue +6 -6
  56. package/layouts/home.vue +6 -2
  57. package/layouts/plain.vue +9 -2
  58. package/list/fleet.cattle.io.cluster.vue +2 -2
  59. package/list/management.cattle.io.feature.vue +1 -1
  60. package/machine-config/vmwarevsphere.vue +48 -7
  61. package/mixins/brand.js +0 -8
  62. package/mixins/child-hook.js +2 -2
  63. package/mixins/create-edit-view/impl.js +3 -3
  64. package/models/__tests__/management.cattle.io.node.ts +96 -0
  65. package/models/__tests__/node.ts +74 -0
  66. package/models/cluster/node.js +6 -5
  67. package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
  68. package/models/management.cattle.io.cluster.js +22 -1
  69. package/models/management.cattle.io.clusterroletemplatebinding.js +3 -3
  70. package/models/management.cattle.io.globalrole.js +17 -2
  71. package/models/management.cattle.io.node.js +6 -4
  72. package/models/management.cattle.io.projectroletemplatebinding.js +3 -3
  73. package/models/management.cattle.io.roletemplate.js +17 -2
  74. package/package.json +2 -6
  75. package/pages/about.vue +2 -0
  76. package/pages/auth/setup.vue +5 -4
  77. package/pages/c/_cluster/monitoring/index.vue +8 -3
  78. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +9 -66
  79. package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +182 -0
  80. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +15 -32
  81. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +8 -46
  82. package/pages/c/_cluster/uiplugins/index.vue +64 -64
  83. package/pages/diagnostic.vue +0 -39
  84. package/pages/home.vue +1 -1
  85. package/plugins/dashboard-store/normalize.js +4 -4
  86. package/plugins/int-number.js +5 -2
  87. package/plugins/positive-int-number.js +19 -0
  88. package/plugins/steve/__tests__/getters.spec.ts +15 -0
  89. package/plugins/steve/getters.js +22 -10
  90. package/rancher-components/Form/LabeledInput/LabeledInput.vue +0 -8
  91. package/rancher-components/Form/Radio/RadioButton.test.ts +3 -7
  92. package/store/index.js +4 -0
  93. package/store/prefs.js +1 -0
  94. package/types/shell/index.d.ts +13 -4
  95. package/utils/__tests__/cluster.test.ts +55 -0
  96. package/utils/__tests__/object.test.ts +21 -2
  97. package/utils/cluster.js +47 -1
  98. package/utils/object.js +12 -5
  99. package/utils/validators/formRules/__tests__/index.test.ts +13 -1
  100. package/utils/validators/formRules/index.ts +4 -0
  101. package/utils/validators/role-template.js +9 -1
  102. package/utils/version.js +1 -1
  103. package/yarn-error.log +16 -16
  104. package/components/ClusterProviderIconMenu.vue +0 -161
  105. package/content/docs/en-us/getting-started.md +0 -224
  106. package/content/docs/en-us/whats-new.md +0 -29
  107. package/content/docs/zh-hans/getting-started.md +0 -224
  108. package/content/docs/zh-hans/whats-new.md +0 -28
  109. package/pages/docs/_doc.vue +0 -345
  110. package/pages/docs/toc.js +0 -27
  111. package/plugins/console.js +0 -34
@@ -3,7 +3,6 @@ import difference from 'lodash/difference';
3
3
  import throttle from 'lodash/throttle';
4
4
  import isArray from 'lodash/isArray';
5
5
  import merge from 'lodash/merge';
6
- import { mapGetters } from 'vuex';
7
6
  import CreateEditView from '@shell/mixins/create-edit-view';
8
7
  import FormValidation from '@shell/mixins/form-validation';
9
8
  import { normalizeName } from '@shell/utils/kube';
@@ -29,7 +28,7 @@ import {
29
28
  import { allHash } from '@shell/utils/promise';
30
29
  import { sortBy } from '@shell/utils/sort';
31
30
 
32
- import { camelToTitle, nlToBr } from '@shell/utils/string';
31
+ import { camelToTitle } from '@shell/utils/string';
33
32
  import { compare, sortable } from '@shell/utils/version';
34
33
  import { isHarvesterSatisfiesVersion } from '@shell/utils/cluster';
35
34
  import * as VERSION from '@shell/utils/version';
@@ -39,7 +38,7 @@ import ArrayListGrouped from '@shell/components/form/ArrayListGrouped';
39
38
  import { BadgeState } from '@components/BadgeState';
40
39
  import { Banner } from '@components/Banner';
41
40
  import { Checkbox } from '@components/Form/Checkbox';
42
- import CruResource from '@shell/components/CruResource';
41
+ import CruResource, { CONTEXT_HOOK_EDIT_YAML } from '@shell/components/CruResource';
43
42
  import { LabeledInput } from '@components/Form/LabeledInput';
44
43
  import LabeledSelect from '@shell/components/form/LabeledSelect';
45
44
  import Loading from '@shell/components/Loading';
@@ -52,9 +51,8 @@ import UnitInput from '@shell/components/form/UnitInput';
52
51
  import YamlEditor from '@shell/components/YamlEditor';
53
52
  import Questions from '@shell/components/Questions';
54
53
 
55
- import ClusterMembershipEditor, { canViewClusterMembershipEditor } from '@shell/components/form/Members/ClusterMembershipEditor';
54
+ import { canViewClusterMembershipEditor } from '@shell/components/form/Members/ClusterMembershipEditor';
56
55
  import SelectOrCreateAuthSecret from '@shell/components/form/SelectOrCreateAuthSecret';
57
- import { LEGACY } from '@shell/store/features';
58
56
  import semver from 'semver';
59
57
 
60
58
  import { SETTING } from '@shell/config/settings';
@@ -74,10 +72,8 @@ import { ELEMENTAL_SCHEMA_IDS, KIND, ELEMENTAL_CLUSTER_PROVIDER } from '../../co
74
72
  import AgentConfiguration from './AgentConfiguration';
75
73
  import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
76
74
  import { ExtensionPoint, TabLocation } from '@shell/core/types';
77
-
78
- const PUBLIC = 'public';
79
- const PRIVATE = 'private';
80
- const ADVANCED = 'advanced';
75
+ import MemberRoles from '@shell/edit/provisioning.cattle.io.cluster/MemberRoles';
76
+ import Basics from '@shell/edit/provisioning.cattle.io.cluster/Basics';
81
77
 
82
78
  const HARVESTER = 'harvester';
83
79
  const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
@@ -115,7 +111,6 @@ export default {
115
111
  Banner,
116
112
  Checkbox,
117
113
  AgentConfiguration,
118
- ClusterMembershipEditor,
119
114
  CruResource,
120
115
  DrainOptions,
121
116
  LabeledInput,
@@ -136,6 +131,8 @@ export default {
136
131
  Tabbed,
137
132
  UnitInput,
138
133
  YamlEditor,
134
+ MemberRoles,
135
+ Basics
139
136
  },
140
137
 
141
138
  mixins: [CreateEditView, FormValidation],
@@ -210,7 +207,6 @@ export default {
210
207
  lastIdx: 0,
211
208
  allPSPs: null,
212
209
  allPSAs: [],
213
- nodeComponent: null,
214
210
  credentialId: '',
215
211
  credential: null,
216
212
  machinePools: null,
@@ -251,21 +247,14 @@ export default {
251
247
  truncateLimit,
252
248
  busy: false,
253
249
  machinePoolValidation: {}, // map of validation states for each machine pool
250
+ machinePoolErrors: {},
254
251
  allNamespaces: [],
255
- initialCloudProvider: this.value?.agentConfig?.['cloud-provider-name'],
252
+ initialCloudProvider: this.value?.agentConfig?.['cloud-provider-name'] || '',
256
253
  extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.CLUSTER_CREATE_RKE2, this.$route, this),
257
254
  };
258
255
  },
259
256
 
260
257
  computed: {
261
- ...mapGetters({ allCharts: 'catalog/charts' }),
262
- ...mapGetters(['currentCluster']),
263
- ...mapGetters({ features: 'features/get' }),
264
- ...mapGetters(['namespaces']),
265
-
266
- PUBLIC: () => PUBLIC,
267
- PRIVATE: () => PRIVATE,
268
- ADVANCED: () => ADVANCED,
269
258
 
270
259
  rkeConfig() {
271
260
  return this.value.spec.rkeConfig;
@@ -275,13 +264,6 @@ export default {
275
264
  return this.truncateLimit && this.truncateLimit !== NETBIOS_TRUNCATION_LENGTH;
276
265
  },
277
266
 
278
- /**
279
- * Check presence of PSPs as template or CLI creation
280
- */
281
- hasPsps() {
282
- return !!this.psps?.count;
283
- },
284
-
285
267
  isElementalCluster() {
286
268
  return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
287
269
  },
@@ -304,17 +286,6 @@ export default {
304
286
  return this.value.agentConfig;
305
287
  },
306
288
 
307
- /**
308
- * Define introduction of PSA and return need of PSA templates based on min k8s version
309
- */
310
- needsPSA() {
311
- const release = this.value?.spec?.kubernetesVersion || '';
312
- const version = release.match(/\d+/g);
313
- const isRequiredVersion = version?.length ? +version[0] > 1 || +version[1] >= 23 : false;
314
-
315
- return isRequiredVersion;
316
- },
317
-
318
289
  /**
319
290
  * Define PSP deprecation and restrict use of PSP based on min k8s version
320
291
  */
@@ -410,196 +381,6 @@ export default {
410
381
  return (this.value?.spec?.kubernetesVersion || '').includes('k3s');
411
382
  },
412
383
 
413
- profileOptions() {
414
- const out = (this.agentArgs?.profile?.options || []).map((x) => {
415
- return { label: x, value: x };
416
- });
417
-
418
- out.unshift({
419
- label: this.$store.getters['i18n/t']('cluster.rke2.cisProfile.option'),
420
- value: ''
421
- });
422
-
423
- return out;
424
- },
425
-
426
- /**
427
- * Allow to display override if PSA is needed and profile is set
428
- */
429
- hasCisOverride() {
430
- return (this.serverConfig?.profile || this.agentConfig?.profile) && this.needsPSA &&
431
- // Also check other cases on when to display the override
432
- this.hasPsaTemplates && this.showCisProfile && this.isCisSupported;
433
- },
434
-
435
- pspOptions() {
436
- if ( this.isK3s ) {
437
- return null;
438
- }
439
-
440
- const out = [{
441
- label: this.$store.getters['i18n/t']('cluster.rke2.defaultPodSecurityPolicyTemplateName.option'),
442
- value: ''
443
- }];
444
-
445
- if ( this.allPSPs ) {
446
- for ( const pspt of this.allPSPs ) {
447
- out.push({
448
- label: pspt.nameDisplay,
449
- value: pspt.id,
450
- });
451
- }
452
- }
453
-
454
- const cur = this.value.spec.defaultPodSecurityPolicyTemplateName;
455
-
456
- if ( cur && !out.find((x) => x.value === cur) ) {
457
- out.unshift({ label: `${ cur } (Current)`, value: cur });
458
- }
459
-
460
- return out;
461
- },
462
-
463
- /**
464
- * Disable PSA if CIS hardening is enabled, except override
465
- */
466
- isPsaDisabled() {
467
- const cisValue = this.agentConfig?.profile || this.serverConfig?.profile;
468
-
469
- return !(!cisValue || this.cisOverride) && this.hasPsaTemplates && this.isCisSupported;
470
- },
471
-
472
- /**
473
- * Get the default label for the PSA template option
474
- */
475
- defaultPsaOptionLabel() {
476
- const optionCase = !this.needsPSP && !this.isK3s ? 'default' : 'none';
477
-
478
- return this.$store.getters['i18n/t'](`cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.option.${ optionCase }`);
479
- },
480
-
481
- /**
482
- * Convert PSA templates into options, sorting and flagging if any selected
483
- */
484
- psaOptions() {
485
- if ( !this.needsPSA ) {
486
- return [];
487
- }
488
- const out = [{
489
- label: this.defaultPsaOptionLabel,
490
- value: ''
491
- }];
492
-
493
- if ( this.allPSAs ) {
494
- for ( const psa of this.allPSAs ) {
495
- out.push({
496
- label: psa.nameDisplay,
497
- value: psa.id,
498
- });
499
- }
500
- }
501
- const cur = this.value.spec.defaultPodSecurityAdmissionConfigurationTemplateName;
502
-
503
- if ( cur && !out.find((x) => x.value === cur) ) {
504
- out.unshift({ label: `${ cur } (Current)`, value: cur });
505
- }
506
-
507
- return out;
508
- },
509
-
510
- /**
511
- * Check if current CIS profile is required and listed in the options
512
- */
513
- isCisSupported() {
514
- const cisProfile = this.serverConfig.profile || this.agentConfig.profile;
515
-
516
- return !cisProfile || this.profileOptions.map((option) => option.value).includes(cisProfile);
517
- },
518
-
519
- disableOptions() {
520
- return this.serverArgs.disable.options.map((value) => {
521
- return {
522
- label: this.$store.getters['i18n/withFallback'](`cluster.${ this.isK3s ? 'k3s' : 'rke2' }.systemService."${ value }"`, null, value.replace(/^(rke2|rancher)-/, '')),
523
- value,
524
- };
525
- });
526
- },
527
-
528
- cloudProviderOptions() {
529
- const out = [{
530
- label: this.$store.getters['i18n/t']('cluster.rke2.cloudProvider.defaultValue.label'),
531
- value: '',
532
- }];
533
-
534
- const preferred = this.$store.getters['plugins/cloudProviderForDriver'](this.provider);
535
-
536
- for ( const opt of this.agentArgs['cloud-provider-name'].options ) {
537
- // If we don't have a preferred provider... show all options
538
- const showAllOptions = preferred === undefined;
539
- // If we have a preferred provider... only show default, preferred and external
540
- const isPreferred = opt === preferred;
541
- const isExternal = opt === 'external';
542
- let disabled = false;
543
-
544
- if ((this.isHarvesterExternalCredential || this.isHarvesterIncompatible) && isPreferred) {
545
- disabled = true;
546
- }
547
-
548
- if (showAllOptions || isPreferred || isExternal) {
549
- out.push({
550
- label: this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ opt }".label`, null, opt),
551
- value: opt,
552
- disabled,
553
- });
554
- }
555
- }
556
-
557
- const cur = this.agentConfig['cloud-provider-name'];
558
-
559
- if (cur && !out.find((x) => x.value === cur)) {
560
- // Localization missing
561
- // Look up cur in the localization file
562
- const label = this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ cur }".label`, null, cur);
563
-
564
- out.unshift({
565
- label: `${ label } (Current)`,
566
- value: cur,
567
- unsupported: true,
568
- disabled: true
569
- });
570
- }
571
-
572
- const initial = this.initialCloudProvider;
573
-
574
- if (cur !== initial && initial && !out.find((x) => x.value === initial)) {
575
- const label = this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ initial }".label`, null, initial);
576
-
577
- out.unshift({
578
- label: `${ label } (Current)`,
579
- value: initial,
580
- unsupported: true,
581
- disabled: true
582
- });
583
- }
584
-
585
- return out;
586
- },
587
-
588
- unsupportedCloudProvider() {
589
- // The current cloud provider
590
- const cur = this.initialCloudProvider;
591
-
592
- const provider = cur && this.cloudProviderOptions.find((x) => x.value === cur);
593
-
594
- return !!provider?.unsupported;
595
- },
596
-
597
- canNotEditCloudProvider() {
598
- const canNotEdit = this.clusterIsAlreadyCreated && !this.unsupportedCloudProvider;
599
-
600
- return canNotEdit;
601
- },
602
-
603
384
  /**
604
385
  * Kube Version
605
386
  */
@@ -636,10 +417,6 @@ export default {
636
417
  return this.selectedVersion?.charts || {};
637
418
  },
638
419
 
639
- showCisProfile() {
640
- return (this.provider === 'custom' || this.isElementalCluster) && ( this.serverArgs?.profile || this.agentArgs?.profile );
641
- },
642
-
643
420
  needCredential() {
644
421
  if ( this.provider === 'custom' || this.provider === 'import' || this.isElementalCluster || this.mode === _VIEW ) {
645
422
  return false;
@@ -789,56 +566,12 @@ export default {
789
566
  return out;
790
567
  },
791
568
 
792
- enabledSystemServices: {
793
- get() {
794
- const out = difference(this.serverArgs.disable.options, this.serverConfig.disable || []);
795
-
796
- return out;
797
- },
798
-
799
- set(neu) {
800
- const out = difference(this.serverArgs.disable.options, neu);
801
-
802
- set(this.serverConfig, 'disable', out);
803
- },
804
- },
805
-
806
- showCloudConfigYaml() {
807
- if ( !this.agentArgs['cloud-provider-name'] ) {
808
- return false;
809
- }
810
-
811
- const name = this.agentConfig['cloud-provider-name'];
812
-
813
- if ( !name ) {
814
- return false;
815
- }
816
-
817
- switch ( name ) {
818
- case 'none': return false;
819
- case 'aws': return false;
820
- case 'rancher-vsphere': return false;
821
- case HARVESTER: return false;
822
- default: return true;
823
- }
824
- },
825
-
826
- showVsphereNote() {
827
- if ( !this.agentArgs['cloud-provider-name'] ) {
828
- return false;
829
- }
830
-
831
- const name = this.agentConfig['cloud-provider-name'];
832
-
833
- return name === 'rancher-vsphere';
834
- },
835
-
836
569
  showCni() {
837
570
  return !!this.serverArgs.cni;
838
571
  },
839
572
 
840
573
  showCloudProvider() {
841
- return this.agentArgs['cloud-provider-name'];
574
+ return !!this.agentArgs['cloud-provider-name'];
842
575
  },
843
576
 
844
577
  /**
@@ -878,15 +611,66 @@ export default {
878
611
  return versions.filter((x) => !!x);
879
612
  },
880
613
 
881
- showk8s21LegacyWarning() {
882
- const isLegacyEnabled = this.features(LEGACY);
614
+ cloudProviderOptions() {
615
+ const out = [{
616
+ label: this.$store.getters['i18n/t']('cluster.rke2.cloudProvider.defaultValue.label'),
617
+ value: '',
618
+ }];
883
619
 
884
- if (!isLegacyEnabled) {
885
- return false;
620
+ if ( !!this.agentArgs['cloud-provider-name']?.options ) {
621
+ const preferred = this.$store.getters['plugins/cloudProviderForDriver'](this.provider);
622
+
623
+ for ( const opt of this.agentArgs['cloud-provider-name']?.options ) {
624
+ // If we don't have a preferred provider... show all options
625
+ const showAllOptions = preferred === undefined;
626
+ // If we have a preferred provider... only show default, preferred and external
627
+ const isPreferred = opt === preferred;
628
+ const isExternal = opt === 'external';
629
+ let disabled = false;
630
+
631
+ if ((this.isHarvesterExternalCredential || this.isHarvesterIncompatible) && isPreferred) {
632
+ disabled = true;
633
+ }
634
+
635
+ if (showAllOptions || isPreferred || isExternal) {
636
+ out.push({
637
+ label: this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ opt }".label`, null, opt),
638
+ value: opt,
639
+ disabled,
640
+ });
641
+ }
642
+ }
643
+ }
644
+
645
+ const cur = this.agentConfig['cloud-provider-name'];
646
+
647
+ if (cur && !out.find((x) => x.value === cur)) {
648
+ // Localization missing
649
+ // Look up cur in the localization file
650
+ const label = this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ cur }".label`, null, cur);
651
+
652
+ out.unshift({
653
+ label: `${ label } (Current)`,
654
+ value: cur,
655
+ unsupported: true,
656
+ disabled: true
657
+ });
658
+ }
659
+
660
+ const initial = this.initialCloudProvider;
661
+
662
+ if (cur !== initial && initial && !out.find((x) => x.value === initial)) {
663
+ const label = this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ initial }".label`, null, initial);
664
+
665
+ out.unshift({
666
+ label: `${ label } (Current)`,
667
+ value: initial,
668
+ unsupported: true,
669
+ disabled: true
670
+ });
886
671
  }
887
- const selectedVersion = semver.coerce(this.value.spec.kubernetesVersion);
888
672
 
889
- return semver.satisfies(selectedVersion, '>=1.21.0');
673
+ return out;
890
674
  },
891
675
 
892
676
  canManageMembers() {
@@ -923,33 +707,6 @@ export default {
923
707
  return out;
924
708
  },
925
709
 
926
- ciliumIpv6: {
927
- get() {
928
- // eslint-disable-next-line no-unused-vars
929
- const cni = this.serverConfig.cni; // force this property to recalculate if cni was changed away from cilium and chartValues['rke-cilium'] deleted
930
-
931
- return this.userChartValues[this.chartVersionKey('rke2-cilium')]?.cilium?.ipv6?.enabled || false;
932
- },
933
- set(val) {
934
- const name = this.chartVersionKey('rke2-cilium');
935
- const values = this.userChartValues[name];
936
-
937
- set(this, 'userChartValues', {
938
- ...this.userChartValues,
939
- [name]: {
940
- ...values,
941
- cilium: {
942
- ...values?.cilium,
943
- ipv6: {
944
- ...values?.cilium?.ipv6,
945
- enabled: val
946
- }
947
- }
948
- }
949
- });
950
- }
951
- },
952
-
953
710
  showIpv6Warning() {
954
711
  const clusterCIDR = this.serverConfig['cluster-cidr'] || '';
955
712
  const serviceCIDR = this.serverConfig['service-cidr'] || '';
@@ -1025,6 +782,14 @@ export default {
1025
782
 
1026
783
  return validRequiredPools && base;
1027
784
  },
785
+ unsupportedCloudProvider() {
786
+ // The current cloud provider
787
+ const cur = this.initialCloudProvider;
788
+
789
+ const provider = cur && this.cloudProviderOptions.find((x) => x.value === cur);
790
+
791
+ return !!provider?.unsupported;
792
+ },
1028
793
  },
1029
794
 
1030
795
  watch: {
@@ -1096,11 +861,6 @@ export default {
1096
861
  set(this.agentConfig, 'cloud-provider-name', undefined);
1097
862
  }
1098
863
  },
1099
-
1100
- },
1101
-
1102
- mounted() {
1103
- window.rke = this;
1104
864
  },
1105
865
 
1106
866
  created() {
@@ -1116,7 +876,6 @@ export default {
1116
876
  },
1117
877
 
1118
878
  methods: {
1119
- nlToBr,
1120
879
  set,
1121
880
 
1122
881
  /**
@@ -1400,6 +1159,7 @@ export default {
1400
1159
  }
1401
1160
 
1402
1161
  const name = `pool${ ++this.lastIdx }`;
1162
+
1403
1163
  const pool = {
1404
1164
  id: name,
1405
1165
  config,
@@ -1420,6 +1180,7 @@ export default {
1420
1180
  kind: this.machineConfigSchema.attributes?.kind,
1421
1181
  name: null,
1422
1182
  },
1183
+ drainBeforeDelete: true
1423
1184
  },
1424
1185
  };
1425
1186
 
@@ -1472,7 +1233,11 @@ export default {
1472
1233
  }
1473
1234
  },
1474
1235
 
1475
- async saveMachinePools() {
1236
+ async saveMachinePools(hookContext) {
1237
+ if (hookContext === CONTEXT_HOOK_EDIT_YAML) {
1238
+ return;
1239
+ }
1240
+
1476
1241
  const finalPools = [];
1477
1242
 
1478
1243
  // If the extension provider wants to do this, let them
@@ -1865,16 +1630,6 @@ export default {
1865
1630
  this.syncChartValues(name);
1866
1631
  },
1867
1632
 
1868
- initQuestions(name) {
1869
- const defaultChartValue = this.versionInfo[name];
1870
- const startingChartValue = this.initYamlEditor(name);
1871
-
1872
- return {
1873
- ...defaultChartValue,
1874
- values: startingChartValue,
1875
- };
1876
- },
1877
-
1878
1633
  initYamlEditor(name) {
1879
1634
  const defaultChartValue = this.versionInfo[name];
1880
1635
  const key = this.chartVersionKey(name);
@@ -2305,6 +2060,9 @@ export default {
2305
2060
  this.lastDefaultPodSecurityPolicyTemplateName = value;
2306
2061
  },
2307
2062
 
2063
+ handleShowDeprecatedPatchVersionsChanged(value) {
2064
+ this.showDeprecatedPatchVersions = value;
2065
+ },
2308
2066
  /**
2309
2067
  * Track Machine Pool validation status
2310
2068
  */
@@ -2314,6 +2072,71 @@ export default {
2314
2072
  } else {
2315
2073
  this.$set(this.machinePoolValidation, id, value);
2316
2074
  }
2075
+ },
2076
+ handleEnabledSystemServicesChanged(val) {
2077
+ set(this.serverConfig, 'disable', val);
2078
+ },
2079
+ handleCiliumIpv6Changed(neu) {
2080
+ const name = this.chartVersionKey('rke2-cilium');
2081
+ const values = this.userChartValues[name];
2082
+
2083
+ set(this, 'userChartValues', {
2084
+ ...this.userChartValues,
2085
+ [name]: {
2086
+ ...values,
2087
+ cilium: {
2088
+ ...values?.cilium,
2089
+ ipv6: {
2090
+ ...values?.cilium?.ipv6,
2091
+ enabled: neu
2092
+ }
2093
+ }
2094
+ }
2095
+ });
2096
+ },
2097
+ handlePspChanged(neu) {
2098
+ this.handlePspChange(neu);
2099
+ },
2100
+ handleCisChanged() {
2101
+ this.handleCisChange();
2102
+ },
2103
+ handlePsaDefaultChanged() {
2104
+ this.togglePsaDefault();
2105
+ },
2106
+ handleMachinePoolError(error) {
2107
+ this.machinePoolErrors = merge(this.machinePoolErrors, error);
2108
+
2109
+ const errors = Object.entries(this.machinePoolErrors)
2110
+ .map((x) => {
2111
+ if (!x[1].length) {
2112
+ return;
2113
+ }
2114
+
2115
+ const formattedFields = (() => {
2116
+ switch (x[1].length) {
2117
+ case 1:
2118
+ return x[1][0];
2119
+ case 2:
2120
+ return `${ x[1][0] } and ${ x[1][1] }`;
2121
+ default: {
2122
+ const [head, ...rest] = x[1];
2123
+
2124
+ return `${ rest.join(', ') }, and ${ head }`;
2125
+ }
2126
+ }
2127
+ })();
2128
+
2129
+ return this.t('cluster.banner.machinePoolError', {
2130
+ count: x[1].length, pool_name: x[0], fields: formattedFields
2131
+ }, true);
2132
+ } )
2133
+ .filter((x) => x);
2134
+
2135
+ if (!errors) {
2136
+ return;
2137
+ }
2138
+
2139
+ this.errors = errors;
2317
2140
  }
2318
2141
  },
2319
2142
  };
@@ -2447,7 +2270,8 @@ export default {
2447
2270
  :idx="idx"
2448
2271
  :machine-pools="machinePools"
2449
2272
  :busy="busy"
2450
- @error="e=>errors = e"
2273
+ :pool-id="obj.id"
2274
+ @error="handleMachinePoolError"
2451
2275
  @validationChanged="v=>machinePoolValidationChanged(obj.id, v)"
2452
2276
  />
2453
2277
  </Tab>
@@ -2465,270 +2289,49 @@ export default {
2465
2289
  :side-tabs="true"
2466
2290
  class="min-height"
2467
2291
  >
2468
- <!-- Basic -->
2469
2292
  <Tab
2470
2293
  name="basic"
2471
2294
  label-key="cluster.tabs.basic"
2472
2295
  :weight="11"
2473
2296
  @active="refreshYamls"
2474
2297
  >
2475
- <Banner
2476
- v-if="!haveArgInfo"
2477
- color="warning"
2478
- :label="t('cluster.banner.haveArgInfo')"
2479
- />
2480
- <Banner
2481
- v-if="showk8s21LegacyWarning"
2482
- color="warning"
2483
- :label="t('cluster.legacyWarning')"
2484
- />
2485
- <Banner
2486
- v-if="isHarvesterDriver && isHarvesterIncompatible && showCloudProvider"
2487
- color="warning"
2488
- >
2489
- <span
2490
- v-clean-html="t('cluster.harvester.warning.cloudProvider.incompatible', null, true)"
2491
- />
2492
- </Banner>
2493
- <div class="row mb-10">
2494
- <div class="col span-6">
2495
- <LabeledSelect
2496
- v-model="value.spec.kubernetesVersion"
2497
- :mode="mode"
2498
- :options="versionOptions"
2499
- label-key="cluster.kubernetesVersion.label"
2500
- @input="handleKubernetesChange($event)"
2501
- />
2502
- <Checkbox
2503
- v-model="showDeprecatedPatchVersions"
2504
- :label="t('cluster.kubernetesVersion.deprecatedPatches')"
2505
- :tooltip="t('cluster.kubernetesVersion.deprecatedPatchWarning')"
2506
- class="patch-version"
2507
- />
2508
- </div>
2509
- <div
2510
- v-if="showCloudProvider"
2511
- class="col span-6"
2512
- >
2513
- <LabeledSelect
2514
- v-model="agentConfig['cloud-provider-name']"
2515
- :mode="mode"
2516
- :disabled="canNotEditCloudProvider"
2517
- :options="cloudProviderOptions"
2518
- :label="t('cluster.rke2.cloudProvider.label')"
2519
- />
2520
- </div>
2521
- </div>
2522
- <div
2523
- v-if="showCni"
2524
- :style="{'align-items':'center'}"
2525
- class="row"
2526
- >
2527
- <div class="col span-6">
2528
- <LabeledSelect
2529
- v-model="serverConfig.cni"
2530
- :mode="mode"
2531
- :disabled="clusterIsAlreadyCreated"
2532
- :options="serverArgs.cni.options"
2533
- :label="t('cluster.rke2.cni.label')"
2534
- />
2535
- </div>
2536
- <div
2537
- v-if="serverConfig.cni === 'cilium' || serverConfig.cni === 'multus,cilium'"
2538
- class="col"
2539
- >
2540
- <Checkbox
2541
- v-model="ciliumIpv6"
2542
- :mode="mode"
2543
- :label="t('cluster.rke2.address.ipv6.enable')"
2544
- />
2545
- </div>
2546
- </div>
2547
- <template v-if="showVsphereNote">
2548
- <Banner
2549
- color="warning"
2550
- label-key="cluster.cloudProvider.rancher-vsphere.note"
2551
- />
2552
- </template>
2553
- <template v-else-if="showCloudConfigYaml">
2554
- <div class="spacer" />
2555
-
2556
- <div class="col span-12">
2557
- <Banner
2558
- v-if="unsupportedCloudProvider"
2559
- class="error mt-5"
2560
- >
2561
- {{ t('cluster.rke2.cloudProvider.unsupported') }}
2562
- </Banner>
2563
- <h3>
2564
- {{ t('cluster.rke2.cloudProvider.header') }}
2565
- </h3>
2566
- <YamlEditor
2567
- ref="yaml"
2568
- v-model="agentConfig['cloud-provider-config']"
2569
- :editor-mode="mode === 'view' ? 'VIEW_CODE' : 'EDIT_CODE'"
2570
- initial-yaml-values="# Cloud Provider Config"
2571
- class="yaml-editor"
2572
- />
2573
- </div>
2574
- </template>
2575
-
2576
- <div class="spacer" />
2577
-
2578
- <h3>
2579
- {{ t('cluster.rke2.security.header') }}
2580
- </h3>
2581
- <Banner
2582
- v-if="isEdit && !needsPSP && hasPsps"
2583
- color="warning"
2584
- :label="t('cluster.banner.invalidPsps')"
2585
- />
2586
- <Banner
2587
- v-else-if="isCreate && !needsPSP"
2588
- color="info"
2589
- :label="t('cluster.banner.removedPsp')"
2590
- />
2591
- <Banner
2592
- v-else-if="isCreate && hasPsps"
2593
- color="info"
2594
- :label="t('cluster.banner.deprecatedPsp')"
2298
+ <!-- Basic -->
2299
+ <Basics
2300
+ v-model="value"
2301
+ :live-value="liveValue"
2302
+ :mode="mode"
2303
+ :provider="provider"
2304
+ :psps="psps"
2305
+ :user-chart-values="userChartValues"
2306
+ :credential="credential"
2307
+ :cis-override="cisOverride"
2308
+ :cis-psa-change-banner="cisPsaChangeBanner"
2309
+ :all-psps="allPSPs"
2310
+ :all-psas="allPSAs"
2311
+ :addon-versions="addonVersions"
2312
+ :show-deprecated-patch-versions="showDeprecatedPatchVersions"
2313
+ :needs-psp="needsPSP"
2314
+ :selected-version="selectedVersion"
2315
+ :is-harvester-driver="isHarvesterDriver"
2316
+ :is-harvester-incompatible="isHarvesterIncompatible"
2317
+ :version-options="versionOptions"
2318
+ :cluster-is-already-created="clusterIsAlreadyCreated"
2319
+ :is-elemental-cluster="isElementalCluster"
2320
+ :has-psa-templates="hasPsaTemplates"
2321
+ :is-k3s="isK3s"
2322
+ :have-arg-info="haveArgInfo"
2323
+ :show-cni="showCni"
2324
+ :show-cloud-provider="showCloudProvider"
2325
+ :unsupported-cloud-provider="unsupportedCloudProvider"
2326
+ :cloud-provider-options="cloudProviderOptions"
2327
+ @cilium-ipv6-changed="handleCiliumIpv6Changed"
2328
+ @enabled-system-services-changed="handleEnabledSystemServicesChanged"
2329
+ @kubernetes-changed="handleKubernetesChange"
2330
+ @psp-changed="handlePspChanged"
2331
+ @cis-changed="handleCisChanged"
2332
+ @psa-default-changed="handlePsaDefaultChanged"
2333
+ @show-deprecated-patch-versions-changed="handleShowDeprecatedPatchVersionsChanged"
2595
2334
  />
2596
-
2597
- <Banner
2598
- v-if="showCisProfile && !isCisSupported && isEdit"
2599
- color="info"
2600
- >
2601
- <p v-clean-html="t('cluster.rke2.banner.cisUnsupported', {cisProfile: serverConfig.profile || agentConfig.profile}, true)" />
2602
- </Banner>
2603
-
2604
- <div class="row mb-10">
2605
- <div
2606
- v-if="pspOptions && needsPSP"
2607
- class="col span-6"
2608
- >
2609
- <!-- PSP template selector -->
2610
- <LabeledSelect
2611
- v-model="value.spec.defaultPodSecurityPolicyTemplateName"
2612
- data-testid="rke2-custom-edit-psp"
2613
- :mode="mode"
2614
- :options="pspOptions"
2615
- :label="t('cluster.rke2.defaultPodSecurityPolicyTemplateName.label')"
2616
- @input="handlePspChange($event)"
2617
- />
2618
- </div>
2619
-
2620
- <div
2621
- v-if="showCisProfile"
2622
- class="col span-6"
2623
- >
2624
- <LabeledSelect
2625
- v-if="serverArgs && serverArgs.profile"
2626
- v-model="serverConfig.profile"
2627
- :mode="mode"
2628
- :options="profileOptions"
2629
- :label="t('cluster.rke2.cis.sever')"
2630
- @input="handleCisChange"
2631
- />
2632
- <LabeledSelect
2633
- v-else-if="agentArgs && agentArgs.profile"
2634
- v-model="agentConfig.profile"
2635
- data-testid="rke2-custom-edit-cis-agent"
2636
- :mode="mode"
2637
- :options="profileOptions"
2638
- :label="t('cluster.rke2.cis.agent')"
2639
- @input="handleCisChange"
2640
- />
2641
- </div>
2642
- </div>
2643
-
2644
- <template v-if="hasCisOverride">
2645
- <Checkbox
2646
- v-model="cisOverride"
2647
- :mode="mode"
2648
- :label="t('cluster.rke2.cis.override')"
2649
- @input="togglePsaDefault"
2650
- />
2651
-
2652
- <Banner
2653
- v-if="cisOverride"
2654
- color="warning"
2655
- :label="t('cluster.rke2.banner.cisOverride')"
2656
- />
2657
- <Banner
2658
- v-if="cisPsaChangeBanner && !cisOverride"
2659
- color="info"
2660
- :label="t('cluster.rke2.banner.psaChange')"
2661
- />
2662
- </template>
2663
-
2664
- <div
2665
- v-if="needsPSA"
2666
- class="row mb-10 mt-10"
2667
- >
2668
- <div class="col span-6">
2669
- <!-- PSA template selector -->
2670
- <LabeledSelect
2671
- v-model="value.spec.defaultPodSecurityAdmissionConfigurationTemplateName"
2672
- :mode="mode"
2673
- data-testid="rke2-custom-edit-psa"
2674
- :options="psaOptions"
2675
- :disabled="isPsaDisabled"
2676
- :label="t('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.label')"
2677
- />
2678
- </div>
2679
- </div>
2680
-
2681
- <div class="row">
2682
- <div class="col span-12 mt-20">
2683
- <Checkbox
2684
- v-if="serverArgs['secrets-encryption']"
2685
- v-model="serverConfig['secrets-encryption']"
2686
- :mode="mode"
2687
- label="Encrypt Secrets"
2688
- />
2689
- <Checkbox
2690
- v-model="value.spec.enableNetworkPolicy"
2691
- :mode="mode"
2692
- :label="t('cluster.rke2.enableNetworkPolicy.label')"
2693
- />
2694
- <!-- <Checkbox v-if="agentArgs.selinux" v-model="agentConfig.selinux" :mode="mode" label="SELinux" /> -->
2695
- </div>
2696
- </div>
2697
-
2698
- <div
2699
- v-if="serverConfig.cni === 'cilium' && value.spec.enableNetworkPolicy"
2700
- class="row"
2701
- >
2702
- <div class="col span-12">
2703
- <Banner
2704
- color="info"
2705
- :label="t('cluster.rke2.enableNetworkPolicy.warning')"
2706
- />
2707
- </div>
2708
- </div>
2709
-
2710
- <div class="spacer" />
2711
-
2712
- <div
2713
- v-if="serverArgs.disable"
2714
- class="row"
2715
- >
2716
- <div class="col span-12">
2717
- <div>
2718
- <h3>
2719
- {{ t('cluster.rke2.systemService.header') }}
2720
- </h3>
2721
- </div>
2722
- <Checkbox
2723
- v-for="opt in disableOptions"
2724
- :key="opt.value"
2725
- v-model="enabledSystemServices"
2726
- :mode="mode"
2727
- :label="opt.label"
2728
- :value-when-true="opt.value"
2729
- />
2730
- </div>
2731
- </div>
2732
2335
  </Tab>
2733
2336
 
2734
2337
  <!-- Member Roles -->
@@ -2738,19 +2341,12 @@ export default {
2738
2341
  label-key="cluster.tabs.memberRoles"
2739
2342
  :weight="10"
2740
2343
  >
2741
- <Banner
2742
- v-if="isEdit"
2743
- color="info"
2744
- >
2745
- {{ t('cluster.memberRoles.removeMessage') }}
2746
- </Banner>
2747
- <ClusterMembershipEditor
2344
+ <MemberRoles
2345
+ v-model="value"
2748
2346
  :mode="mode"
2749
- :parent-id="value.mgmt ? value.mgmt.id : null"
2750
- @membership-update="onMembershipUpdate"
2347
+ :on-membership-update="onMembershipUpdate"
2751
2348
  />
2752
2349
  </Tab>
2753
-
2754
2350
  <!-- etcd -->
2755
2351
  <Tab
2756
2352
  name="etcd"
@@ -2961,11 +2557,11 @@ export default {
2961
2557
  v-if="get(rkeConfig, 'upgradeStrategy.controlPlaneDrainOptions.deleteEmptyDirData')"
2962
2558
  color="warning"
2963
2559
  >
2964
- {{ t('cluster.rke2.deleteEmptyDir', {}, true) }}
2560
+ {{ t('cluster.rke2.drain.deleteEmptyDir.warning', {}, true) }}
2965
2561
  </Banner>
2966
2562
  <div class="row">
2967
2563
  <div class="col span-6">
2968
- <h3>Control Plane</h3>
2564
+ <h3>{{ t('cluster.rke2.controlPlaneConcurrency.header') }}</h3>
2969
2565
  <LabeledInput
2970
2566
  v-model="rkeConfig.upgradeStrategy.controlPlaneConcurrency"
2971
2567
  :mode="mode"
@@ -3003,7 +2599,7 @@ export default {
3003
2599
  label-key="cluster.tabs.registry"
3004
2600
  >
3005
2601
  <div class="row">
3006
- <h3>Registry for Rancher System Container Images</h3>
2602
+ <h3>{{ t('cluster.privateRegistry.label') }}</h3>
3007
2603
  </div>
3008
2604
  <div class="row">
3009
2605
  <div class="col span-12">