@rancher/shell 3.0.2-rc.5 → 3.0.2

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 (219) hide show
  1. package/assets/images/providers/nutanix.svg +12 -1
  2. package/assets/styles/base/_basic.scss +2 -1
  3. package/assets/styles/base/_helpers.scss +4 -0
  4. package/assets/styles/base/_variables.scss +2 -0
  5. package/assets/styles/global/_labeled-input.scss +5 -13
  6. package/assets/styles/global/_layout.scss +4 -1
  7. package/assets/styles/global/_select.scss +5 -0
  8. package/assets/styles/themes/_dark.scss +1 -3
  9. package/assets/styles/themes/_light.scss +5 -1
  10. package/assets/translations/en-us.yaml +130 -23
  11. package/assets/translations/zh-hans.yaml +0 -3
  12. package/cloud-credential/azure.vue +1 -1
  13. package/components/ActionMenuShell.vue +105 -0
  14. package/components/AppModal.vue +2 -2
  15. package/components/AsyncButton.vue +2 -0
  16. package/components/ButtonGroup.vue +9 -2
  17. package/components/ClusterBadge.vue +1 -0
  18. package/components/ClusterIconMenu.vue +3 -0
  19. package/components/ClusterProviderIcon.vue +14 -1
  20. package/components/CodeMirror.vue +96 -5
  21. package/components/Collapse.vue +16 -3
  22. package/components/CruResource.vue +9 -0
  23. package/components/CruResourceFooter.vue +1 -1
  24. package/components/ExplorerMembers.vue +2 -1
  25. package/components/FixedBanner.vue +19 -12
  26. package/components/Import.vue +14 -1
  27. package/components/LandingPagePreference.vue +4 -2
  28. package/components/PodSecurityAdmission.vue +8 -6
  29. package/components/PromptChangePassword.vue +1 -0
  30. package/components/PromptRemove.vue +23 -21
  31. package/components/ResourceDetail/Masthead.vue +30 -11
  32. package/components/ResourceDetail/__tests__/Masthead.test.ts +61 -0
  33. package/components/ResourceDetail/index.vue +6 -0
  34. package/components/ResourceTable.vue +6 -1
  35. package/components/ResourceYaml.vue +1 -0
  36. package/components/Setting.vue +115 -0
  37. package/components/SortableTable/THead.vue +2 -0
  38. package/components/SortableTable/index.vue +7 -12
  39. package/components/StatusBadge.vue +71 -0
  40. package/components/Tabbed/index.vue +16 -15
  41. package/components/Wizard.vue +108 -104
  42. package/components/YamlEditor.vue +12 -2
  43. package/components/__tests__/Collapse.test.ts +2 -2
  44. package/components/__tests__/FixedBanner.test.ts +3 -3
  45. package/components/auth/Principal.vue +29 -17
  46. package/components/auth/__tests__/Principal.test.ts +40 -0
  47. package/components/auth/login/ldap.vue +7 -0
  48. package/components/fleet/FleetBundles.vue +1 -1
  49. package/components/fleet/FleetRepos.vue +1 -1
  50. package/components/fleet/FleetResources.vue +0 -2
  51. package/components/fleet/FleetSummary.vue +60 -65
  52. package/components/fleet/ForceDirectedTreeChart/index.vue +5 -1
  53. package/components/fleet/__tests__/FleetSummary.test.ts +49 -9
  54. package/components/form/ArrayList.vue +6 -2
  55. package/components/form/ColorInput.vue +1 -0
  56. package/components/form/KeyValue.vue +11 -12
  57. package/components/form/LabeledSelect.vue +15 -3
  58. package/components/form/Labels.vue +8 -1
  59. package/components/form/Members/MembershipEditor.vue +230 -222
  60. package/components/form/Members/__tests__/MembershipEditor.test.ts +62 -0
  61. package/components/form/Password.vue +3 -0
  62. package/components/form/ProjectMemberEditor.vue +6 -3
  63. package/components/form/ResourceTabs/index.vue +15 -13
  64. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +5 -4
  65. package/components/form/SchedulingCustomization.vue +85 -0
  66. package/components/form/Select.vue +3 -2
  67. package/components/form/SelectOrCreateAuthSecret.vue +2 -1
  68. package/components/form/UnitInput.vue +3 -4
  69. package/components/form/__tests__/ArrayList.test.ts +9 -6
  70. package/components/form/__tests__/LabeledSelect.test.ts +37 -0
  71. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +34 -0
  72. package/components/form/__tests__/UnitInput.test.ts +4 -5
  73. package/components/formatter/LiveDate.vue +3 -1
  74. package/components/formatter/ServiceType.vue +12 -4
  75. package/components/formatter/WorkloadHealthScale.vue +2 -1
  76. package/components/nav/Header.vue +35 -2
  77. package/components/nav/HeaderPageActionMenu.vue +11 -40
  78. package/components/nav/Jump.vue +8 -2
  79. package/components/nav/NamespaceFilter.vue +5 -4
  80. package/components/nav/Pinned.vue +1 -1
  81. package/components/nav/TopLevelMenu.helper.ts +5 -5
  82. package/components/nav/TopLevelMenu.vue +1 -12
  83. package/components/nav/WindowManager/ContainerLogs.vue +96 -58
  84. package/components/nav/WindowManager/ContainerShell.vue +99 -18
  85. package/components/nav/WindowManager/index.vue +74 -6
  86. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
  87. package/components/templates/default.vue +2 -47
  88. package/config/features.js +1 -0
  89. package/config/labels-annotations.js +11 -1
  90. package/config/router/navigation-guards/index.js +2 -1
  91. package/config/router/navigation-guards/record-last-route.js +24 -0
  92. package/config/settings.ts +66 -98
  93. package/config/version.js +1 -1
  94. package/core/types-provisioning.ts +7 -0
  95. package/detail/fleet.cattle.io.bundle.vue +7 -0
  96. package/detail/fleet.cattle.io.cluster.vue +0 -3
  97. package/detail/fleet.cattle.io.gitrepo.vue +8 -15
  98. package/detail/provisioning.cattle.io.cluster.vue +8 -2
  99. package/dialog/DeactivateDriverDialog.vue +5 -5
  100. package/dialog/GitRepoForceUpdateDialog.vue +132 -0
  101. package/directives/strip-html-aria-label.js +19 -0
  102. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +87 -0
  103. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +217 -37
  104. package/edit/auth/__tests__/oidc.test.ts +60 -12
  105. package/edit/auth/ldap/__tests__/config.test.ts +40 -0
  106. package/edit/auth/ldap/config.vue +67 -89
  107. package/edit/auth/oidc.vue +16 -2
  108. package/edit/catalog.cattle.io.clusterrepo.vue +12 -8
  109. package/edit/cis.cattle.io.clusterscan.vue +13 -1
  110. package/edit/fleet.cattle.io.gitrepo.vue +198 -72
  111. package/edit/logging-flow/Match.vue +0 -21
  112. package/edit/management.cattle.io.project.vue +1 -1
  113. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +10 -3
  114. package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +5 -1
  115. package/edit/monitoring.coreos.com.prometheusrule/index.vue +5 -2
  116. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +8 -1
  117. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -0
  118. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -2
  119. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +55 -15
  120. package/edit/provisioning.cattle.io.cluster/index.vue +28 -30
  121. package/edit/provisioning.cattle.io.cluster/rke2.vue +64 -13
  122. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +37 -2
  123. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -2
  124. package/edit/resources.cattle.io.backup.vue +150 -15
  125. package/edit/secret/__tests__/ssh.test.ts +79 -0
  126. package/edit/secret/ssh.vue +7 -1
  127. package/edit/service.vue +0 -3
  128. package/edit/workload/Job.vue +8 -8
  129. package/edit/workload/__tests__/Job.test.ts +0 -1
  130. package/edit/workload/index.vue +3 -1
  131. package/initialize/install-directives.js +2 -0
  132. package/initialize/install-plugins.js +6 -1
  133. package/list/catalog.cattle.io.app.vue +21 -4
  134. package/list/fleet.cattle.io.bundle.vue +1 -1
  135. package/list/management.cattle.io.setting.vue +34 -132
  136. package/list/provisioning.cattle.io.cluster.vue +11 -3
  137. package/machine-config/vmwarevsphere.vue +15 -8
  138. package/mixins/__tests__/auth-config.test.ts +74 -0
  139. package/mixins/__tests__/chart.test.ts +5 -4
  140. package/mixins/__tests__/create-edit-view.test.ts +38 -0
  141. package/mixins/auth-config.js +8 -0
  142. package/mixins/chart.js +2 -2
  143. package/mixins/create-edit-view/impl.js +4 -1
  144. package/mixins/vue-select-overrides.js +10 -0
  145. package/models/__tests__/catalog.cattle.io.app.test.ts +148 -0
  146. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +157 -0
  147. package/models/__tests__/secret.test.ts +56 -13
  148. package/models/catalog.cattle.io.app.js +112 -37
  149. package/models/cluster.js +11 -0
  150. package/models/fleet.cattle.io.bundle.js +40 -2
  151. package/models/fleet.cattle.io.gitrepo.js +169 -109
  152. package/models/management.cattle.io.fleetworkspace.js +4 -0
  153. package/models/management.cattle.io.kontainerdriver.js +7 -0
  154. package/models/nodedriver.js +4 -1
  155. package/models/provisioning.cattle.io.cluster.js +24 -0
  156. package/models/secret.js +1 -1
  157. package/package.json +5 -5
  158. package/pages/auth/login.vue +5 -11
  159. package/pages/auth/verify.vue +11 -1
  160. package/pages/c/_cluster/apps/charts/index.vue +6 -4
  161. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  162. package/pages/c/_cluster/explorer/ConfigBadge.vue +3 -5
  163. package/pages/c/_cluster/explorer/EventsTable.vue +3 -2
  164. package/pages/c/_cluster/explorer/__tests__/index.test.ts +9 -9
  165. package/pages/c/_cluster/explorer/index.vue +33 -35
  166. package/pages/c/_cluster/explorer/tools/index.vue +3 -3
  167. package/pages/c/_cluster/fleet/index.vue +0 -5
  168. package/pages/c/_cluster/legacy/project/index.vue +1 -1
  169. package/pages/c/_cluster/settings/performance.vue +52 -53
  170. package/pages/c/_cluster/uiplugins/index.vue +19 -22
  171. package/pages/home.vue +17 -12
  172. package/pages/prefs.vue +5 -1
  173. package/plugins/shortkey.js +10 -1
  174. package/plugins/steve/steve-pagination-utils.ts +58 -8
  175. package/promptRemove/management.cattle.io.fleetworkspace.vue +98 -0
  176. package/promptRemove/management.cattle.io.globalrole.vue +1 -1
  177. package/promptRemove/management.cattle.io.project.vue +2 -8
  178. package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
  179. package/promptRemove/mixin/roleDeletionCheck.js +1 -7
  180. package/promptRemove/pod.vue +7 -28
  181. package/rancher-components/Card/Card.vue +9 -1
  182. package/rancher-components/Form/Checkbox/Checkbox.vue +42 -6
  183. package/rancher-components/Form/LabeledInput/LabeledInput.vue +30 -3
  184. package/rancher-components/Form/Radio/RadioButton.vue +18 -3
  185. package/rancher-components/Form/Radio/RadioGroup.vue +39 -5
  186. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +13 -1
  187. package/rancher-components/RcButton/RcButton.test.ts +97 -0
  188. package/rancher-components/RcButton/RcButton.vue +14 -9
  189. package/rancher-components/RcDropdown/RcDropdown.vue +3 -1
  190. package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -2
  191. package/rancher-components/RcDropdown/RcDropdownMenu.vue +66 -0
  192. package/rancher-components/RcDropdown/index.ts +1 -0
  193. package/rancher-components/RcDropdown/types.ts +27 -0
  194. package/rancher-components/RcDropdown/useDropdownContext.ts +5 -2
  195. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
  196. package/scripts/typegen.sh +1 -0
  197. package/store/__tests__/auth.test.ts +120 -0
  198. package/store/action-menu.js +13 -3
  199. package/store/auth.js +14 -9
  200. package/store/aws.js +9 -2
  201. package/store/catalog.js +14 -7
  202. package/store/features.js +1 -0
  203. package/store/prefs.js +9 -28
  204. package/store/type-map.utils.ts +4 -0
  205. package/types/resources/settings.d.ts +27 -20
  206. package/types/shell/index.d.ts +18 -12
  207. package/utils/__tests__/array.test.ts +13 -1
  208. package/utils/__tests__/string.test.ts +80 -1
  209. package/utils/array.ts +13 -0
  210. package/utils/auth.js +4 -0
  211. package/utils/banners.js +0 -45
  212. package/utils/cluster.js +1 -1
  213. package/{edit/monitoring.coreos.com.prometheusrule → utils}/duration.js +5 -3
  214. package/utils/object.js +0 -3
  215. package/utils/pagination-utils.ts +15 -2
  216. package/utils/string.js +31 -7
  217. package/utils/validators/formRules/__tests__/index.test.ts +27 -0
  218. package/utils/validators/formRules/index.ts +16 -0
  219. package/edit/provisioning.cattle.io.cluster/import.vue +0 -198
