@rancher/shell 3.0.2-rc.4 → 3.0.2-rc.6

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 (212) 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 +1 -0
  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 +142 -22
  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 +15 -1
  17. package/components/ButtonMultiAction.vue +5 -1
  18. package/components/ClusterBadge.vue +1 -0
  19. package/components/ClusterIconMenu.vue +3 -0
  20. package/components/ClusterProviderIcon.vue +14 -1
  21. package/components/CodeMirror.vue +96 -5
  22. package/components/Collapse.vue +16 -3
  23. package/components/CopyToClipboardText.vue +3 -1
  24. package/components/CruResource.vue +9 -0
  25. package/components/CruResourceFooter.vue +1 -1
  26. package/components/ExplorerMembers.vue +2 -1
  27. package/components/ExplorerProjectsNamespaces.vue +7 -0
  28. package/components/Import.vue +14 -1
  29. package/components/LandingPagePreference.vue +4 -2
  30. package/components/PodSecurityAdmission.vue +8 -6
  31. package/components/PromptChangePassword.vue +1 -0
  32. package/components/PromptRemove.vue +23 -21
  33. package/components/ResourceDetail/Masthead.vue +30 -11
  34. package/components/ResourceDetail/__tests__/Masthead.test.ts +61 -0
  35. package/components/ResourceDetail/index.vue +6 -0
  36. package/components/ResourceTable.vue +6 -14
  37. package/components/ResourceYaml.vue +1 -0
  38. package/components/SelectIconGrid.vue +2 -0
  39. package/components/Setting.vue +115 -0
  40. package/components/SortableTable/THead.vue +2 -0
  41. package/components/SortableTable/index.vue +38 -14
  42. package/components/Tabbed/index.vue +16 -15
  43. package/components/Wizard.vue +108 -104
  44. package/components/YamlEditor.vue +12 -2
  45. package/components/__tests__/Collapse.test.ts +2 -2
  46. package/components/auth/Principal.vue +29 -17
  47. package/components/auth/__tests__/Principal.test.ts +40 -0
  48. package/components/auth/login/ldap.vue +7 -0
  49. package/components/fleet/FleetBundles.vue +1 -1
  50. package/components/fleet/FleetRepos.vue +1 -1
  51. package/components/fleet/FleetResources.vue +0 -2
  52. package/components/fleet/FleetSummary.vue +60 -65
  53. package/components/fleet/ForceDirectedTreeChart/index.vue +5 -1
  54. package/components/fleet/__tests__/FleetSummary.test.ts +49 -9
  55. package/components/form/ArrayList.vue +6 -2
  56. package/components/form/ColorInput.vue +1 -0
  57. package/components/form/KeyValue.vue +11 -12
  58. package/components/form/LabeledSelect.vue +16 -3
  59. package/components/form/Labels.vue +8 -1
  60. package/components/form/Members/MembershipEditor.vue +230 -222
  61. package/components/form/Members/__tests__/MembershipEditor.test.ts +62 -0
  62. package/components/form/Password.vue +3 -0
  63. package/components/form/ProjectMemberEditor.vue +6 -3
  64. package/components/form/ResourceTabs/index.vue +15 -13
  65. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +5 -4
  66. package/components/form/SchedulingCustomization.vue +85 -0
  67. package/components/form/Select.vue +4 -2
  68. package/components/form/SelectOrCreateAuthSecret.vue +2 -1
  69. package/components/form/UnitInput.vue +1 -2
  70. package/components/form/__tests__/ArrayList.test.ts +9 -6
  71. package/components/form/__tests__/LabeledSelect.test.ts +37 -0
  72. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +34 -0
  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/WindowManager/ContainerLogs.vue +97 -49
  83. package/components/nav/WindowManager/ContainerShell.vue +99 -18
  84. package/components/nav/WindowManager/index.vue +85 -6
  85. package/components/templates/default.vue +2 -47
  86. package/config/features.js +1 -0
  87. package/config/home-links.js +1 -1
  88. package/config/labels-annotations.js +11 -1
  89. package/config/router/navigation-guards/index.js +2 -1
  90. package/config/router/navigation-guards/record-last-route.js +24 -0
  91. package/config/settings.ts +66 -98
  92. package/config/version.js +1 -1
  93. package/core/types-provisioning.ts +7 -0
  94. package/detail/fleet.cattle.io.bundle.vue +7 -0
  95. package/detail/fleet.cattle.io.cluster.vue +0 -3
  96. package/detail/fleet.cattle.io.gitrepo.vue +8 -15
  97. package/detail/provisioning.cattle.io.cluster.vue +8 -2
  98. package/dialog/DeactivateDriverDialog.vue +5 -5
  99. package/dialog/GitRepoForceUpdateDialog.vue +132 -0
  100. package/directives/strip-html-aria-label.js +19 -0
  101. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +87 -0
  102. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +217 -37
  103. package/edit/auth/__tests__/oidc.test.ts +26 -9
  104. package/edit/auth/ldap/__tests__/config.test.ts +40 -0
  105. package/edit/auth/ldap/config.vue +67 -89
  106. package/edit/auth/oidc.vue +15 -1
  107. package/edit/catalog.cattle.io.clusterrepo.vue +12 -8
  108. package/edit/cis.cattle.io.clusterscan.vue +13 -1
  109. package/edit/fleet.cattle.io.gitrepo.vue +198 -72
  110. package/edit/logging-flow/Match.vue +0 -21
  111. package/edit/management.cattle.io.project.vue +1 -1
  112. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +10 -3
  113. package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +5 -1
  114. package/edit/monitoring.coreos.com.prometheusrule/index.vue +5 -2
  115. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +8 -1
  116. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -0
  117. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +55 -15
  118. package/edit/provisioning.cattle.io.cluster/index.vue +39 -39
  119. package/edit/provisioning.cattle.io.cluster/rke2.vue +63 -12
  120. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +37 -2
  121. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -2
  122. package/edit/resources.cattle.io.backup.vue +150 -15
  123. package/edit/secret/__tests__/ssh.test.ts +79 -0
  124. package/edit/secret/ssh.vue +7 -1
  125. package/edit/workload/Job.vue +2 -2
  126. package/edit/workload/index.vue +3 -1
  127. package/initialize/install-directives.js +2 -0
  128. package/initialize/install-plugins.js +6 -1
  129. package/list/catalog.cattle.io.app.vue +21 -4
  130. package/list/fleet.cattle.io.bundle.vue +1 -1
  131. package/list/management.cattle.io.setting.vue +34 -129
  132. package/list/provisioning.cattle.io.cluster.vue +11 -3
  133. package/machine-config/vmwarevsphere.vue +15 -8
  134. package/mixins/__tests__/auth-config.test.ts +74 -0
  135. package/mixins/__tests__/chart.test.ts +5 -4
  136. package/mixins/__tests__/create-edit-view.test.ts +38 -0
  137. package/mixins/auth-config.js +9 -1
  138. package/mixins/chart.js +2 -2
  139. package/mixins/create-edit-view/impl.js +4 -1
  140. package/mixins/vue-select-overrides.js +10 -0
  141. package/models/__tests__/catalog.cattle.io.app.test.ts +148 -0
  142. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +157 -0
  143. package/models/__tests__/secret.test.ts +56 -13
  144. package/models/catalog.cattle.io.app.js +112 -37
  145. package/models/cluster.js +11 -0
  146. package/models/fleet.cattle.io.bundle.js +40 -2
  147. package/models/fleet.cattle.io.gitrepo.js +169 -109
  148. package/models/management.cattle.io.fleetworkspace.js +4 -0
  149. package/models/management.cattle.io.kontainerdriver.js +7 -0
  150. package/models/nodedriver.js +4 -1
  151. package/models/provisioning.cattle.io.cluster.js +24 -0
  152. package/models/secret.js +1 -1
  153. package/package.json +4 -4
  154. package/pages/auth/login.vue +4 -2
  155. package/pages/auth/verify.vue +11 -1
  156. package/pages/c/_cluster/apps/charts/chart.vue +1 -0
  157. package/pages/c/_cluster/apps/charts/index.vue +6 -4
  158. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  159. package/pages/c/_cluster/explorer/ConfigBadge.vue +3 -5
  160. package/pages/c/_cluster/explorer/EventsTable.vue +3 -2
  161. package/pages/c/_cluster/explorer/__tests__/index.test.ts +9 -9
  162. package/pages/c/_cluster/explorer/index.vue +33 -35
  163. package/pages/c/_cluster/explorer/tools/index.vue +17 -4
  164. package/pages/c/_cluster/fleet/index.vue +0 -5
  165. package/pages/c/_cluster/legacy/project/index.vue +1 -1
  166. package/pages/c/_cluster/settings/performance.vue +52 -53
  167. package/pages/c/_cluster/uiplugins/index.vue +21 -22
  168. package/pages/home.vue +17 -12
  169. package/pages/prefs.vue +5 -1
  170. package/plugins/shortkey.js +10 -1
  171. package/plugins/steve/steve-pagination-utils.ts +58 -8
  172. package/promptRemove/management.cattle.io.fleetworkspace.vue +98 -0
  173. package/promptRemove/management.cattle.io.globalrole.vue +1 -1
  174. package/promptRemove/management.cattle.io.project.vue +2 -8
  175. package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
  176. package/promptRemove/mixin/roleDeletionCheck.js +1 -7
  177. package/promptRemove/pod.vue +7 -28
  178. package/rancher-components/Card/Card.vue +9 -1
  179. package/rancher-components/Form/Checkbox/Checkbox.vue +42 -6
  180. package/rancher-components/Form/LabeledInput/LabeledInput.vue +30 -3
  181. package/rancher-components/Form/Radio/RadioButton.vue +18 -3
  182. package/rancher-components/Form/Radio/RadioGroup.vue +39 -5
  183. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +13 -1
  184. package/rancher-components/RcButton/RcButton.test.ts +97 -0
  185. package/rancher-components/RcButton/RcButton.vue +14 -9
  186. package/rancher-components/RcDropdown/RcDropdown.vue +3 -1
  187. package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -14
  188. package/rancher-components/RcDropdown/RcDropdownMenu.vue +66 -0
  189. package/rancher-components/RcDropdown/index.ts +1 -0
  190. package/rancher-components/RcDropdown/types.ts +27 -0
  191. package/rancher-components/RcDropdown/useDropdownContext.ts +5 -2
  192. package/scripts/typegen.sh +1 -0
  193. package/store/__tests__/auth.test.ts +120 -0
  194. package/store/action-menu.js +13 -3
  195. package/store/auth.js +14 -9
  196. package/store/catalog.js +14 -7
  197. package/store/features.js +1 -0
  198. package/store/prefs.js +9 -28
  199. package/store/type-map.utils.ts +4 -0
  200. package/types/resources/settings.d.ts +27 -20
  201. package/types/shell/index.d.ts +18 -2
  202. package/utils/__tests__/array.test.ts +13 -1
  203. package/utils/__tests__/string.test.ts +80 -1
  204. package/utils/array.ts +13 -0
  205. package/utils/auth.js +4 -0
  206. package/utils/cluster.js +1 -1
  207. package/{edit/monitoring.coreos.com.prometheusrule → utils}/duration.js +5 -3
  208. package/utils/pagination-utils.ts +15 -2
  209. package/utils/string.js +31 -7
  210. package/utils/validators/formRules/__tests__/index.test.ts +27 -0
  211. package/utils/validators/formRules/index.ts +16 -0
  212. package/edit/provisioning.cattle.io.cluster/import.vue +0 -198
