@rancher/shell 3.0.0-rc.8 → 3.0.0

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 (84) hide show
  1. package/assets/translations/en-us.yaml +12 -11
  2. package/assets/translations/zh-hans.yaml +1 -4
  3. package/components/EmberPage.vue +0 -8
  4. package/components/ResourceTable.vue +26 -1
  5. package/components/SortableTable/actions.js +1 -1
  6. package/components/SortableTable/index.vue +17 -1
  7. package/components/SortableTable/selection.js +1 -1
  8. package/components/SortableTable/sorting.js +11 -3
  9. package/components/fleet/FleetClusters.vue +0 -3
  10. package/components/form/ColorInput.vue +13 -2
  11. package/components/form/HookOption.vue +31 -29
  12. package/components/form/LabeledSelect.vue +0 -1
  13. package/components/form/LifecycleHooks.vue +2 -2
  14. package/components/form/__tests__/ColorInput.test.ts +27 -0
  15. package/components/formatter/SecretData.vue +1 -1
  16. package/components/nav/Header.vue +10 -13
  17. package/components/nav/TopLevelMenu.vue +0 -40
  18. package/components/nav/WorkspaceSwitcher.vue +0 -1
  19. package/config/private-label.js +2 -1
  20. package/config/router/routes.js +2 -26
  21. package/config/settings.ts +5 -0
  22. package/config/version.js +2 -0
  23. package/detail/catalog.cattle.io.app.vue +17 -4
  24. package/detail/fleet.cattle.io.cluster.vue +11 -9
  25. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  26. package/edit/cis.cattle.io.clusterscan.vue +4 -3
  27. package/edit/cis.cattle.io.clusterscanbenchmark.vue +2 -0
  28. package/edit/constraints.gatekeeper.sh.constraint/index.vue +2 -0
  29. package/edit/fleet.cattle.io.cluster.vue +4 -0
  30. package/edit/fleet.cattle.io.gitrepo.vue +11 -8
  31. package/edit/helm.cattle.io.projecthelmchart.vue +2 -0
  32. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +2 -0
  33. package/edit/kontainerDriver.vue +2 -0
  34. package/edit/logging-flow/index.vue +2 -0
  35. package/edit/management.cattle.io.project.vue +2 -1
  36. package/edit/management.cattle.io.projectroletemplatebinding.vue +2 -1
  37. package/edit/management.cattle.io.user.vue +3 -0
  38. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +2 -0
  39. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -0
  40. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +5 -5
  41. package/edit/monitoring.coreos.com.prometheusrule/index.vue +3 -1
  42. package/edit/monitoring.coreos.com.receiver/index.vue +2 -0
  43. package/edit/monitoring.coreos.com.route.vue +2 -0
  44. package/edit/networking.istio.io.destinationrule/index.vue +2 -0
  45. package/edit/nodeDriver.vue +2 -0
  46. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +26 -0
  47. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +63 -149
  48. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +4 -1
  49. package/edit/provisioning.cattle.io.cluster/import.vue +2 -0
  50. package/edit/provisioning.cattle.io.cluster/rke2.vue +5 -3
  51. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +7 -2
  52. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +108 -35
  53. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +1 -1
  54. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +1 -1
  55. package/edit/ui.cattle.io.navlink.vue +4 -3
  56. package/edit/workload/mixins/workload.js +1 -1
  57. package/mixins/browser-tab-visibility.js +1 -1
  58. package/mixins/chart.js +6 -2
  59. package/mixins/metric-poller.js +1 -1
  60. package/mixins/resource-fetch.js +1 -1
  61. package/models/catalog.cattle.io.app.js +108 -21
  62. package/models/cloudcredential.js +4 -4
  63. package/models/fleet.cattle.io.gitrepo.js +8 -13
  64. package/models/management.cattle.io.cluster.js +13 -2
  65. package/models/management.cattle.io.project.js +4 -0
  66. package/models/provisioning.cattle.io.cluster.js +1 -2
  67. package/models/workload.js +1 -1
  68. package/package.json +11 -4
  69. package/pages/auth/logout.vue +7 -9
  70. package/pages/auth/setup.vue +3 -0
  71. package/pages/c/_cluster/apps/charts/install.vue +11 -3
  72. package/pages/c/_cluster/explorer/__tests__/index.test.ts +7 -4
  73. package/pages/c/_cluster/explorer/index.vue +45 -24
  74. package/pages/c/_cluster/fleet/index.vue +11 -5
  75. package/pages/c/_cluster/uiplugins/index.vue +4 -2
  76. package/pages/diagnostic.vue +1 -0
  77. package/plugins/steve/mutations.js +4 -1
  78. package/plugins/steve/subscribe.js +3 -4
  79. package/types/shell/index.d.ts +13 -0
  80. package/utils/__tests__/object.test.ts +152 -1
  81. package/utils/object.js +37 -0
  82. package/utils/string.js +9 -0
  83. package/utils/validators/formRules/index.ts +1 -1
  84. package/config/product/multi-cluster-apps.js +0 -61
