@rancher/shell 0.3.23 → 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 (149) hide show
  1. package/assets/styles/base/_variables.scss +1 -0
  2. package/assets/styles/themes/_dark.scss +1 -0
  3. package/assets/styles/themes/_light.scss +6 -5
  4. package/assets/translations/en-us.yaml +44 -17
  5. package/assets/translations/zh-hans.yaml +2 -2
  6. package/components/ClusterIconMenu.vue +143 -0
  7. package/components/CruResource.vue +7 -1
  8. package/components/ExplorerProjectsNamespaces.vue +11 -1
  9. package/components/FixedBanner.vue +17 -1
  10. package/components/Loading.vue +1 -1
  11. package/components/Markdown.vue +1 -1
  12. package/components/Questions/__tests__/Yaml.test.ts +3 -2
  13. package/components/SideNav.vue +1 -1
  14. package/components/SortableTable/index.vue +3 -2
  15. package/components/auth/RoleDetailEdit.vue +15 -2
  16. package/components/auth/login/saml.vue +12 -1
  17. package/components/form/LabeledSelect.vue +12 -5
  18. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  19. package/components/form/Members/MembershipEditor.vue +6 -1
  20. package/components/form/SelectOrCreateAuthSecret.vue +7 -0
  21. package/components/form/__tests__/KeyValue.test.ts +6 -3
  22. package/components/form/__tests__/LabeledSelect.test.ts +18 -0
  23. package/components/formatter/PodsUsage.vue +11 -36
  24. package/components/formatter/PrincipalGroupBindings.vue +8 -5
  25. package/components/formatter/__tests__/PodsUsage.test.ts +36 -19
  26. package/components/nav/Group.vue +62 -34
  27. package/components/nav/Header.vue +13 -6
  28. package/components/nav/Pinned.vue +47 -0
  29. package/components/nav/TopLevelMenu.vue +673 -325
  30. package/components/nav/Type.vue +88 -8
  31. package/config/home-links.js +1 -1
  32. package/config/product/istio.js +15 -5
  33. package/config/router.js +3 -9
  34. package/config/table-headers.js +5 -6
  35. package/config/uiplugins.js +1 -0
  36. package/core/plugin-helpers.js +3 -0
  37. package/core/types.ts +6 -1
  38. package/creators/app/files/.vscode/settings.json +0 -1
  39. package/creators/pkg/init +2 -2
  40. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +118 -0
  41. package/detail/autoscaling.horizontalpodautoscaler/index.vue +4 -4
  42. package/detail/provisioning.cattle.io.cluster.vue +7 -5
  43. package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +58 -0
  44. package/edit/__tests__/namespace.test.ts +5 -3
  45. package/edit/fleet.cattle.io.gitrepo.vue +43 -15
  46. package/edit/logging.banzaicloud.io.output/index.vue +7 -0
  47. package/edit/management.cattle.io.clusterroletemplatebinding.vue +3 -11
  48. package/edit/namespace.vue +8 -4
  49. package/edit/provisioning.cattle.io.cluster/Basics.vue +662 -0
  50. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +9 -8
  51. package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +13 -8
  52. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -2
  53. package/edit/provisioning.cattle.io.cluster/MemberRoles.vue +40 -0
  54. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  55. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +71 -23
  56. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +52 -0
  57. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -142
  58. package/edit/provisioning.cattle.io.cluster/rke2.vue +253 -582
  59. package/edit/workload/storage/ContainerMountPaths.vue +7 -5
  60. package/edit/workload/storage/__tests__/Storage.test.ts +2 -2
  61. package/edit/workload/storage/persistentVolumeClaim/__tests__/persistentvolumeclaim.test.ts +36 -0
  62. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +15 -7
  63. package/initialize/App.js +2 -0
  64. package/initialize/client.js +63 -51
  65. package/initialize/index.js +7 -5
  66. package/layouts/default.vue +10 -2
  67. package/layouts/home.vue +6 -2
  68. package/layouts/plain.vue +9 -2
  69. package/list/fleet.cattle.io.cluster.vue +2 -2
  70. package/list/management.cattle.io.feature.vue +1 -1
  71. package/machine-config/amazonec2.vue +1 -0
  72. package/machine-config/vmwarevsphere.vue +48 -7
  73. package/mixins/brand.js +0 -8
  74. package/mixins/child-hook.js +2 -2
  75. package/mixins/create-edit-view/impl.js +3 -3
  76. package/mixins/fetch.client.js +3 -3
  77. package/models/__tests__/management.cattle.io.node.ts +96 -0
  78. package/models/__tests__/node.ts +74 -0
  79. package/models/cluster/node.js +6 -5
  80. package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
  81. package/models/management.cattle.io.cluster.js +22 -1
  82. package/models/management.cattle.io.clusterroletemplatebinding.js +3 -3
  83. package/models/management.cattle.io.globalrole.js +17 -2
  84. package/models/management.cattle.io.node.js +6 -4
  85. package/models/management.cattle.io.projectroletemplatebinding.js +3 -3
  86. package/models/management.cattle.io.roletemplate.js +17 -2
  87. package/package.json +2 -6
  88. package/pages/__tests__/prefs.test.ts +1 -1
  89. package/pages/about.vue +2 -0
  90. package/pages/auth/setup.vue +5 -4
  91. package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -0
  92. package/pages/c/_cluster/monitoring/index.vue +8 -3
  93. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +9 -66
  94. package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +182 -0
  95. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +15 -32
  96. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +8 -46
  97. package/pages/c/_cluster/uiplugins/index.vue +64 -64
  98. package/pages/diagnostic.vue +0 -39
  99. package/pages/home.vue +1 -1
  100. package/pages/prefs.vue +3 -13
  101. package/plugins/dashboard-store/normalize.js +4 -4
  102. package/plugins/dashboard-store/resource-class.js +1 -1
  103. package/plugins/int-number.js +5 -2
  104. package/plugins/positive-int-number.js +19 -0
  105. package/plugins/steve/__tests__/getters.spec.ts +15 -0
  106. package/plugins/steve/getters.js +22 -10
  107. package/public/index.html +4 -2
  108. package/rancher-components/BadgeState/BadgeState.vue +5 -1
  109. package/rancher-components/Banner/Banner.test.ts +51 -1
  110. package/rancher-components/Banner/Banner.vue +134 -53
  111. package/rancher-components/Card/Card.test.ts +37 -0
  112. package/rancher-components/Card/Card.vue +24 -7
  113. package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
  114. package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
  115. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
  116. package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
  117. package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
  118. package/rancher-components/Form/Radio/RadioButton.vue +30 -13
  119. package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
  120. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
  121. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
  122. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
  123. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
  124. package/rancher-components/StringList/StringList.test.ts +453 -49
  125. package/rancher-components/StringList/StringList.vue +92 -58
  126. package/scripts/extension/parse-tag-name +0 -0
  127. package/store/index.js +4 -0
  128. package/store/prefs.js +4 -4
  129. package/store/type-map.js +2 -16
  130. package/types/shell/index.d.ts +26 -14
  131. package/utils/__tests__/cluster.test.ts +55 -0
  132. package/utils/__tests__/object.test.ts +21 -2
  133. package/utils/__tests__/sort.test.ts +61 -0
  134. package/utils/cluster.js +47 -1
  135. package/utils/object.js +12 -5
  136. package/utils/string.js +12 -0
  137. package/utils/validators/formRules/__tests__/index.test.ts +13 -1
  138. package/utils/validators/formRules/index.ts +4 -0
  139. package/utils/validators/role-template.js +9 -1
  140. package/utils/version.js +1 -1
  141. package/vue.config.js +1 -4
  142. package/yarn-error.log +200 -0
  143. package/content/docs/en-us/getting-started.md +0 -224
  144. package/content/docs/en-us/whats-new.md +0 -29
  145. package/content/docs/zh-hans/getting-started.md +0 -224
  146. package/content/docs/zh-hans/whats-new.md +0 -28
  147. package/pages/docs/_doc.vue +0 -345
  148. package/pages/docs/toc.js +0 -27
  149. 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,