@@ -1,5 +1,7 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import CustomCommand from '@shell/edit/provisioning.cattle.io.cluster/CustomCommand.vue';
3
+ import { clone } from '@shell/utils/object';
4
+
3
5
  jest.mock('@shell/utils/clipboard', () => {
4
6
  return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
5
7
  });
@@ -8,9 +10,9 @@ describe('component: CustomCommand', () => {
8
10
  const token = 'MY_TOKEN';
9
11
  const ip = 'MY_IP';
10
12
  const checkSum = 'MY_CHECKSUM';
11
- const wrapper = mount(CustomCommand, {
13
+ const customCommandConfig = {
12
14
  props: {
13
- cluster: {},
15
+ cluster: { },
14
16
  clusterToken: {
15
17
  insecureNodeCommand: ` curl --insecure -fL ${ ip }/system-agent-install.sh | sudo sh -s - --server ${ ip } --label 'cattle.io/os=linux' --token ${ token } --ca-checksum ${ checkSum }`,
16
18
  nodeCommand: ` curl -fL ${ ip }/system-agent-install.sh | sudo sh -s - --server ${ ip } --label 'cattle.io/os=linux' --token ${ token } --ca-checksum ${ checkSum }`
@@ -40,28 +42,34 @@ describe('component: CustomCommand', () => {
40
42
  },
41
43
  },
42
44
  },
43
- });
45
+ };
44
46
 
45
- it('should return linux commands with the right flags based on cluster information', () => {
46
- const value = `curl -fL ${ ip }/system-agent-install.sh | sudo sh -s - --server ${ ip } --label 'cattle.io/os=linux' --token ${ token } --ca-checksum ${ checkSum } --etcd --controlplane --worker`;
47
- const element = wrapper.find('#copiedLinux').element;
47
+ describe('should show basic messaging', () => {
48
+ const wrapper = mount(CustomCommand, customCommandConfig);
48
49
 
49
- expect(element.textContent).toContain(value);
50
- });
50
+ it('should return linux commands with the right flags based on cluster information', () => {
51
+ const value = `curl -fL ${ ip }/system-agent-install.sh | sudo sh -s - --server ${ ip } --label 'cattle.io/os=linux' --token ${ token } --ca-checksum ${ checkSum } --etcd --controlplane --worker`;
52
+ const element = wrapper.find('#copiedLinux').element;
51
53
 
52
- it('should not display warning message if all node roles are selected', async() => {
53
- await wrapper.setData({
54
- controlPlane: true,
55
- etcd: true,
56
- worker: true,
54
+ expect(element.textContent).toContain(value);
57
55
  });
58
56
 
59
- const element = wrapper.find('[data-testid="node-role-warning"]');
57
+ it('should not display warning message if all node roles are selected', async() => {
58
+ await wrapper.setData({
59
+ controlPlane: true,
60
+ etcd: true,
61
+ worker: true,
62
+ });
63
+
64
+ const element = wrapper.find('[data-testid="node-role-warning"]');
60
65
 
61
- expect(element.exists()).toBe(false);
66
+ expect(element.exists()).toBe(false);
67
+ });
62
68
  });
63
69
 
64
70
  describe('should display warning message if at least one of the node roles is unselected', () => {
71
+ const wrapper = mount(CustomCommand, customCommandConfig);
72
+
65
73
  it.each([
66
74
  [true, true, false],
67
75
  [true, false, true],
@@ -86,4 +94,36 @@ describe('component: CustomCommand', () => {
86
94
  expect(element).toBeDefined();
87
95
  });
88
96
  });
97
+
98
+ describe('should show windows messaging when appropriate', () => {
99
+ it('should show ready for windows banner if the cluster supports windows', () => {
100
+ const config = clone(customCommandConfig);
101
+
102
+ config.props.cluster = {
103
+ supportsWindows: true,
104
+ mgmt: { isReady: true },
105
+ nodes: [
106
+ { isWorker: true },
107
+ { isEtcd: true },
108
+ { isControlPlane: true }
109
+ ]
110
+ };
111
+ const wrapper = mount(CustomCommand, config);
112
+
113
+ const element = wrapper.find('[data-testid="ready-for-windows"]');
114
+
115
+ expect(element.exists()).toBe(true);
116
+ });
117
+
118
+ it('should NOT show ready for windows banner if the cluster supports windows', () => {
119
+ const config = clone(customCommandConfig);
120
+
121
+ config.props.cluster = { supportsWindows: true };
122
+ const wrapper = mount(CustomCommand, config);
123
+
124
+ const element = wrapper.find('[data-testid="windows-not-ready"]');
125
+
126
+ expect(element.exists()).toBe(true);
127
+ });
128
+ });
89
129
  });
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import CreateEditView from '@shell/mixins/create-edit-view';
3
3
  import Loading from '@shell/components/Loading';
4
+ import { Banner } from '@components/Banner';
4
5
  import CruResource from '@shell/components/CruResource';
5
6
  import SelectIconGrid from '@shell/components/SelectIconGrid';
6
7
  import EmberPage from '@shell/components/EmberPage';
@@ -19,7 +20,6 @@ import { allHash } from '@shell/utils/promise';
19
20
  import { BLANK_CLUSTER } from '@shell/store/store-types.js';
20
21
  import { ELEMENTAL_PRODUCT_NAME, ELEMENTAL_CLUSTER_PROVIDER } from '../../config/elemental-types';
21
22
  import Rke2Config from './rke2';
22
- import Import from './import';
23
23
  import { DRIVER_TO_IMPORT } from '@shell/models/management.cattle.io.kontainerdriver';
24
24
 
25
25
  const SORT_GROUPS = {
@@ -46,11 +46,11 @@ export default {
46
46
  components: {
47
47
  CruResource,
48
48
  EmberPage,
49
- Import,
50
49
  Loading,
51
50
  Rke2Config,
52
51
  SelectIconGrid,
53
- ToggleSwitch
52
+ ToggleSwitch,
53
+ Banner
54
54
  },
55
55
 
56
56
  mixins: [CreateEditView],
@@ -345,10 +345,7 @@ export default {
345
345
  addType(this.$plugin, obj.driverName, 'kontainer', false, (isImport ? obj.emberImportPath : obj.emberCreatePath));
346
346
  }
347
347
  });
348
-
349
- if ( isImport ) {
350
- addType(this.$plugin, 'import', 'custom', false);
351
- } else {
348
+ if (!isImport) {
352
349
  templates.forEach((chart) => {
353
350
  out.push({
354
351
  id: `chart:${ chart.id }`,
@@ -385,23 +382,26 @@ export default {
385
382
 
386
383
  addType(this.$plugin, 'custom', 'custom2', false);
387
384
  }
388
-
389
- // Add from extensions
390
- this.extensions.forEach((ext) => {
385
+ }
386
+ // Add from extensions
387
+ this.extensions.forEach((ext) => {
391
388
  // if the rke toggle is set to rke1, don't add extensions that specify rke2 group
392
389
  // default group is rke2
393
- if (!this.isRke2 && (ext.group === _RKE2 || !ext.group)) {
394
- return;
395
- }
396
- // Do not show the extension provisioner on the import cluster page unless its explicitly set to do so
397
- if (isImport && !ext.showImport) {
398
- return;
399
- }
400
- // Allow extensions to overwrite provisioners with the same id
401
- out = out.filter((type) => type.id !== ext.id);
402
- addExtensionType(ext, getters);
403
- });
404
- }
390
+ if (!this.isRke2 && (ext.group === _RKE2 || !ext.group)) {
391
+ return;
392
+ }
393
+ // Do not show the extension provisioner on the import cluster page unless its explicitly set to do so
394
+ if (isImport && !ext.showImport) {
395
+ return;
396
+ }
397
+ // Do not show the extension provisioner on create if it is disabled
398
+ if (!isImport && !!ext.hideCreate) {
399
+ return;
400
+ }
401
+ // Allow extensions to overwrite provisioners with the same id
402
+ out = out.filter((type) => type.id !== ext.id);
403
+ addExtensionType(ext, getters);
404
+ });
405
405
 
406
406
  return out;
407
407
 
@@ -669,6 +669,11 @@ export default {
669
669
  </div>
670
670
  {{ obj.label }}
671
671
  </h4>
672
+ <Banner
673
+ v-if="provisioner === _RKE1 && i === 1"
674
+ color="warning"
675
+ label-key="cluster.banner.rke1DeprecationShortMessage"
676
+ />
672
677
  <SelectIconGrid
673
678
  :rows="obj.types"
674
679
  key-field="id"
@@ -681,14 +686,7 @@ export default {
681
686
  </div>
682
687
  </template>
683
688
 
684
- <Import
685
- v-if="isImport"
686
- v-model:value="localValue"
687
- :mode="mode"
688
- :provider="subType"
689
- @update:value="$emit('input', $event)"
690
- />
691
- <template v-else-if="subType">
689
+ <template v-if="subType">
692
690
  <!-- allow extensions to provide their own cluster provisioning form -->
693
691
  <component
694
692
  :is="selectedSubType.component"
@@ -47,7 +47,7 @@ import Labels from '@shell/edit/provisioning.cattle.io.cluster/Labels';
47
47
  import MachinePool from '@shell/edit/provisioning.cattle.io.cluster/tabs/MachinePool';
48
48
  import SelectCredential from './SelectCredential';
49
49
  import { ELEMENTAL_SCHEMA_IDS, KIND, ELEMENTAL_CLUSTER_PROVIDER } from '../../config/elemental-types';
50
- import AgentConfiguration from '@shell/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration';
50
+ import AgentConfiguration from '@shell/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue';
51
51
  import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
52
52
  import { ExtensionPoint, TabLocation } from '@shell/core/types';
53
53
  import MemberRoles from '@shell/edit/provisioning.cattle.io.cluster/tabs/MemberRoles';
@@ -62,7 +62,8 @@ import { DEFAULT_COMMON_BASE_PATH, DEFAULT_SUBDIRS } from '@shell/edit/provision
62
62
  import ClusterAppearance from '@shell/components/form/ClusterAppearance';
63
63
  import AddOnAdditionalManifest from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest';
64
64
  import VsphereUtils, { VMWARE_VSPHERE } from '@shell/utils/v-sphere';
65
-
65
+ import { mapGetters } from 'vuex';
66
+ import { SCHEDULING_CUSTOMIZATION } from '@shell/store/features';
66
67
  const HARVESTER = 'harvester';
67
68
  const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
68
69
  const NETBIOS_TRUNCATION_LENGTH = 15;
@@ -87,6 +88,8 @@ const NODE_TOTAL = {
87
88
  const CLUSTER_AGENT_CUSTOMIZATION = 'clusterAgentDeploymentCustomization';
88
89
  const FLEET_AGENT_CUSTOMIZATION = 'fleetAgentDeploymentCustomization';
89
90
 
91
+ const REGISTRIES_TAB_NAME = 'registry';
92
+
90
93
  const isAzureK8sUnsupported = (version) => semver.gte(version, '1.30.0');
91
94
 
92
95
  export default {
@@ -146,6 +149,7 @@ export default {
146
149
  await this.initSpecs();
147
150
  await this.initAddons();
148
151
  await this.initRegistry();
152
+ await this.initSchedulingCustomization();
149
153
 
150
154
  Object.entries(this.chartValues).forEach(([name, value]) => {
151
155
  const key = this.chartVersionKey(name);
@@ -239,20 +243,31 @@ export default {
239
243
  fvFormRuleSets: [{
240
244
  path: 'metadata.name', rules: ['subDomain'], translationKey: 'nameNsDescription.name.label'
241
245
  }],
242
- harvesterVersionRange: {},
243
- cisOverride: false,
246
+ harvesterVersionRange: {},
247
+ cisOverride: false,
244
248
  truncateLimit,
245
- busy: false,
246
- machinePoolValidation: {}, // map of validation states for each machine pool
247
- machinePoolErrors: {},
248
- addonConfigValidation: {}, // validation state of each addon config (boolean of whether codemirror's yaml lint passed)
249
- allNamespaces: [],
250
- extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.CLUSTER_CREATE_RKE2, this.$route, this),
249
+ busy: false,
250
+ machinePoolValidation: {}, // map of validation states for each machine pool
251
+ machinePoolErrors: {},
252
+ addonConfigValidation: {}, // validation state of each addon config (boolean of whether codemirror's yaml lint passed)
253
+ allNamespaces: [],
254
+ extensionTabs: getApplicableExtensionEnhancements(this, ExtensionPoint.TAB, TabLocation.CLUSTER_CREATE_RKE2, this.$route, this),
255
+ clusterAgentDeploymentCustomization: null,
256
+ schedulingCustomizationFeatureEnabled: false,
257
+ clusterAgentDefaultPC: null,
258
+ clusterAgentDefaultPDB: null,
259
+ activeTab: null,
260
+ REGISTRIES_TAB_NAME,
251
261
  labelForAddon
262
+
252
263
  };
253
264
  },
254
265
 
255
266
  computed: {
267
+ ...mapGetters({ features: 'features/get' }),
268
+ isActiveTabRegistries() {
269
+ return this.activeTab?.selectedName === REGISTRIES_TAB_NAME;
270
+ },
256
271
  clusterName() {
257
272
  return this.value.metadata?.name || '';
258
273
  },
@@ -1047,6 +1062,32 @@ export default {
1047
1062
  }
1048
1063
  },
1049
1064
 
1065
+ async initSchedulingCustomization() {
1066
+ this.schedulingCustomizationFeatureEnabled = this.features(SCHEDULING_CUSTOMIZATION);
1067
+ try {
1068
+ this.clusterAgentDefaultPC = JSON.parse((await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS })).value) || null;
1069
+ } catch (e) {
1070
+ this.errors.push(e);
1071
+ }
1072
+ try {
1073
+ this.clusterAgentDefaultPDB = JSON.parse((await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET })).value) || null;
1074
+ } catch (e) {
1075
+ this.errors.push(e);
1076
+ }
1077
+
1078
+ if (this.schedulingCustomizationFeatureEnabled && this.mode === _CREATE && isEmpty(this.value?.spec?.clusterAgentDeploymentCustomization?.schedulingCustomization)) {
1079
+ set(this.value, 'spec.clusterAgentDeploymentCustomization.schedulingCustomization', { priorityClass: this.clusterAgentDefaultPC, podDisruptionBudget: this.clusterAgentDefaultPDB });
1080
+ }
1081
+ },
1082
+
1083
+ setSchedulingCustomization(val) {
1084
+ if (val) {
1085
+ set(this.value, 'spec.clusterAgentDeploymentCustomization.schedulingCustomization', { priorityClass: this.clusterAgentDefaultPC, podDisruptionBudget: this.clusterAgentDefaultPDB });
1086
+ } else {
1087
+ delete this.value.spec.clusterAgentDeploymentCustomization.schedulingCustomization;
1088
+ }
1089
+ },
1090
+
1050
1091
  cleanAgentConfiguration(model, key) {
1051
1092
  if (!model || !model[key]) {
1052
1093
  return;
@@ -1660,7 +1701,7 @@ export default {
1660
1701
  const defaultChartValue = this.versionInfo[name];
1661
1702
  const key = this.chartVersionKey(name);
1662
1703
 
1663
- return mergeWithReplaceArrays(defaultChartValue?.values, this.userChartValues[key]);
1704
+ return merge({}, defaultChartValue?.values || {}, this.userChartValues[key] || {});
1664
1705
  },
1665
1706
 
1666
1707
  initServerAgentArgs() {
@@ -2051,6 +2092,10 @@ export default {
2051
2092
  addonConfigValidationChanged(configName, isValid) {
2052
2093
  this.addonConfigValidation[configName] = isValid;
2053
2094
  },
2095
+
2096
+ handleTabChange(data) {
2097
+ this.activeTab = data;
2098
+ }
2054
2099
  }
2055
2100
  };
2056
2101
  </script>
@@ -2218,6 +2263,7 @@ export default {
2218
2263
  <Tabbed
2219
2264
  :side-tabs="true"
2220
2265
  class="min-height"
2266
+ @changed="handleTabChange"
2221
2267
  >
2222
2268
  <Tab
2223
2269
  name="basic"
@@ -2328,10 +2374,11 @@ export default {
2328
2374
 
2329
2375
  <!-- Registries -->
2330
2376
  <Tab
2331
- name="registry"
2377
+ :name="REGISTRIES_TAB_NAME"
2332
2378
  label-key="cluster.tabs.registry"
2333
2379
  >
2334
2380
  <Registries
2381
+ v-if="isActiveTabRegistries"
2335
2382
  v-model:value="localValue"
2336
2383
  :mode="mode"
2337
2384
  :register-before-hook="registerBeforeHook"
@@ -2391,15 +2438,19 @@ export default {
2391
2438
 
2392
2439
  <!-- Cluster Agent Configuration -->
2393
2440
  <Tab
2441
+ v-if="value.spec.clusterAgentDeploymentCustomization"
2394
2442
  name="clusteragentconfig"
2395
2443
  label-key="cluster.agentConfig.tabs.cluster"
2396
2444
  >
2397
2445
  <AgentConfiguration
2398
- v-if="value.spec.clusterAgentDeploymentCustomization"
2399
2446
  v-model:value="value.spec.clusterAgentDeploymentCustomization"
2400
2447
  data-testid="rke2-cluster-agent-config"
2401
2448
  type="cluster"
2402
2449
  :mode="mode"
2450
+ :scheduling-customization-feature-enabled="schedulingCustomizationFeatureEnabled"
2451
+ :default-p-c="clusterAgentDefaultPC"
2452
+ :default-p-d-b="clusterAgentDefaultPDB"
2453
+ @scheduling-customization-changed="setSchedulingCustomization"
2403
2454
  />
2404
2455
  </Tab>
2405
2456
 
@@ -5,10 +5,11 @@ import PodAffinity from '@shell/components/form/PodAffinity';
5
5
  import NodeAffinity from '@shell/components/form/NodeAffinity';
6
6
  import ContainerResourceLimit from '@shell/components/ContainerResourceLimit';
7
7
  import Tolerations from '@shell/components/form/Tolerations';
8
+ import SchedulingCustomization from '@shell/components/form/SchedulingCustomization';
8
9
  import { cleanUp } from '@shell/utils/object';
9
10
  import { fetchSetting } from '@shell/utils/settings';
10
11
  import { RadioGroup } from '@components/Form/Radio';
11
-
12
+ import { _EDIT } from '@shell/config/query-params';
12
13
  // Affinity radio button choices
13
14
  const DEFAULT = 'default';
14
15
  const CUSTOM = 'custom';
@@ -16,7 +17,7 @@ const CUSTOM = 'custom';
16
17
  // This is the form for Agent Configuration
17
18
  // Used for both Cluster Agent and Fleet Agent configuration
18
19
  export default {
19
- emits: ['input'],
20
+ emits: ['input', 'scheduling-customization-changed'],
20
21
 
21
22
  components: {
22
23
  Banner,
@@ -26,6 +27,7 @@ export default {
26
27
  NodeAffinity,
27
28
  RadioGroup,
28
29
  Tolerations,
30
+ SchedulingCustomization
29
31
  },
30
32
  props: {
31
33
  value: {
@@ -41,6 +43,18 @@ export default {
41
43
  type: {
42
44
  type: String,
43
45
  required: true,
46
+ },
47
+ schedulingCustomizationFeatureEnabled: {
48
+ type: Boolean,
49
+ required: false
50
+ },
51
+ defaultPC: {
52
+ type: Object,
53
+ default: () => {},
54
+ },
55
+ defaultPDB: {
56
+ type: Object,
57
+ default: () => {},
44
58
  }
45
59
  },
46
60
 
@@ -130,6 +144,13 @@ export default {
130
144
  this.value['overrideResourceRequirements'] = cleanUp(out);
131
145
  },
132
146
  },
147
+ isEdit() {
148
+ return this.mode === _EDIT;
149
+ },
150
+
151
+ schedulingCustomizationVisible() {
152
+ return this.schedulingCustomizationFeatureEnabled || (this.isEdit && this.value.schedulingCustomization );
153
+ },
133
154
 
134
155
  affinityOptions() {
135
156
  return [{
@@ -289,6 +310,20 @@ export default {
289
310
  @update:value="updateNodeAffinity"
290
311
  />
291
312
  </GroupPanel>
313
+ <GroupPanel
314
+ v-if="schedulingCustomizationVisible"
315
+ label-key="cluster.agentConfig.groups.schedulingCustomization"
316
+ class="mt-20"
317
+ >
318
+ <SchedulingCustomization
319
+ :value="value.schedulingCustomization"
320
+ :mode="mode"
321
+ :feature="schedulingCustomizationFeatureEnabled"
322
+ :default-p-c="defaultPC"
323
+ :default-p-d-b="defaultPDB"
324
+ @scheduling-customization-changed="$emit('scheduling-customization-changed', $event)"
325
+ />
326
+ </GroupPanel>
292
327
  </div>
293
328
  </template>
294
329
 
@@ -91,6 +91,7 @@ export default {
91
91
  :mode="mode"
92
92
  :label="t('cluster.rke2.etcd.snapshotRetention.label')"
93
93
  :suffix="t('cluster.rke2.snapshots.suffix')"
94
+ :tooltip="t('cluster.rke2.etcd.snapshotRetention.tooltip')"
94
95
  />
95
96
  </div>
96
97
  </div>
@@ -102,8 +103,8 @@ export default {
102
103
  :value="s3Backup"
103
104
  name="etcd-s3"
104
105
  :options="[false, true]"
105
- label="Backup Snapshots to S3"
106
- :labels="['Disable','Enable']"
106
+ :label="t('cluster.rke2.etcd.s3backups.label')"
107
+ :labels="[t('generic.disable'),t('generic.enable')]"
107
108
  :mode="mode"
108
109
  @update:value="$emit('s3-backup-changed', $event)"
109
110
  />