@@ -1,7 +1,7 @@
1
1
  import { nextTick } from 'vue';
2
2
  /* eslint-disable jest/no-hooks */
3
3
  import { mount, Wrapper } from '@vue/test-utils';
4
- import DirectoryConfig from '@shell/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue';
4
+ import DirectoryConfig, { DATA_DIR_RADIO_OPTIONS, DEFAULT_SUBDIRS } from '@shell/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue';
5
5
  import { _EDIT, _CREATE } from '@shell/config/query-params';
6
6
  import { clone } from '@shell/utils/object';
7
7
 
@@ -15,7 +15,8 @@ describe('component: DirectoryConfig', () => {
15
15
  provisioning: '',
16
16
  k8sDistro: '',
17
17
  },
18
- mode: _CREATE,
18
+ k8sVersion: 'k3s',
19
+ mode: _CREATE,
19
20
  },
20
21
  mocks: {
21
22
  $store: {
@@ -34,203 +35,119 @@ describe('component: DirectoryConfig', () => {
34
35
  );
35
36
 
36
37
  const title = wrapper.find('h3');
37
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
38
+ const radioInput = wrapper.find('[data-testid="rke2-directory-config-radio-input"]');
38
39
  const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
39
40
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
40
41
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
41
42
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
42
43
 
43
44
  expect(title.exists()).toBe(true);
44
- expect(checkbox.exists()).toBe(true);
45
- // for the default config, checkbox should be checked
46
- expect(wrapper.vm.isSettingCommonConfig).toBe(true);
47
- expect(commonInput.exists()).toBe(true);
45
+ expect(radioInput.exists()).toBe(true);
46
+
47
+ // for the default config, the default radio input should be "default"
48
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.DEFAULT);
48
49
 
49
- // since we have all of the vars empty, then the individual inputs should not be there
50
+ // since we have all of the vars empty, then the inputs should not be there
51
+ expect(commonInput.exists()).toBe(false);
50
52
  expect(systemAgentInput.exists()).toBe(false);
51
53
  expect(provisioningInput.exists()).toBe(false);
52
54
  expect(k8sDistroInput.exists()).toBe(false);
53
55
  });
54
56
 