@@ -262,6 +262,12 @@ export default {
262
262
  <template v-if="cluster.supportsWindows">
263
263
  <hr class="mt-20 mb-20">
264
264
  <h4 v-t="'cluster.custom.registrationCommand.windowsDetail'" />
265
+ <Banner
266
+ v-if="readyForWindows"
267
+ color="info"
268
+ label-key="cluster.custom.registrationCommand.windowsWorkersOnly"
269
+ data-testid="ready-for-windows"
270
+ />
265
271
  <Banner
266
272
  v-if="cluster.isRke1"
267
273
  color="warning"
@@ -288,7 +294,8 @@ export default {
288
294
  <Banner
289
295
  v-else
290
296
  color="info"
291
- :label="t('cluster.custom.registrationCommand.windowsNotReady')"
297
+ label-key="cluster.custom.registrationCommand.windowsNotReady"
298
+ data-testid="windows-not-ready"
292
299
  />
293
300
  </template>
294
301
  </InfoBox>
@@ -194,6 +194,8 @@ export default {
194
194
  } catch (e) {
195
195
  this.errors = [e];
196
196
  btnCb(false);
197
+
198
+ return;
197
199
  }
198
200
  }
199
201
 
@@ -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],
@@ -173,7 +173,16 @@ export default {
173
173
  },