@@ -219,6 +215,13 @@ export default {
219
215
  defaultRke2: '',
220
216
  defaultK3s: '',
221
217
  s3Backup: false,
218
+ /**
219
+ * All info related to a specific version of the chart
220
+ *
221
+ * This includes chart itself, README and values
222
+ *
223
+ * { [chartName:string]: { chart: json, readme: string, values: json } }
224
+ */
222
225
  versionInfo: {},
223
226
  membershipUpdate: {},
224
227
  showDeprecatedPatchVersions: false,
@@ -244,20 +247,14 @@ export default {
244
247
  truncateLimit,
245
248
  busy: false,
246
249
  machinePoolValidation: {}, // map of validation states for each machine pool
250
+ machinePoolErrors: {},
247
251
  allNamespaces: [],
252
+ initialCloudProvider: this.value?.agentConfig?.['cloud-provider-name'] || '',
248
253
  extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.CLUSTER_CREATE_RKE2, this.$route, this),
249
254
  };
250
255
  },
251
256
 
252
257
  computed: {
253
- ...mapGetters({ allCharts: 'catalog/charts' }),
254
- ...mapGetters(['currentCluster']),
255
- ...mapGetters({ features: 'features/get' }),
256
- ...mapGetters(['namespaces']),
257
-
258
- PUBLIC: () => PUBLIC,
259
- PRIVATE: () => PRIVATE,
260
- ADVANCED: () => ADVANCED,
261
258
 
262
259
  rkeConfig() {
263
260
  return this.value.spec.rkeConfig;
@@ -267,13 +264,6 @@ export default {
267
264
  return this.truncateLimit && this.truncateLimit !== NETBIOS_TRUNCATION_LENGTH;
268
265
  },
269
266
 
270
- /**
271
- * Check presence of PSPs as template or CLI creation
272
- */
273
- hasPsps() {
274
- return !!this.psps?.count;
275
- },
276
-
277
267
  isElementalCluster() {
278
268
  return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
279
269
  },
@@ -296,17 +286,6 @@ export default {
296
286
  return this.value.agentConfig;
297
287
  },
298
288
 
299
- /**
300
- * Define introduction of PSA and return need of PSA templates based on min k8s version
301
- */
302
- needsPSA() {
303
- const release = this.value?.spec?.kubernetesVersion || '';
304
- const version = release.match(/\d+/g);
305
- const isRequiredVersion = version?.length ? +version[0] > 1 || +version[1] >= 23 : false;
306
-
307
- return isRequiredVersion;
308
- },
309
-
310
289
  /**
311
290
  * Define PSP deprecation and restrict use of PSP based on min k8s version
312
291
  */
@@ -402,159 +381,9 @@ export default {
402
381
  return (this.value?.spec?.kubernetesVersion || '').includes('k3s');
403
382
  },
404
383
 
405
- profileOptions() {
406
- const out = (this.agentArgs?.profile?.options || []).map((x) => {
407
- return { label: x, value: x };
408
- });
409
-
410
- out.unshift({
411
- label: this.$store.getters['i18n/t']('cluster.rke2.cisProfile.option'),
412
- value: ''
413
- });
414
-
415
- return out;
416
- },
417
-
418
- /**
419
- * Allow to display override if PSA is needed and profile is set
420
- */
421
- hasCisOverride() {
422
- return (this.serverConfig?.profile || this.agentConfig?.profile) && this.needsPSA &&
423
- // Also check other cases on when to display the override
424
- this.hasPsaTemplates && this.showCisProfile && this.isCisSupported;
425
- },
426
-
427
- pspOptions() {
428
- if ( this.isK3s ) {
429
- return null;
430
- }
431
-
432
- const out = [{
433
- label: this.$store.getters['i18n/t']('cluster.rke2.defaultPodSecurityPolicyTemplateName.option'),
434
- value: ''
435
- }];
436
-
437
- if ( this.allPSPs ) {
438
- for ( const pspt of this.allPSPs ) {
439
- out.push({
440
- label: pspt.nameDisplay,
441
- value: pspt.id,
442
- });
443
- }
444
- }
445
-
446
- const cur = this.value.spec.defaultPodSecurityPolicyTemplateName;
447
-
448
- if ( cur && !out.find((x) => x.value === cur) ) {
449
- out.unshift({ label: `${ cur } (Current)`, value: cur });
450
- }
451
-
452
- return out;
453
- },
454
-
455
- /**
456
- * Disable PSA if CIS hardening is enabled, except override
457
- */
458
- isPsaDisabled() {
459
- const cisValue = this.agentConfig?.profile || this.serverConfig?.profile;
460
-
461
- return !(!cisValue || this.cisOverride) && this.hasPsaTemplates && this.isCisSupported;
462
- },
463
-
464
- /**
465
- * Get the default label for the PSA template option
466
- */
467
- defaultPsaOptionLabel() {
468
- const optionCase = !this.needsPSP && !this.isK3s ? 'default' : 'none';
469
-
470
- return this.$store.getters['i18n/t'](`cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.option.${ optionCase }`);
471
- },
472
-
473
384
  /**
474
- * Convert PSA templates into options, sorting and flagging if any selected
385
+ * Kube Version
475
386
  */
476
- psaOptions() {
477
- if ( !this.needsPSA ) {
478
- return [];
479
- }
480
- const out = [{
481
- label: this.defaultPsaOptionLabel,
482
- value: ''
483
- }];
484
-
485
- if ( this.allPSAs ) {
486
- for ( const psa of this.allPSAs ) {
487
- out.push({
488
- label: psa.nameDisplay,
489
- value: psa.id,
490
- });
491
- }
492
- }
493
- const cur = this.value.spec.defaultPodSecurityAdmissionConfigurationTemplateName;
494
-
495
- if ( cur && !out.find((x) => x.value === cur) ) {
496
- out.unshift({ label: `${ cur } (Current)`, value: cur });
497
- }
498
-
499
- return out;
500
- },
501
-
502
- /**
503
- * Check if current CIS profile is required and listed in the options
504
- */
505
- isCisSupported() {
506
- const cisProfile = this.serverConfig.profile || this.agentConfig.profile;
507
-
508
- return !cisProfile || this.profileOptions.map((option) => option.value).includes(cisProfile);
509
- },
510
-
511
- disableOptions() {
512
- return this.serverArgs.disable.options.map((value) => {
513
- return {
514
- label: this.$store.getters['i18n/withFallback'](`cluster.${ this.isK3s ? 'k3s' : 'rke2' }.systemService."${ value }"`, null, value.replace(/^(rke2|rancher)-/, '')),
515
- value,
516
- };
517
- });
518
- },
519
-
520
- cloudProviderOptions() {
521
- const out = [{
522
- label: this.$store.getters['i18n/t']('cluster.rke2.cloudProvider.defaultValue.label'),
523
- value: '',
524
- }];
525
-
526
- const preferred = this.$store.getters['plugins/cloudProviderForDriver'](this.provider);
527
-
528
- for ( const opt of this.agentArgs['cloud-provider-name'].options ) {
529
- // If we don't have a preferred provider... show all options
530
- const showAllOptions = preferred === undefined;
531
- // If we have a preferred provider... only show default, preferred and external
532
- const isPreferred = opt === preferred;
533
- const isExternal = opt === 'external';
534
- let disabled = false;
535
-
536
- if ((this.isHarvesterExternalCredential || this.isHarvesterIncompatible) && isPreferred) {
537
- disabled = true;
538
- }
539
-
540
- if (showAllOptions || isPreferred || isExternal) {
541
- out.push({
542
- label: this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ opt }".label`, null, opt),
543
- value: opt,
544
- disabled,
545
- });
546
- }
547
- }
548
-
549
- const cur = this.agentConfig['cloud-provider-name'];
550
-
551
- if ( cur && !out.find((x) => x.value === cur) ) {
552
- out.unshift({ label: `${ cur } (Current)`, value: cur });
553
- }
554
-
555
- return out;
556
- },
557
-
558
387
  selectedVersion() {
559
388
  const str = this.value.spec.kubernetesVersion;
560
389
 
@@ -579,14 +408,15 @@ export default {
579
408
  return this.selectedVersion?.agentArgs || {};
580
409
  },
581
410
 
411
+ /**
412
+ * The addons (kube charts) applicable for the selected kube version
413
+ *
414
+ * { [chartName:string]: { repo: string, version: string } }
415
+ */
582
416
  chartVersions() {
583
417
  return this.selectedVersion?.charts || {};
584
418
  },
585
419
 
586
- showCisProfile() {
587
- return (this.provider === 'custom' || this.isElementalCluster) && ( this.serverArgs?.profile || this.agentArgs?.profile );
588
- },
589
-
590
420
  needCredential() {
591
421
  if ( this.provider === 'custom' || this.provider === 'import' || this.isElementalCluster || this.mode === _VIEW ) {
592
422
  return false;
@@ -736,58 +566,17 @@ export default {
736
566
  return out;
737
567
  },
738
568
 
739
- enabledSystemServices: {
740
- get() {
741
- const out = difference(this.serverArgs.disable.options, this.serverConfig.disable || []);
742
-
743
- return out;
744
- },
745
-
746
- set(neu) {
747
- const out = difference(this.serverArgs.disable.options, neu);
748
-
749
- set(this.serverConfig, 'disable', out);
750
- },
751
- },
752
-
753
- showCloudConfigYaml() {
754
- if ( !this.agentArgs['cloud-provider-name'] ) {
755
- return false;
756
- }
757
-
758
- const name = this.agentConfig['cloud-provider-name'];
759
-
760
- if ( !name ) {
761
- return false;
762
- }
763
-
764
- switch ( name ) {
765
- case 'none': return false;
766
- case 'aws': return false;
767
- case 'rancher-vsphere': return false;
768
- case HARVESTER: return false;
769
- default: return true;
770
- }
771
- },
772
-
773
- showVsphereNote() {
774
- if ( !this.agentArgs['cloud-provider-name'] ) {
775
- return false;
776
- }
777
-
778
- const name = this.agentConfig['cloud-provider-name'];
779
-
780
- return name === 'rancher-vsphere';
781
- },
782
-
783
569
  showCni() {
784
570
  return !!this.serverArgs.cni;
785
571
  },
786
572
 
787
573
  showCloudProvider() {
788
- return this.agentArgs['cloud-provider-name'];
574
+ return !!this.agentArgs['cloud-provider-name'];
789
575
  },
790
576
 
577
+ /**
578
+ * The chart names of the addons applicable to the current kube version and selected cloud provider
579
+ */
791
580
  addonNames() {
792
581
  const names = [];
793
582
  const cni = this.serverConfig.cni;
@@ -811,21 +600,77 @@ export default {
811
600
  return names;
812
601
  },
813
602
 
603
+ /**
604
+ * The charts of the addons applicable to the current kube version and selected cloud provider
605
+ *
606
+ * These are the charts themselves and do not include chart readme or values
607
+ */
814
608
  addonVersions() {
815
- const versions = this.addonNames.map((name) => this.chartVersionFor(name));
609
+ const versions = this.addonNames.map((name) => this.versionInfo[name]?.chart);
816
610
 
817
611
  return versions.filter((x) => !!x);
818
612
  },
819
613
 
820
- showk8s21LegacyWarning() {
821
- 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
+ }];
822
619
 
823
- if (!isLegacyEnabled) {
824
- 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
+ });
825
658
  }
826
- const selectedVersion = semver.coerce(this.value.spec.kubernetesVersion);
827
659
 
828
- return semver.satisfies(selectedVersion, '>=1.21.0');
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
+ });
671
+ }
672
+
673
+ return out;
829
674
  },