55
- it('should render the component with configuration being an empty object, without errors', () => {
57
+ it('updating common base directory should set the correct values on each data dir variable', async() => {
56
58
  const newMountOptions = clone(mountOptions);
57
59
 
58
- newMountOptions.propsData.value = {};
59
-
60
- wrapper = mount(
61
- DirectoryConfig,
62
- newMountOptions
63
- );
64
-
65
- const title = wrapper.find('h3');
66
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
67
- const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
68
- const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
69
- const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
70
- const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
71
-
72
- expect(title.exists()).toBe(true);
73
- expect(checkbox.exists()).toBe(true);
74
- // for the default config, checkbox should be checked
75
- expect(wrapper.vm.isSettingCommonConfig).toBe(true);
76
- expect(commonInput.exists()).toBe(true);
77
-
78
- // since we have all of the vars empty, then the individual inputs should not be there
79
- expect(systemAgentInput.exists()).toBe(false);
80
- expect(provisioningInput.exists()).toBe(false);
81
- expect(k8sDistroInput.exists()).toBe(false);
82
- });
83
-
84
- it('updating common config path should set the correct values on each data dir variable', async() => {
85
60
  wrapper = mount(
86
61
  DirectoryConfig,
87
- mountOptions
62
+ {
63
+ ...newMountOptions,
64
+ // couldn't use setData, so this is the next best solution
65
+ data() {
66
+ return { dataConfigRadioValue: DATA_DIR_RADIO_OPTIONS.COMMON };
67
+ }
68
+ }
88
69
  );
89
70
 
90
71
  const inputPath = 'some-data-dir';
91
72
  const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
92
73
 
74
+ // update base dir value
75
+ expect(commonInput.exists()).toBe(true);
93
76
  commonInput.setValue(inputPath);
94
77
  await nextTick();
95
78
 
96
- expect(wrapper.vm.value.systemAgent).toStrictEqual(inputPath);
97
- expect(wrapper.vm.value.provisioning).toStrictEqual(inputPath);
98
- expect(wrapper.vm.value.k8sDistro).toStrictEqual(inputPath);
79
+ expect(wrapper.vm.value.systemAgent).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`);
80
+ expect(wrapper.vm.value.provisioning).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`);
81
+ expect(wrapper.vm.value.k8sDistro).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_K3S }`);
99
82
  });
100
83
 
101
84
  it('updating each individual data dir should set the correct values on each data dir variable', async() => {
102
- wrapper = mount(
103
- DirectoryConfig,
104
- mountOptions
105
- );
106
-
107
- const inputPath = 'some-data-dir';
108
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
109
-
110
- await checkbox.find('label').trigger('click');
111
- await nextTick();
112
- await nextTick();
113
-
114
- expect(wrapper.vm.isSettingCommonConfig).toBe(false);
115
-
116
- const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
117
- const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
118
- const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
119
-
120
- systemAgentInput.setValue(inputPath);
121
- provisioningInput.setValue(inputPath);
122
- k8sDistroInput.setValue(inputPath);
123
- await nextTick();
124
-
125
- expect(wrapper.vm.value.systemAgent).toStrictEqual(inputPath);
126
- expect(wrapper.vm.value.provisioning).toStrictEqual(inputPath);
127
- expect(wrapper.vm.value.k8sDistro).toStrictEqual(inputPath);
128
- });
129
-
130
- it('checkbox should be checked if all data dir values are the same (with all data dir values filled)', () => {
131
85
  const newMountOptions = clone(mountOptions);
132
- const inputPath = 'some-data-dir';
133
-
134
- newMountOptions.propsData.value.systemAgent = inputPath;
135
- newMountOptions.propsData.value.provisioning = inputPath;
136
- newMountOptions.propsData.value.k8sDistro = inputPath;
137
86
 
138
87
  wrapper = mount(
139
88
  DirectoryConfig,
140
- newMountOptions
89
+ {
90
+ ...newMountOptions,
91
+ // couldn't use setData, so this is the next best solution
92
+ data() {
93
+ return { dataConfigRadioValue: DATA_DIR_RADIO_OPTIONS.CUSTOM };
94
+ }
95
+ }
141
96
  );
97
+ const inputPath = 'some-data-dir';
98
+ const agentValue = `${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`;
99
+ const provisioningValue = `${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`;
100
+ const k8sDistroValue = `${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_RKE2 }`;
142
101
 
143
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
144
-
145
- expect(checkbox.exists()).toBe(true);
146
- expect(wrapper.vm.isSettingCommonConfig).toBe(true);
147
-
148
- const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
149
102
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
150
103
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
151
104
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
152
105
 
153
- expect(commonInput.exists()).toBe(true);
154
- expect(systemAgentInput.exists()).toBe(false);
155
- expect(provisioningInput.exists()).toBe(false);
156
- expect(k8sDistroInput.exists()).toBe(false);
106
+ systemAgentInput.setValue(agentValue);
107
+ provisioningInput.setValue(provisioningValue);
108
+ k8sDistroInput.setValue(k8sDistroValue);
109
+ await nextTick();
157
110
 
158
- expect(wrapper.vm.value.systemAgent).toStrictEqual(inputPath);
159
- expect(wrapper.vm.value.provisioning).toStrictEqual(inputPath);
160
- expect(wrapper.vm.value.k8sDistro).toStrictEqual(inputPath);
111
+ expect(wrapper.vm.value.systemAgent).toStrictEqual(agentValue);
112
+ expect(wrapper.vm.value.provisioning).toStrictEqual(provisioningValue);
113
+ expect(wrapper.vm.value.k8sDistro).toStrictEqual(k8sDistroValue);
161
114
  });
162
115
 
163
- it('checkbox should NOT be checked if some data dir values are the different (with all data dir values filled)', () => {
116
+ it('should render the component with configuration being an empty object, without errors and radio be of value DATA_DIR_RADIO_OPTIONS.DEFAULT (edit scenario)', () => {
164
117
  const newMountOptions = clone(mountOptions);
165
- const inputPath1 = 'some-data-dir1';
166
- const inputPath2 = 'some-data-dir2';
167
- const inputPath3 = 'some-data-dir3';
168
118
 
169
- newMountOptions.propsData.value.systemAgent = inputPath1;
170
- newMountOptions.propsData.value.provisioning = inputPath2;
171
- newMountOptions.propsData.value.k8sDistro = inputPath3;
119
+ newMountOptions.propsData.value = {};
120
+ newMountOptions.propsData.mode = _EDIT;
172
121
 
173
122
  wrapper = mount(
174
123
  DirectoryConfig,
175
124
  newMountOptions
176
125
  );
177
126
 
178
- expect(wrapper.vm.isSettingCommonConfig).toBe(false);
179
-
180
- const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
127
+ const title = wrapper.find('h3');
128
+ const radioInput = wrapper.find('[data-testid="rke2-directory-config-radio-input"]');
181
129
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
182
130
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
183
131
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
184
132
 
185
- expect(commonInput.exists()).toBe(false);
186
- expect(systemAgentInput.exists()).toBe(true);
187
- expect(provisioningInput.exists()).toBe(true);
188
- expect(k8sDistroInput.exists()).toBe(true);
189
-
190
- expect(wrapper.vm.value.systemAgent).toStrictEqual(inputPath1);
191
- expect(wrapper.vm.value.provisioning).toStrictEqual(inputPath2);
192
- expect(wrapper.vm.value.k8sDistro).toStrictEqual(inputPath3);
193
- });
194
-
195
- it('on a mode different than _CREATE all visible inputs should be disabled (with common config)', () => {
196
- const newMountOptions = clone(mountOptions);
197
- const inputPath = 'some-data-dir';
198
-
199
- newMountOptions.propsData.value.systemAgent = inputPath;
200
- newMountOptions.propsData.value.provisioning = inputPath;
201
- newMountOptions.propsData.value.k8sDistro = inputPath;
202
- newMountOptions.propsData.mode = _EDIT;
203
-
204
- wrapper = mount(
205
- DirectoryConfig,
206
- newMountOptions
207
- );
133
+ expect(title.exists()).toBe(true);
134
+ expect(radioInput.exists()).toBe(true);
208
135
 
209
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
210
- const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
211
- const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
212
- const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
213
- const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
136
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.DEFAULT);
214
137
 
215
- expect(checkbox.exists()).toBe(true);
216
- expect(commonInput.exists()).toBe(true);
138
+ // since we have all of the vars empty, then the inputs should not be there
217
139
  expect(systemAgentInput.exists()).toBe(false);
218
140
  expect(provisioningInput.exists()).toBe(false);
219
141
  expect(k8sDistroInput.exists()).toBe(false);
220
-
221
- expect(checkbox.find('label').classes('disabled')).toBe(true);
222
- expect(commonInput.attributes('disabled')).toBe('');
223
142
  });
224
143
 
225
- it('on a mode different than _CREATE all visible inputs should be disabled (with different values)', () => {
144
+ it('radio input should be set to DATA_DIR_RADIO_OPTIONS.CUSTOM with all data dir values existing and different (edit scenario)', async() => {
226
145
  const newMountOptions = clone(mountOptions);
227
- const inputPath1 = 'some-data-dir1';
228
- const inputPath2 = 'some-data-dir2';
229
- const inputPath3 = 'some-data-dir3';
146
+ const inputPath = 'some-data-dir';
230
147
 
231
- newMountOptions.propsData.value.systemAgent = inputPath1;
232
- newMountOptions.propsData.value.provisioning = inputPath2;
233
- newMountOptions.propsData.value.k8sDistro = inputPath3;
148
+ newMountOptions.propsData.value.systemAgent = `${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`;
149
+ newMountOptions.propsData.value.provisioning = `${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`;
150
+ newMountOptions.propsData.value.k8sDistro = `${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_K3S }`;
234
151
  newMountOptions.propsData.mode = _EDIT;
235
152
 
236
153
  wrapper = mount(
@@ -238,21 +155,18 @@ describe('component: DirectoryConfig', () => {
238
155
  newMountOptions
239
156
  );
240
157
 
241
- const checkbox = wrapper.find('[data-testid="rke2-directory-config-individual-config-checkbox"]');
242
- const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
158
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.CUSTOM);
159
+
243
160
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
244
161
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
245
162
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
246
163
 
247
- expect(checkbox.exists()).toBe(true);
248
- expect(commonInput.exists()).toBe(false);
249
- expect(systemAgentInput.exists()).toBe(true);
250
- expect(provisioningInput.exists()).toBe(true);
251
- expect(k8sDistroInput.exists()).toBe(true);
164
+ expect(systemAgentInput.isVisible()).toBe(true);
165
+ expect(provisioningInput.isVisible()).toBe(true);
166
+ expect(k8sDistroInput.isVisible()).toBe(true);
252
167
 
253
- expect(checkbox.find('label').classes('disabled')).toBe(true);
254
- expect(systemAgentInput.attributes('disabled')).toBe('');
255
- expect(provisioningInput.attributes('disabled')).toBe('');
256
- expect(k8sDistroInput.attributes('disabled')).toBe('');
168
+ expect(wrapper.vm.value.systemAgent).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`);
169
+ expect(wrapper.vm.value.provisioning).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`);
170
+ expect(wrapper.vm.value.k8sDistro).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_K3S }`);
257
171
  });
258
172
  });