174
174
 
175
175
  data() {
176
- const subType = this.$route.query[SUB_TYPE] || null;
176
+ let subType = null;
177
+
178
+ subType = this.$route.query[SUB_TYPE] || null;
179
+ if ( this.$route.query[SUB_TYPE]) {
180
+ subType = this.$route.query[SUB_TYPE];
181
+ } else if (this.value.isImported) {
182
+ subType = IMPORTED;
183
+ } else if (this.value.isLocal) {
184
+ subType = LOCAL;
185
+ }
177
186
  const rkeType = this.$route.query[RKE_TYPE] || null;
178
187
  const chart = this.$route.query[CHART] || null;
179
188
  const isImport = this.realMode === _IMPORT;
@@ -213,14 +222,6 @@ export default {
213
222
 
214
223
  emberLink() {
215
224
  if (this.value) {
216
- // for imported and local clusters, set subtype using properties from prov cluster model
217
- //
218
- if (this.value.isImported) {
219
- this.selectType(IMPORTED, false);
220
- } else if (this.value.isLocal) {
221
- this.selectType(LOCAL, false);
222
- }
223
-
224
225
  // set subtype if editing EKS/GKE/AKS cluster -- this ensures that the component provided by extension is loaded instead of iframing old ember ui
225
226
  if (this.value.provisioner) {
226
227
  const matchingSubtype = this.subTypes.find((st) => DRIVER_TO_IMPORT[st.id.toLowerCase()] === this.value.provisioner.toLowerCase());
@@ -239,6 +240,7 @@ export default {
239
240
 
240
241
  return '';
241
242
  }
243
+
242
244
  // For custom RKE2 clusters, don't load an Ember page.
243
245
  // It should be the dashboard.
244
246
  if ( this.value.isRke2 && ((this.value.isCustom && this.mode === _EDIT) || (this.value.isCustom && this.as === _CONFIG && this.mode === _VIEW) || (this.subType || '').toLowerCase() === 'custom')) {
@@ -343,10 +345,7 @@ export default {
343
345
  addType(this.$plugin, obj.driverName, 'kontainer', false, (isImport ? obj.emberImportPath : obj.emberCreatePath));
344
346
  }
345
347
  });
346
-
347
- if ( isImport ) {
348
- addType(this.$plugin, 'import', 'custom', false);
349
- } else {
348
+ if (!isImport) {
350
349
  templates.forEach((chart) => {
351
350
  out.push({
352
351
  id: `chart:${ chart.id }`,
@@ -383,23 +382,26 @@ export default {
383
382
 
384
383
  addType(this.$plugin, 'custom', 'custom2', false);
385
384
  }
386
-
387
- // Add from extensions
388
- this.extensions.forEach((ext) => {
385
+ }
386
+ // Add from extensions
387
+ this.extensions.forEach((ext) => {
389
388
  // if the rke toggle is set to rke1, don't add extensions that specify rke2 group
390
389
  // default group is rke2
391
- if (!this.isRke2 && (ext.group === _RKE2 || !ext.group)) {
392
- return;
393
- }
394
- // Do not show the extension provisioner on the import cluster page unless its explicitly set to do so
395
- if (isImport && !ext.showImport) {
396
- return;
397
- }
398
- // Allow extensions to overwrite provisioners with the same id
399
- out = out.filter((type) => type.id !== ext.id);
400
- addExtensionType(ext, getters);
401
- });
402
- }
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
+ });
403
405
 
404
406
  return out;
405
407
 
@@ -667,6 +669,11 @@ export default {
667
669
  </div>
668
670
  {{ obj.label }}
669
671
  </h4>
672
+ <Banner
673
+ v-if="provisioner === _RKE1 && i === 1"
674
+ color="warning"
675
+ label-key="cluster.banner.rke1DeprecationShortMessage"
676
+ />
670
677
  <SelectIconGrid
671
678
  :rows="obj.types"
672
679
  key-field="id"
@@ -679,14 +686,7 @@ export default {
679
686
  </div>
680
687
  </template>
681
688
 
682
- <Import
683
- v-if="isImport"
684
- v-model:value="localValue"
685
- :mode="mode"
686
- :provider="subType"
687
- @update:value="$emit('input', $event)"
688
- />
689
- <template v-else-if="subType">
689
+ <template v-if="subType">
690
690
  <!-- allow extensions to provide their own cluster provisioning form -->
691
691
  <component
692
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;
@@ -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
  />