830
675
 
831
676
  canManageMembers() {
@@ -862,33 +707,6 @@ export default {
862
707
  return out;
863
708
  },
864
709
 
865
- ciliumIpv6: {
866
- get() {
867
- // eslint-disable-next-line no-unused-vars
868
- const cni = this.serverConfig.cni; // force this property to recalculate if cni was changed away from cilium and chartValues['rke-cilium'] deleted
869
-
870
- return this.userChartValues[this.chartVersionKey('rke2-cilium')]?.cilium?.ipv6?.enabled || false;
871
- },
872
- set(val) {
873
- const name = this.chartVersionKey('rke2-cilium');
874
- const values = this.userChartValues[name];
875
-
876
- set(this, 'userChartValues', {
877
- ...this.userChartValues,
878
- [name]: {
879
- ...values,
880
- cilium: {
881
- ...values?.cilium,
882
- ipv6: {
883
- ...values?.cilium?.ipv6,
884
- enabled: val
885
- }
886
- }
887
- }
888
- });
889
- }
890
- },
891
-
892
710
  showIpv6Warning() {
893
711
  const clusterCIDR = this.serverConfig['cluster-cidr'] || '';
894
712
  const serviceCIDR = this.serverConfig['service-cidr'] || '';
@@ -964,6 +782,14 @@ export default {
964
782
 
965
783
  return validRequiredPools && base;
966
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
+ },
967
793
  },
968
794
 
969
795
  watch: {
@@ -1035,11 +861,6 @@ export default {
1035
861
  set(this.agentConfig, 'cloud-provider-name', undefined);
1036
862
  }
1037
863
  },
1038
-
1039
- },
1040
-
1041
- mounted() {
1042
- window.rke = this;
1043
864
  },