@@ -2,6 +2,7 @@ import { mount, shallowMount } from '@vue/test-utils';
2
2
  import { SECRET } from '@shell/config/types';
3
3
  import { _CREATE } from '@shell/config/query-params';
4
4
  import rke2 from '@shell/edit/provisioning.cattle.io.cluster/rke2.vue';
5
+ import { get } from '@shell/utils/object';
5
6
 
6
7
  /**
7
8
  * DISCLAIMER ***************************************************************************************
@@ -242,7 +243,9 @@ describe('component: rke2', () => {
242
243
 
243
244
  await wrapper.vm._doSaveOverride(jest.fn());
244
245
 
245
- expect(wrapper.vm.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`]).toStrictEqual('my-k8s-distro-path/etc/config-files/cloud-provider-config');
246
+ const cloudConfigPath = get(wrapper.vm.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`);
247
+
248
+ expect(cloudConfigPath).toStrictEqual('my-k8s-distro-path/etc/config-files/cloud-provider-config');
246
249
  });
247
250
 
248
251
  // TODO: Complete test after implementing fetch https://github.com/rancher/dashboard/issues/9322
@@ -36,6 +36,8 @@ export default {
36
36
 
37
37
  mixins: [CreateEditView],
38
38
 
39
+ inheritAttrs: false,
40
+
39
41
  props: {
40
42
  mode: {
41
43
  type: String,
@@ -62,6 +62,7 @@ import Upgrade from '@shell/edit/provisioning.cattle.io.cluster/tabs/upgrade';
62
62
  import Registries from '@shell/edit/provisioning.cattle.io.cluster/tabs/registries';
63
63
  import AddOnConfig from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig';
64
64
  import Advanced from '@shell/edit/provisioning.cattle.io.cluster/tabs/Advanced';
65
+ import { DEFAULT_COMMON_BASE_PATH, DEFAULT_SUBDIRS } from '@shell/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig';
65
66
  import ClusterAppearance from '@shell/components/form/ClusterAppearance';
66
67
  import AddOnAdditionalManifest from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest';
67
68
  import VsphereUtils from '@shell/utils/v-sphere';
@@ -1480,12 +1481,13 @@ export default {
1480
1481
  this.agentConfig['cloud-provider-config'] = `secret://fleet-default:${ harvesterKubeconfigSecret?.metadata?.name }`;
1481
1482
 
1482
1483
  if (this.isCreate) {
1483
- this.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.global.cattle.clusterName`] = this.value.metadata.name;
1484
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.global.cattle.clusterName`, this.value.metadata.name);
1484
1485
  }
1485
1486
 
1486
- const distroRoot = this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro?.length ? this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro : '/var/lib/rancher/rke2';
1487
+ const distroSubdir = this.value?.spec?.kubernetesVersion?.includes('k3s') ? DEFAULT_SUBDIRS.K8S_DISTRO_K3S : DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
1488
+ const distroRoot = this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro?.length ? this.value?.spec?.rkeConfig?.dataDirectories?.k8sDistro : `${ DEFAULT_COMMON_BASE_PATH }/${ distroSubdir }`;
1487
1489
 
1488
- this.chartValues[`${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`] = `${ distroRoot }/etc/config-files/cloud-provider-config`;
1490
+ set(this.chartValues, `${ HARVESTER_CLOUD_PROVIDER }.cloudConfigPath`, `${ distroRoot }/etc/config-files/cloud-provider-config`);
1489
1491
  }
1490
1492
  } catch (err) {
1491
1493
  this.errors.push(err);
@@ -80,10 +80,14 @@ export default {
80
80
  return i !== 0 || !this.agentConfig;
81
81
  },
82
82
  showEmptyKubeletArg(config) {
83
- return !this.serverArg?.['kubelet-arg']?.length && !config?.['kubelet-arg']?.length;
83
+ return !this.serverArgs?.['kubelet-arg']?.length && !config?.['kubelet-arg']?.length;
84
84
  },
85
85
  onInputProtectKernelDefaults(value) {
86
- this.agentConfig ? this.agentConfig = value : this.serverConfig['protect-kernel-defaults'] = value;
86
+ if (this.agentConfig && this.agentConfig['protect-kernel-defaults'] !== undefined ) {
87
+ this.agentConfig['protect-kernel-defaults'] = value;
88
+ } else {
89
+ this.serverConfig['protect-kernel-defaults'] = value;
90
+ }
87
91
  }
88
92
  }
89
93
  };
@@ -100,6 +104,7 @@ export default {
100
104
  <template v-if="haveArgInfo">
101
105
  <DirectoryConfig
102
106
  v-model:value="value.spec.rkeConfig.dataDirectories"
107
+ :k8s-version="value.spec.kubernetesVersion"
103
108
  :mode="mode"
104
109
  />
105
110
  <h3>{{ t('cluster.advanced.argInfo.title') }}</h3>
@@ -1,14 +1,29 @@
1
1
 
2
2
  <script>
3
- import { Checkbox } from '@components/Form/Checkbox';
4
3
  import { LabeledInput } from '@components/Form/LabeledInput';
5
4
  import { _CREATE } from '@shell/config/query-params';
5
+ import RadioGroup from '@components/Form/Radio/RadioGroup.vue';
6
+
7
+ export const DATA_DIR_RADIO_OPTIONS = {
8
+ DEFAULT: 'defaultDataDir',
9
+ COMMON: 'commonBaseDataDir',
10
+ CUSTOM: 'customDataDir',
11
+ };
12
+
13
+ export const DEFAULT_COMMON_BASE_PATH = '/var/lib/rancher';
14
+
15
+ export const DEFAULT_SUBDIRS = {
16
+ AGENT: 'agent',
17
+ PROVISIONING: 'provisioning',
18
+ K8S_DISTRO_RKE2: 'rke2',
19
+ K8S_DISTRO_K3S: 'k3s',
20
+ };
6
21
 
7
22
  export default {
8
23
  name: 'DirectoryConfig',
9
24
  components: {
10
- Checkbox,
11
25
  LabeledInput,
26
+ RadioGroup
12
27
  },
13
28
  props: {
14
29
  mode: {
@@ -16,52 +31,114 @@ export default {
16
31
  required: true,
17
32
  },
18
33
 
34
+ k8sVersion: {
35
+ type: String,
36
+ required: true,
37
+ },
38
+
19
39
  value: {
20
40
  type: Object,
21
41
  required: true,
22
42
  },
23
43
  },
24
44
  data() {
25
- let atLeastOneDirWithAnIdentifier = false;
26
- let allDirsWithSameIdentifier = false;
27
-
28
- if (this.value?.systemAgent?.length || this.value?.provisioning?.length || this.value?.k8sDistro?.length) {
29
- atLeastOneDirWithAnIdentifier = true;
30
- if (this.value?.systemAgent === this.value?.provisioning && this.value?.provisioning === this.value?.k8sDistro &&
31
- this.value?.systemAgent === this.value?.k8sDistro) {
32
- allDirsWithSameIdentifier = true;
45
+ let dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
46
+ let k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
47
+
48
+ if (this.k8sVersion && this.k8sVersion.includes('k3s')) {
49
+ k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_K3S;
50
+ }
51
+
52
+ if (this.mode !== _CREATE) {
53
+ if (this.value?.systemAgent?.length || this.value?.provisioning?.length || this.value?.k8sDistro?.length) {
54
+ dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
33
55
  }
34
56
  }
35
57
 
36
58
  return {
37
- isSettingCommonConfig: !(atLeastOneDirWithAnIdentifier && !allDirsWithSameIdentifier),
38
- commonConfig: allDirsWithSameIdentifier ? this.value?.systemAgent : '',
59
+ DATA_DIR_RADIO_OPTIONS,
60
+ dataConfigRadioValue,
61
+ k8sDistroSubDir,
62
+ commonConfig: '',
39
63
  };
40
64
  },
41
65
  watch: {
42
66
  commonConfig(neu) {
43
- if (neu && neu.length && this.isSettingCommonConfig) {
44
- this.value.systemAgent = neu;
45
- this.value.provisioning = neu;
46
- this.value.k8sDistro = neu;
67
+ if (neu && neu.length && this.dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.COMMON) {
68
+ this.value.systemAgent = `${ neu }/${ DEFAULT_SUBDIRS.AGENT }`;
69
+ this.value.provisioning = `${ neu }/${ DEFAULT_SUBDIRS.PROVISIONING }`;
70
+ this.value.k8sDistro = `${ neu }/${ this.k8sDistroSubDir }`;
71
+ }
72
+ },
73
+ k8sVersion: {
74
+ handler(neu) {
75
+ if (neu && neu.includes('k3s')) {
76
+ this.k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_K3S;
77
+ } else {
78
+ this.k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
79
+ }
80
+
81
+ if (this.value.k8sDistro) {
82
+ this.value.k8sDistro = `${ neu }/${ this.k8sDistroSubDir }`;
83
+ }
47
84
  }
48
85
  }
49
86
  },
50
87
  computed: {
51
- disableEditInput() {
52
- return this.mode !== _CREATE;
88
+ dataConfigRadioOptions() {
89
+ const defaultDataDirOption = {
90
+ value: DATA_DIR_RADIO_OPTIONS.DEFAULT,
91
+ label: this.t('cluster.directoryConfig.radioInput.defaultLabel')
92
+ };
93
+ const customDataDirOption = {
94
+ value: DATA_DIR_RADIO_OPTIONS.CUSTOM,
95
+ label: this.t('cluster.directoryConfig.radioInput.customLabel')
96
+ };
97
+
98
+ if (this.mode === _CREATE) {
99
+ return [
100
+ defaultDataDirOption,
101
+ { value: DATA_DIR_RADIO_OPTIONS.COMMON, label: this.t('cluster.directoryConfig.radioInput.commonLabel') },
102
+ customDataDirOption
103
+ ];
104
+ } else {
105
+ return [
106
+ defaultDataDirOption,
107
+ customDataDirOption
108
+ ];
109
+ }
53
110
  }
54
111
  },
55
112
  methods: {
56
- handleCommonConfig(val) {
57
- this.isSettingCommonConfig = val;
113
+ handleRadioInput(val) {
114
+ switch (val) {
115
+ case DATA_DIR_RADIO_OPTIONS.DEFAULT:
116
+ if (this.mode === _CREATE) {
117
+ this.commonConfig = '';
118
+ }
119
+ this.value.systemAgent = '';
120
+ this.value.provisioning = '';
121
+ this.value.k8sDistro = '';
122
+
123
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
124
+ break;
125
+ case DATA_DIR_RADIO_OPTIONS.COMMON:
126
+ this.commonConfig = DEFAULT_COMMON_BASE_PATH;
127
+
128
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.COMMON;
129
+ break;
130
+ // default is custom config
131
+ default:
132
+ if (this.mode === _CREATE) {
133
+ this.commonConfig = '';
134
+ }
58
135
 
59
- if (val) {
60
136
  this.value.systemAgent = '';
61
137
  this.value.provisioning = '';
62
138
  this.value.k8sDistro = '';
63
- } else {
64
- this.commonConfig = '';
139
+
140
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
141
+ break;
65
142
  }
66
143
  }
67
144
  },
@@ -74,33 +151,31 @@ export default {
74
151
  <h3 class="mb-20">
75
152
  {{ t('cluster.directoryConfig.title') }}
76
153
  </h3>
77
- <Checkbox
154
+ <RadioGroup
155
+ :value="dataConfigRadioValue"
78
156
  class="mb-10"
79
- :value="isSettingCommonConfig"
80
157
  :mode="mode"
81
- :label="t('cluster.directoryConfig.checkboxText')"
82
- :disabled="disableEditInput"
83
- data-testid="rke2-directory-config-individual-config-checkbox"
84
- @update:value="handleCommonConfig"
158
+ :options="dataConfigRadioOptions"
159
+ name="directory-config-radio"
160
+ data-testid="rke2-directory-config-radio-input"
161
+ @update:value="handleRadioInput"
85
162
  />
86
163
  <LabeledInput
87
- v-if="isSettingCommonConfig"
164
+ v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.COMMON"
88
165
  v-model:value="commonConfig"
89
166
  class="mb-20"
90
167
  :mode="mode"
91
168
  :label="t('cluster.directoryConfig.common.label')"
92
169
  :tooltip="t('cluster.directoryConfig.common.tooltip')"
93
- :disabled="disableEditInput"
94
170
  data-testid="rke2-directory-config-common-data-dir"
95
171
  />
96
- <div v-if="!isSettingCommonConfig">
172
+ <div v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.CUSTOM">
97
173
  <LabeledInput
98
174
  v-model:value="value.systemAgent"
99
175
  class="mb-20"
100
176
  :mode="mode"
101
177
  :label="t('cluster.directoryConfig.systemAgent.label')"
102
178
  :tooltip="t('cluster.directoryConfig.systemAgent.tooltip')"
103
- :disabled="disableEditInput"
104
179
  data-testid="rke2-directory-config-systemAgent-data-dir"
105
180
  />
106
181
  <LabeledInput
@@ -109,7 +184,6 @@ export default {
109
184
  :mode="mode"
110
185
  :label="t('cluster.directoryConfig.provisioning.label')"
111
186
  :tooltip="t('cluster.directoryConfig.provisioning.tooltip')"
112
- :disabled="disableEditInput"
113
187
  data-testid="rke2-directory-config-provisioning-data-dir"
114
188
  />
115
189
  <LabeledInput
@@ -118,7 +192,6 @@ export default {
118
192
  :mode="mode"
119
193
  :label="t('cluster.directoryConfig.k8sDistro.label')"
120
194
  :tooltip="t('cluster.directoryConfig.k8sDistro.tooltip')"
121
- :disabled="disableEditInput"
122
195
  data-testid="rke2-directory-config-k8sDistro-data-dir"
123
196
  />
124
197
  </div>
@@ -317,7 +317,7 @@ export default {
317
317
  />
318
318
  </h3>
319
319
  <UnitInput
320
- v-model.number="unhealthyNodeTimeoutInteger"
320
+ v-model:value="unhealthyNodeTimeoutInteger"
321
321
  :hide-arrows="true"
322
322
  :placeholder="t('containerResourceLimit.cpuPlaceholder')"
323
323
  :mode="mode"
@@ -154,7 +154,6 @@ export default {
154
154
  :mode="mode"
155
155
  :data-testid="`registry-auth-host-input-${i}`"
156
156
  />
157
-
158
157
  <SelectOrCreateAuthSecret
159
158
  v-model:value="row.value.authConfigSecretName"
160
159
  :register-before-hook="wrapRegisterBeforeHook"
@@ -168,6 +167,7 @@ export default {
168
167
  generate-name="registryconfig-auth-"
169
168
  :data-testid="`registry-auth-select-or-create-${i}`"
170
169
  :cache-secrets="true"
170
+ @update:value="update"
171
171
  />
172
172
  </div>
173
173
  <div class="col span-6">
@@ -20,9 +20,10 @@ const LINK_TARGET_BLANK = '_blank';
20
20
  const LINK_TARGET_SELF = '_self';
21
21
 
22
22
  export default {
23
- emits: ['update:value.spec.iconSrc ', 'input'],
24
- mixins: [CreateEditView, FormValidation],
25
- components: {
23
+ emits: ['update:value.spec.iconSrc ', 'input'],
24
+ mixins: [CreateEditView, FormValidation],
25
+ inheritAttrs: false,
26
+ components: {
26
27
  CruResource,
27
28
  LabeledInput,
28
29
  RadioGroup,