1044
865
 
1045
866
  created() {
@@ -1055,7 +876,6 @@ export default {
1055
876
  },
1056
877
 
1057
878
  methods: {
1058
- nlToBr,
1059
879
  set,
1060
880
 
1061
881
  /**
@@ -1339,6 +1159,7 @@ export default {
1339
1159
  }
1340
1160
 
1341
1161
  const name = `pool${ ++this.lastIdx }`;
1162
+
1342
1163
  const pool = {
1343
1164
  id: name,
1344
1165
  config,
@@ -1359,6 +1180,7 @@ export default {
1359
1180
  kind: this.machineConfigSchema.attributes?.kind,
1360
1181
  name: null,
1361
1182
  },
1183
+ drainBeforeDelete: true
1362
1184
  },
1363
1185
  };
1364
1186
 
@@ -1411,7 +1233,11 @@ export default {
1411
1233
  }
1412
1234
  },
1413
1235
 
1414
- async saveMachinePools() {
1236
+ async saveMachinePools(hookContext) {
1237
+ if (hookContext === CONTEXT_HOOK_EDIT_YAML) {
1238
+ return;
1239
+ }
1240
+
1415
1241
  const finalPools = [];
1416
1242
 
1417
1243
  // If the extension provider wants to do this, let them
@@ -1723,41 +1549,37 @@ export default {
1723
1549
  });
1724
1550
  },
1725
1551
 
1726
- chartVersionFor(chartName) {
1727
- const entry = this.chartVersions[chartName];
1728
-
1729
- if ( !entry ) {
1730
- return null;
1731
- }
1732
-
1733
- const out = this.$store.getters['catalog/version']({
1734
- repoType: 'cluster',
1735
- repoName: entry.repo,
1736
- chartName,
1737
- versionName: entry.version,
1738
- });
1739
-
1740
- return out;
1741
- },
1742
-
1552
+ /**
1553
+ * Ensure all chart information required to show addons is available
1554
+ *
1555
+ * This basically means
1556
+ * 1) That the full chart relating to the addon is fetched (which includes core chart, readme and values)
1557
+ * 2) We're ready to cache any values the user provides for each addon
1558
+ */
1743
1559
  async initAddons() {
1744
- for ( const v of this.addonVersions ) {
1745
- if ( this.versionInfo[v.name] ) {
1560
+ for ( const chartName of this.addonNames ) {
1561
+ const entry = this.chartVersions[chartName];
1562
+
1563
+ if ( this.versionInfo[chartName] ) {
1746
1564
  continue;
1747
1565
  }
1748
1566
 
1749
- const res = await this.$store.dispatch('catalog/getVersionInfo', {
1750
- repoType: 'cluster',
1751
- repoName: v.repoName,
1752
- chartName: v.name,
1753
- versionName: v.version
1754
- });
1567
+ try {
1568
+ const res = await this.$store.dispatch('catalog/getVersionInfo', {
1569
+ repoType: 'cluster',
1570
+ repoName: entry.repo,
1571
+ chartName,
1572
+ versionName: entry.version,
1573
+ });
1755
1574
 
1756
- set(this.versionInfo, v.name, res);
1757
- const key = this.chartVersionKey(v.name);
1575
+ set(this.versionInfo, chartName, res);
1576
+ const key = this.chartVersionKey(chartName);
1758
1577
 
1759
- if (!this.userChartValues[key]) {
1760
- this.userChartValues[key] = {};
1578
+ if (!this.userChartValues[key]) {
1579
+ this.userChartValues[key] = {};
1580
+ }
1581
+ } catch (e) {
1582
+ console.error(`Failed to fetch or process chart info for ${ chartName }`); // eslint-disable-line no-console
1761
1583
  }
1762
1584
  }
1763
1585
  },
@@ -1808,16 +1630,6 @@ export default {
1808
1630
  this.syncChartValues(name);
1809
1631
  },
1810
1632
 
1811
- initQuestions(name) {
1812
- const defaultChartValue = this.versionInfo[name];
1813
- const startingChartValue = this.initYamlEditor(name);
1814
-
1815
- return {
1816
- ...defaultChartValue,
1817
- values: startingChartValue,
1818
- };
1819
- },
1820
-
1821
1633
  initYamlEditor(name) {
1822
1634
  const defaultChartValue = this.versionInfo[name];
1823
1635
  const key = this.chartVersionKey(name);
@@ -2226,6 +2038,18 @@ export default {
2226
2038
  if (this.isHarvesterDriver && this.mode === _CREATE && this.isHarvesterIncompatible) {
2227
2039
  this.setHarvesterDefaultCloudProvider();
2228
2040
  }
2041
+
2042
+ // Cloud Provider check
2043
+ // If the cloud provider is unsupported, switch provider to 'external'
2044
+ if (this.unsupportedCloudProvider) {
2045
+ set(this.agentConfig, 'cloud-provider-name', 'external');
2046
+ } else {
2047
+ // Switch the cloud provider back to the initial value
2048
+ // Use changed the Kubernetes version back to a version where the initial cloud provider is valid - so switch back to this one
2049
+ // to undo the change to external that we may have made
2050
+ // Note: Cloud Provider can only be changed on edit when the initial provider is no longer supported
2051
+ set(this.agentConfig, 'cloud-provider-name', this.initialCloudProvider);
2052
+ }
2229
2053
  }
2230
2054
  },
2231
2055
 
@@ -2236,6 +2060,9 @@ export default {
2236
2060
  this.lastDefaultPodSecurityPolicyTemplateName = value;
2237
2061
  },
2238
2062
 
2063
+ handleShowDeprecatedPatchVersionsChanged(value) {
2064
+ this.showDeprecatedPatchVersions = value;
2065
+ },
2239
2066
  /**
2240
2067
  * Track Machine Pool validation status
2241
2068
  */
@@ -2245,6 +2072,71 @@ export default {
2245
2072
  } else {
2246
2073
  this.$set(this.machinePoolValidation, id, value);
2247
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;
2248
2140
  }
2249
2141
  },
2250
2142
  };
@@ -2378,7 +2270,8 @@ export default {
2378
2270
  :idx="idx"
2379
2271
  :machine-pools="machinePools"
2380
2272
  :busy="busy"
2381
- @error="e=>errors = e"
2273
+ :pool-id="obj.id"
2274
+ @error="handleMachinePoolError"
2382
2275
  @validationChanged="v=>machinePoolValidationChanged(obj.id, v)"
2383
2276
  />
2384
2277
  </Tab>
@@ -2396,264 +2289,49 @@ export default {
2396
2289
  :side-tabs="true"
2397
2290
  class="min-height"
2398
2291
  >
2399
- <!-- Basic -->
2400
2292
  <Tab
2401
2293
  name="basic"
2402
2294
  label-key="cluster.tabs.basic"
2403
2295
  :weight="11"
2404
2296
  @active="refreshYamls"
2405
2297
  >
2406
- <Banner
2407
- v-if="!haveArgInfo"
2408
- color="warning"
2409
- :label="t('cluster.banner.haveArgInfo')"
2410
- />
2411
- <Banner
2412
- v-if="showk8s21LegacyWarning"
2413
- color="warning"
2414
- :label="t('cluster.legacyWarning')"
2415
- />
2416
- <Banner
2417
- v-if="isHarvesterDriver && isHarvesterIncompatible && showCloudProvider"
2418
- color="warning"
2419
- >
2420
- <span
2421
- v-clean-html="t('cluster.harvester.warning.cloudProvider.incompatible', null, true)"
2422
- />
2423
- </Banner>
2424
- <div class="row mb-10">
2425
- <div class="col span-6">
2426
- <LabeledSelect
2427
- v-model="value.spec.kubernetesVersion"
2428
- :mode="mode"
2429
- :options="versionOptions"
2430
- label-key="cluster.kubernetesVersion.label"
2431
- @input="handleKubernetesChange($event)"
2432
- />
2433
- <Checkbox
2434
- v-model="showDeprecatedPatchVersions"
2435
- :label="t('cluster.kubernetesVersion.deprecatedPatches')"
2436
- :tooltip="t('cluster.kubernetesVersion.deprecatedPatchWarning')"
2437
- class="patch-version"
2438
- />
2439
- </div>
2440
- <div
2441
- v-if="showCloudProvider"
2442
- class="col span-6"
2443
- >
2444
- <LabeledSelect
2445
- v-model="agentConfig['cloud-provider-name']"
2446
- :mode="mode"
2447
- :disabled="clusterIsAlreadyCreated"
2448
- :options="cloudProviderOptions"
2449
- :label="t('cluster.rke2.cloudProvider.label')"
2450
- />
2451
- </div>
2452
- </div>
2453
- <div
2454
- v-if="showCni"
2455
- :style="{'align-items':'center'}"
2456
- class="row"
2457
- >
2458
- <div class="col span-6">
2459
- <LabeledSelect
2460
- v-model="serverConfig.cni"
2461
- :mode="mode"
2462
- :disabled="clusterIsAlreadyCreated"
2463
- :options="serverArgs.cni.options"
2464
- :label="t('cluster.rke2.cni.label')"
2465
- />
2466
- </div>
2467
- <div
2468
- v-if="serverConfig.cni === 'cilium' || serverConfig.cni === 'multus,cilium'"
2469
- class="col"
2470
- >
2471
- <Checkbox
2472
- v-model="ciliumIpv6"
2473
- :mode="mode"
2474
- :label="t('cluster.rke2.address.ipv6.enable')"
2475
- />
2476
- </div>
2477
- </div>
2478
- <template v-if="showVsphereNote">
2479
- <Banner
2480
- color="warning"
2481
- label-key="cluster.cloudProvider.rancher-vsphere.note"
2482
- />
2483
- </template>
2484
- <template v-else-if="showCloudConfigYaml">
2485
- <div class="spacer" />
2486
-
2487
- <div class="col span-12">
2488
- <h3>
2489
- {{ t('cluster.rke2.cloudProvider.header') }}
2490
- </h3>
2491
- <YamlEditor
2492
- ref="yaml"
2493
- v-model="agentConfig['cloud-provider-config']"
2494
- :editor-mode="mode === 'view' ? 'VIEW_CODE' : 'EDIT_CODE'"
2495
- initial-yaml-values="# Cloud Provider Config"
2496
- class="yaml-editor"
2497
- />
2498
- </div>
2499
- </template>
2500
-
2501
- <div class="spacer" />
2502
-
2503
- <h3>
2504
- {{ t('cluster.rke2.security.header') }}
2505
- </h3>
2506
- <Banner
2507
- v-if="isEdit && !needsPSP && hasPsps"
2508
- color="warning"
2509
- :label="t('cluster.banner.invalidPsps')"
2510
- />
2511
- <Banner
2512
- v-else-if="isCreate && !needsPSP"
2513
- color="info"
2514
- :label="t('cluster.banner.removedPsp')"
2515
- />
2516
- <Banner
2517
- v-else-if="isCreate && hasPsps"
2518
- color="info"
2519
- :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"
2520
2334
  />
2521
-
2522
- <Banner
2523
- v-if="showCisProfile && !isCisSupported && isEdit"
2524
- color="info"
2525
- >
2526
- <p v-clean-html="t('cluster.rke2.banner.cisUnsupported', {cisProfile: serverConfig.profile || agentConfig.profile}, true)" />
2527
- </Banner>
2528
-
2529
- <div class="row mb-10">
2530
- <div
2531
- v-if="pspOptions && needsPSP"
2532
- class="col span-6"
2533
- >
2534
- <!-- PSP template selector -->
2535
- <LabeledSelect
2536
- v-model="value.spec.defaultPodSecurityPolicyTemplateName"
2537
- data-testid="rke2-custom-edit-psp"
2538
- :mode="mode"
2539
- :options="pspOptions"
2540
- :label="t('cluster.rke2.defaultPodSecurityPolicyTemplateName.label')"
2541
- @input="handlePspChange($event)"
2542
- />
2543
- </div>
2544
-
2545
- <div
2546
- v-if="showCisProfile"
2547
- class="col span-6"
2548
- >
2549
- <LabeledSelect
2550
- v-if="serverArgs && serverArgs.profile"
2551
- v-model="serverConfig.profile"
2552
- :mode="mode"
2553
- :options="profileOptions"
2554
- :label="t('cluster.rke2.cis.sever')"
2555
- @input="handleCisChange"
2556
- />
2557
- <LabeledSelect
2558
- v-else-if="agentArgs && agentArgs.profile"
2559
- v-model="agentConfig.profile"
2560
- data-testid="rke2-custom-edit-cis-agent"
2561
- :mode="mode"
2562
- :options="profileOptions"
2563
- :label="t('cluster.rke2.cis.agent')"
2564
- @input="handleCisChange"
2565
- />
2566
- </div>
2567
- </div>
2568
-
2569
- <template v-if="hasCisOverride">
2570
- <Checkbox
2571
- v-model="cisOverride"
2572
- :mode="mode"
2573
- :label="t('cluster.rke2.cis.override')"
2574
- @input="togglePsaDefault"
2575
- />
2576
-
2577
- <Banner
2578
- v-if="cisOverride"
2579
- color="warning"
2580
- :label="t('cluster.rke2.banner.cisOverride')"
2581
- />
2582
- <Banner
2583
- v-if="cisPsaChangeBanner && !cisOverride"
2584
- color="info"
2585
- :label="t('cluster.rke2.banner.psaChange')"
2586
- />
2587
- </template>
2588
-
2589
- <div
2590
- v-if="needsPSA"
2591
- class="row mb-10 mt-10"
2592
- >
2593
- <div class="col span-6">
2594
- <!-- PSA template selector -->
2595
- <LabeledSelect
2596
- v-model="value.spec.defaultPodSecurityAdmissionConfigurationTemplateName"
2597
- :mode="mode"
2598
- data-testid="rke2-custom-edit-psa"
2599
- :options="psaOptions"
2600
- :disabled="isPsaDisabled"
2601
- :label="t('cluster.rke2.defaultPodSecurityAdmissionConfigurationTemplateName.label')"
2602
- />
2603
- </div>
2604
- </div>
2605
-
2606
- <div class="row">
2607
- <div class="col span-12 mt-20">
2608
- <Checkbox
2609
- v-if="serverArgs['secrets-encryption']"
2610
- v-model="serverConfig['secrets-encryption']"
2611
- :mode="mode"
2612
- label="Encrypt Secrets"
2613
- />
2614
- <Checkbox
2615
- v-model="value.spec.enableNetworkPolicy"
2616
- :mode="mode"
2617
- :label="t('cluster.rke2.enableNetworkPolicy.label')"
2618
- />
2619
- <!-- <Checkbox v-if="agentArgs.selinux" v-model="agentConfig.selinux" :mode="mode" label="SELinux" /> -->
2620
- </div>
2621
- </div>
2622
-
2623
- <div
2624
- v-if="serverConfig.cni === 'cilium' && value.spec.enableNetworkPolicy"
2625
- class="row"
2626
- >
2627
- <div class="col span-12">
2628
- <Banner
2629
- color="info"
2630
- :label="t('cluster.rke2.enableNetworkPolicy.warning')"
2631
- />
2632
- </div>
2633
- </div>
2634
-
2635
- <div class="spacer" />
2636
-
2637
- <div
2638
- v-if="serverArgs.disable"
2639
- class="row"
2640
- >
2641
- <div class="col span-12">
2642
- <div>
2643
- <h3>
2644
- {{ t('cluster.rke2.systemService.header') }}
2645
- </h3>
2646
- </div>
2647
- <Checkbox
2648
- v-for="opt in disableOptions"
2649
- :key="opt.value"
2650
- v-model="enabledSystemServices"
2651
- :mode="mode"
2652
- :label="opt.label"
2653
- :value-when-true="opt.value"
2654
- />
2655
- </div>
2656
- </div>
2657
2335
  </Tab>
2658
2336
 
2659
2337
  <!-- Member Roles -->
@@ -2663,19 +2341,12 @@ export default {
2663
2341
  label-key="cluster.tabs.memberRoles"
2664
2342
  :weight="10"
2665
2343
  >
2666
- <Banner
2667
- v-if="isEdit"
2668
- color="info"
2669
- >
2670
- {{ t('cluster.memberRoles.removeMessage') }}
2671
- </Banner>
2672
- <ClusterMembershipEditor
2344
+ <MemberRoles
2345
+ v-model="value"
2673
2346
  :mode="mode"
2674
- :parent-id="value.mgmt ? value.mgmt.id : null"
2675
- @membership-update="onMembershipUpdate"
2347
+ :on-membership-update="onMembershipUpdate"
2676
2348
  />
2677
2349
  </Tab>
2678
-
2679
2350
  <!-- etcd -->
2680
2351
  <Tab
2681
2352
  name="etcd"
@@ -2886,11 +2557,11 @@ export default {
2886
2557
  v-if="get(rkeConfig, 'upgradeStrategy.controlPlaneDrainOptions.deleteEmptyDirData')"
2887
2558
  color="warning"
2888
2559
  >
2889
- {{ t('cluster.rke2.deleteEmptyDir', {}, true) }}
2560
+ {{ t('cluster.rke2.drain.deleteEmptyDir.warning', {}, true) }}
2890
2561
  </Banner>
2891
2562
  <div class="row">
2892
2563
  <div class="col span-6">
2893
- <h3>Control Plane</h3>
2564
+ <h3>{{ t('cluster.rke2.controlPlaneConcurrency.header') }}</h3>
2894
2565
  <LabeledInput
2895
2566
  v-model="rkeConfig.upgradeStrategy.controlPlaneConcurrency"
2896
2567
  :mode="mode"
@@ -2928,7 +2599,7 @@ export default {
2928
2599
  label-key="cluster.tabs.registry"
2929
2600
  >
2930
2601
  <div class="row">
2931
- <h3>Registry for Rancher System Container Images</h3>
2602
+ <h3>{{ t('cluster.privateRegistry.label') }}</h3>
2932
2603
  </div>
2933
2604
  <div class="row">
2934
2605
  <div class="col span-12">