@rancher/shell 2.0.2 → 2.0.3

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 (36) hide show
  1. package/assets/translations/en-us.yaml +9 -1
  2. package/components/ResourceDetail/index.vue +2 -1
  3. package/components/SideNav.vue +1 -1
  4. package/components/TableDataUserIcon.vue +1 -1
  5. package/components/fleet/FleetRepos.vue +0 -7
  6. package/components/formatter/ClusterProvider.vue +3 -3
  7. package/components/nav/TopLevelMenu.vue +12 -12
  8. package/config/labels-annotations.js +1 -0
  9. package/core/types-provisioning.ts +5 -0
  10. package/core/types.ts +26 -1
  11. package/detail/fleet.cattle.io.bundle.vue +5 -68
  12. package/detail/fleet.cattle.io.gitrepo.vue +2 -1
  13. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +109 -24
  14. package/edit/provisioning.cattle.io.cluster/index.vue +10 -4
  15. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -3
  16. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +1 -0
  17. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +177 -26
  18. package/models/__tests__/management.cattle.io.cluster.test.ts +3 -3
  19. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -86
  20. package/models/fleet.cattle.io.bundle.js +3 -1
  21. package/models/fleet.cattle.io.gitrepo.js +46 -48
  22. package/models/management.cattle.io.cluster.js +2 -5
  23. package/models/provisioning.cattle.io.cluster.js +25 -12
  24. package/package.json +1 -1
  25. package/pages/c/_cluster/fleet/index.vue +1 -0
  26. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +0 -2
  27. package/scripts/extension/parse-tag-name +21 -12
  28. package/scripts/publish-shell.sh +7 -0
  29. package/scripts/typegen.sh +3 -1
  30. package/store/features.js +1 -0
  31. package/types/resources/fleet.d.ts +40 -0
  32. package/types/shell/index.d.ts +97 -0
  33. package/utils/auth.js +1 -1
  34. package/utils/fleet.ts +159 -0
  35. package/utils/v-sphere.ts +31 -0
  36. package/vue.config.js +3 -3
@@ -1467,6 +1467,14 @@ cluster:
1467
1467
  placeholder: A unique name for the cluster
1468
1468
  directoryConfig:
1469
1469
  title: Data directory configuration
1470
+ banner: Data directory configuration can not be changed once the cluster has been created
1471
+ radioInput:
1472
+ defaultLabel: Use default data directory configuration
1473
+ commonLabel: Use a common base directory for data directory configuration (sub-directories will be used for the system-agent, provisioning and distro paths)
1474
+ customLabel: Use custom data directories
1475
+ common:
1476
+ label: Data directory base path
1477
+ tooltip: Data directory base path. We will append the sub-directories appropriate for each directory (/agent, /provisioning and either /rke2 or /k3s)
1470
1478
  systemAgent:
1471
1479
  label: System-agent directory path
1472
1480
  tooltip: Data directory for the system-agent connection info and plans
@@ -1954,7 +1962,7 @@ cluster:
1954
1962
  pinganyunecs: Pinganyun ECS
1955
1963
  pnap: phoenixNAP
1956
1964
  rackspace: RackSpace
1957
- rancherkubernetesengine: RKE
1965
+ rancherkubernetesengine: RKE1
1958
1966
  rke2: RKE2
1959
1967
  rke: RKE1
1960
1968
  rkeWindows: Windows (RKE1 only)
@@ -171,7 +171,8 @@ export default {
171
171
  },
172
172
  bundle: {
173
173
  inStoreType: 'management',
174
- type: FLEET.BUNDLE
174
+ type: FLEET.BUNDLE,
175
+ opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] },
175
176
  },
176
177
 
177
178
  bundleDeployment: {
@@ -480,7 +480,7 @@ export default {
480
480
  <template v-else>
481
481
  <span
482
482
  v-if="isVirtualCluster && isExplorer"
483
- v-tooltip="{content: harvesterVersion, placement: 'top'}"
483
+ v-clean-tooltip="{content: harvesterVersion, placement: 'top'}"
484
484
  class="clip text-muted ml-5"
485
485
  >
486
486
  (Harvester-{{ harvesterVersion }})
@@ -24,7 +24,7 @@ const iconClass = computed(() => {
24
24
  <template>
25
25
  <div class="icon-center">
26
26
  <i
27
- v-tooltip="ucFirst(userState)"
27
+ v-clean-tooltip="ucFirst(userState)"
28
28
  :class="iconClass"
29
29
  />
30
30
  </div>
@@ -16,7 +16,6 @@ import {
16
16
  FLEET_REPO_PER_CLUSTER_STATE
17
17
 
18
18
  } from '@shell/config/table-headers';
19
- import { FLEET } from '@shell/config/labels-annotations';
20
19
  import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
21
20
 
22
21
  // i18n-ignore repoDisplay
@@ -118,12 +117,6 @@ export default {
118
117
  parseTargetMode(row) {
119
118
  return row.targetInfo?.mode === 'clusterGroup' ? this.t('fleet.gitRepo.warningTooltip.clusterGroup') : this.t('fleet.gitRepo.warningTooltip.cluster');
120
119
  },
121
-
122
- clusterViewResourceStatus(row) {
123
- return row.clusterResourceStatus.find((c) => {
124
- return c.metadata?.labels[FLEET.CLUSTER_NAME] === this.clusterId;
125
- });
126
- }
127
120
  },
128
121
  };
129
122
  </script>
@@ -25,12 +25,12 @@ export default {
25
25
  {{ row.machineProviderDisplay }}
26
26
  </span>
27
27
  </template>
28
- <template v-else-if="row.isCustom">
29
- {{ t('cluster.provider.custom') }}
30
- </template>
31
28
  <template v-else-if="row.isImported">
32
29
  {{ t('cluster.provider.imported') }}
33
30
  </template>
31
+ <template v-else-if="row.isCustom">
32
+ {{ t('cluster.provider.custom') }}
33
+ </template>
34
34
  <div class="text-muted">
35
35
  {{ row.provisionerDisplay }}
36
36
  </div>
@@ -558,7 +558,7 @@ export default {
558
558
  :to="{ name: 'home' }"
559
559
  >
560
560
  <svg
561
- v-tooltip="getTooltipConfig(t('nav.home'))"
561
+ v-clean-tooltip="getTooltipConfig(t('nav.home'))"
562
562
  xmlns="http://www.w3.org/2000/svg"
563
563
  height="24"
564
564
  viewBox="0 0 24 24"
@@ -672,13 +672,13 @@ export default {
672
672
  @shortkey="handleKeyComboClick"
673
673
  >
674
674
  <ClusterIconMenu
675
- v-tooltip="getTooltipConfig(c, true)"
675
+ v-clean-tooltip="getTooltipConfig(c, true)"
676
676
  :cluster="c"
677
677
  :route-combo="routeCombo"
678
678
  class="rancher-provider-icon"
679
679
  />
680
680
  <div
681
- v-tooltip="getTooltipConfig(c)"
681
+ v-clean-tooltip="getTooltipConfig(c)"
682
682
  class="cluster-name"
683
683
  >
684
684
  <p>{{ c.label }}</p>
@@ -699,12 +699,12 @@ export default {
699
699
  :data-testid="`pinned-menu-cluster-disabled-${ c.id }`"
700
700
  >
701
701
  <ClusterIconMenu
702
- v-tooltip="getTooltipConfig(c, true)"
702
+ v-clean-tooltip="getTooltipConfig(c, true)"
703
703
  :cluster="c"
704
704
  class="rancher-provider-icon"
705
705
  />
706
706
  <div
707
- v-tooltip="getTooltipConfig(c)"
707
+ v-clean-tooltip="getTooltipConfig(c)"
708
708
  class="cluster-name"
709
709
  >
710
710
  <p>{{ c.label }}</p>
@@ -747,13 +747,13 @@ export default {
747
747
  @shortkey="handleKeyComboClick"
748
748
  >
749
749
  <ClusterIconMenu
750
- v-tooltip="getTooltipConfig(c, true)"
750
+ v-clean-tooltip="getTooltipConfig(c, true)"
751
751
  :cluster="c"
752
752
  :route-combo="routeCombo"
753
753
  class="rancher-provider-icon"
754
754
  />
755
755
  <div
756
- v-tooltip="getTooltipConfig(c)"
756
+ v-clean-tooltip="getTooltipConfig(c)"
757
757
  class="cluster-name"
758
758
  >
759
759
  <p>{{ c.label }}</p>
@@ -775,12 +775,12 @@ export default {
775
775
  :data-testid="`menu-cluster-disabled-${ c.id }`"
776
776
  >
777
777
  <ClusterIconMenu
778
- v-tooltip="getTooltipConfig(c, true)"
778
+ v-clean-tooltip="getTooltipConfig(c, true)"
779
779
  :cluster="c"
780
780
  class="rancher-provider-icon"
781
781
  />
782
782
  <div
783
- v-tooltip="getTooltipConfig(c)"
783
+ v-clean-tooltip="getTooltipConfig(c)"
784
784
  class="cluster-name"
785
785
  >
786
786
  <p>{{ c.label }}</p>
@@ -847,7 +847,7 @@ export default {
847
847
  :to="a.to"
848
848
  >
849
849
  <IconOrSvg
850
- v-tooltip="getTooltipConfig(a.label)"
850
+ v-clean-tooltip="getTooltipConfig(a.label)"
851
851
  :icon="a.icon"
852
852
  :src="a.svg"
853
853
  />
@@ -875,7 +875,7 @@ export default {
875
875
  :to="a.to"
876
876
  >
877
877
  <IconOrSvg
878
- v-tooltip="getTooltipConfig(a.label)"
878
+ v-clean-tooltip="getTooltipConfig(a.label)"
879
879
  :icon="a.icon"
880
880
  :src="a.svg"
881
881
  />
@@ -905,7 +905,7 @@ export default {
905
905
  :to="a.to"
906
906
  >
907
907
  <IconOrSvg
908
- v-tooltip="getTooltipConfig(a.label)"
908
+ v-clean-tooltip="getTooltipConfig(a.label)"
909
909
  :icon="a.icon"
910
910
  :src="a.svg"
911
911
  />
@@ -111,6 +111,7 @@ export const FLEET = {
111
111
  CLUSTER_NAME: 'management.cattle.io/cluster-name',
112
112
  BUNDLE_ID: 'fleet.cattle.io/bundle-id',
113
113
  MANAGED: 'fleet.cattle.io/managed',
114
+ CLUSTER_NAMESPACE: 'fleet.cattle.io/cluster-namespace',
114
115
  CLUSTER: 'fleet.cattle.io/cluster'
115
116
  };
116
117
 
@@ -106,6 +106,11 @@ export interface IClusterProvisioner {
106
106
  */
107
107
  disabled?: boolean;
108
108
 
109
+ /**
110
+ * Hide the cluster provider card
111
+ */
112
+ hidden?: boolean;
113
+
109
114
  /**
110
115
  * Custom Dashboard route to navigate to when the cluster provider card is clicked
111
116
  */
package/core/types.ts CHANGED
@@ -237,6 +237,16 @@ export interface ProductOptions {
237
237
  */
238
238
  to?: Location;
239
239
 
240
+ /**
241
+ * Alternative to the icon property. Uses require
242
+ */
243
+ svg?: Function;
244
+
245
+ /**
246
+ * Product name
247
+ */
248
+ name?: string;
249
+
240
250
  /**
241
251
  * Leaving these here for completeness but I don't think these should be advertised as useable to plugin creators.
242
252
  */
@@ -373,10 +383,25 @@ export interface ConfigureTypeOptions {
373
383
  }
374
384
 
375
385
  export interface ConfigureVirtualTypeOptions extends ConfigureTypeOptions {
386
+ /**
387
+ * Only load the product if the type is present
388
+ */
389
+ ifHave?: string;
390
+
391
+ /**
392
+ * Only load the product if the type is present
393
+ */
394
+ ifHaveType?: string | RegExp | Object;
395
+
396
+ /**
397
+ * The label that this type should display
398
+ */
399
+ label?: string;
400
+
376
401
  /**
377
402
  * The translation key displayed anywhere this type is referenced
378
403
  */
379
- labelKey: string;
404
+ labelKey?: string;
380
405
 
381
406
  /**
382
407
  * An identifier that should be unique across all types
@@ -1,77 +1,25 @@
1
1
  <script>
2
- import { FLEET } from '@shell/config/types';
3
2
  import FleetBundleResources from '@shell/components/fleet/FleetBundleResources.vue';
4
- import SortableTable from '@shell/components/SortableTable';
3
+ import FleetUtils from '@shell/utils/fleet';
5
4
 
6
5
  export default {
7
6
  name: 'FleetBundleDetail',
8
7
 
9
- components: {
10
- FleetBundleResources,
11
- SortableTable,
12
- },
13
- props: {
8
+ components: { FleetBundleResources },
9
+ props: {
14
10
  value: {
15
11
  type: Object,
16
12
  required: true,
17
13
  }
18
14
  },
19
15
 
20
- data() {
21
- return { repo: null };
22
- },
23
-
24
- async fetch() {
25
- const { namespace, labels } = this.value.metadata;
26
- const repoName = `${ namespace }/${ labels['fleet.cattle.io/repo-name'] }`;
27
-
28
- if (this.hasRepoLabel) {
29
- this.repo = await this.$store.dispatch('management/find', { type: FLEET.GIT_REPO, id: repoName });
30
- }
31
- },
32
-
33
16
  computed: {
34
- hasRepoLabel() {
35
- return !!(this.value?.metadata?.labels && this.value?.metadata?.labels['fleet.cattle.io/repo-name']);
36
- },
37
17
  bundleResources() {
38
- if (this.hasRepoLabel) {
39
- const bundleResourceIds = this.bundleResourceIds;
40
-
41
- return this.repo?.status?.resources?.filter((resource) => {
42
- return bundleResourceIds.includes(resource.name);
43
- });
44
- } else if (this.value?.spec?.resources?.length) {
45
- return this.value?.spec?.resources.map((item) => {
46
- return {
47
- content: item.content,
48
- name: item.name.includes('.') ? item.name.split('.')[0] : item.name
49
- };
50
- });
51
- }
52
-
53
- return [];
54
- },
55
- resourceHeaders() {
56
- return [
57
- {
58
- name: 'name',
59
- value: 'name',
60
- sort: ['name'],
61
- labelKey: 'tableHeaders.name',
62
- },
63
- ];
18
+ return FleetUtils.resourcesFromBundleStatus(this.value?.status);
64
19
  },
65
20
  resourceCount() {
66
- return (this.bundleResources && this.bundleResources.length) || this.value?.spec?.resources?.length;
21
+ return this.bundleResources.length;
67
22
  },
68
- bundleResourceIds() {
69
- if (this.value.status?.resourceKey) {
70
- return this.value?.status?.resourceKey.map((item) => item.name);
71
- }
72
-
73
- return [];
74
- }
75
23
  }
76
24
  };
77
25
 
@@ -84,19 +32,8 @@ export default {
84
32
  <span>{{ resourceCount }}</span>
85
33
  </div>
86
34
  <FleetBundleResources
87
- v-if="hasRepoLabel"
88
35
  :value="bundleResources"
89
36
  />
90
- <SortableTable
91
- v-else
92
- :rows="bundleResources"
93
- :headers="resourceHeaders"
94
- :table-actions="false"
95
- :row-actions="false"
96
- key-field="tableKey"
97
- default-sort-by="state"
98
- :paged="true"
99
- />
100
37
  </div>
101
38
  </template>
102
39
 
@@ -80,7 +80,8 @@ export default {
80
80
  const allDispatches = await checkSchemasForFindAllHash({
81
81
  allBundles: {
82
82
  inStoreType: 'management',
83
- type: FLEET.BUNDLE
83
+ type: FLEET.BUNDLE,
84
+ opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] },
84
85
  },
85
86
 
86
87
  allBundleDeployments: {
@@ -1,6 +1,7 @@
1
+ import { nextTick } from 'vue';
1
2
  /* eslint-disable jest/no-hooks */
2
3
  import { mount, Wrapper } from '@vue/test-utils';
3
- 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';
4
5
  import { _EDIT, _CREATE } from '@shell/config/query-params';
5
6
  import { clone } from '@shell/utils/object';
6
7
 
@@ -14,7 +15,8 @@ describe('component: DirectoryConfig', () => {
14
15
  provisioning: '',
15
16
  k8sDistro: '',
16
17
  },
17
- mode: _CREATE,
18
+ k8sVersion: 'k3s',
19
+ mode: _CREATE,
18
20
  },
19
21
  mocks: {
20
22
  $store: {
@@ -33,48 +35,88 @@ describe('component: DirectoryConfig', () => {
33
35
  );
34
36
 
35
37
  const title = wrapper.find('h3');
38
+ const radioInput = wrapper.find('[data-testid="rke2-directory-config-radio-input"]');
39
+ const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
36
40
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
37
41
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
38
42
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
39
43
 
40
44
  expect(title.exists()).toBe(true);
45
+ expect(radioInput.exists()).toBe(true);
41
46
 
42
- expect(systemAgentInput.exists()).toBe(true);
43
- expect(provisioningInput.exists()).toBe(true);
44
- expect(k8sDistroInput.exists()).toBe(true);
47
+ // for the default config, the default radio input should be "default"
48
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.DEFAULT);
49
+
50
+ // since we have all of the vars empty, then the inputs should not be there
51
+ expect(commonInput.exists()).toBe(false);
52
+ expect(systemAgentInput.exists()).toBe(false);
53
+ expect(provisioningInput.exists()).toBe(false);
54
+ expect(k8sDistroInput.exists()).toBe(false);
45
55
  });
46
56
 
47
- it('updating each individual data dir should set the correct values on each data dir variable', async() => {
57
+ it('updating common base directory should set the correct values on each data dir variable', async() => {
58
+ const newMountOptions = clone(mountOptions);
59
+
48
60
  wrapper = mount(
49
61
  DirectoryConfig,
50
- 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
+ }
51
69
  );
52
70
 
53
71
  const inputPath = 'some-data-dir';
72
+ const commonInput = wrapper.find('[data-testid="rke2-directory-config-common-data-dir"]');
73
+
74
+ // update base dir value
75
+ expect(commonInput.exists()).toBe(true);
76
+ commonInput.setValue(inputPath);
77
+ await nextTick();
78
+
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 }`);
82
+ });
83
+
84
+ it('updating each individual data dir should set the correct values on each data dir variable', async() => {
85
+ const newMountOptions = clone(mountOptions);
86
+
87
+ wrapper = mount(
88
+ DirectoryConfig,
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
+ }
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 }`;
54
101
 
55
102
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
56
103
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
57
104
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
58
105
 
59
- systemAgentInput.setValue(inputPath);
60
- provisioningInput.setValue(inputPath);
61
- k8sDistroInput.setValue(inputPath);
62
- await wrapper.vm.$nextTick();
106
+ systemAgentInput.setValue(agentValue);
107
+ provisioningInput.setValue(provisioningValue);
108
+ k8sDistroInput.setValue(k8sDistroValue);
109
+ await nextTick();
63
110
 
64
- expect(wrapper.vm.value.systemAgent).toStrictEqual(inputPath);
65
- expect(wrapper.vm.value.provisioning).toStrictEqual(inputPath);
66
- 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);
67
114
  });
68
115
 
69
- it('on a mode different than _CREATE all visible inputs should be disabled (with different values)', () => {
116
+ it('should render the component with configuration being an empty object, without errors and radio be of value DATA_DIR_RADIO_OPTIONS.CUSTOM (edit scenario)', () => {
70
117
  const newMountOptions = clone(mountOptions);
71
- const inputPath1 = 'some-data-dir1';
72
- const inputPath2 = 'some-data-dir2';
73
- const inputPath3 = 'some-data-dir3';
74
118
 
75
- newMountOptions.propsData.value.systemAgent = inputPath1;
76
- newMountOptions.propsData.value.provisioning = inputPath2;
77
- newMountOptions.propsData.value.k8sDistro = inputPath3;
119
+ newMountOptions.propsData.value = {};
78
120
  newMountOptions.propsData.mode = _EDIT;
79
121
 
80
122
  wrapper = mount(
@@ -82,16 +124,59 @@ describe('component: DirectoryConfig', () => {
82
124
  newMountOptions
83
125
  );
84
126
 
127
+ const title = wrapper.find('h3');
128
+ const radioInput = wrapper.find('[data-testid="rke2-directory-config-radio-input"]');
85
129
  const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
86
130
  const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
87
131
  const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
88
132
 
133
+ expect(title.exists()).toBe(true);
134
+ expect(radioInput.isVisible()).toBe(false);
135
+
136
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.CUSTOM);
137
+
138
+ // since we have all of the vars empty, then the inputs should not be there
89
139
  expect(systemAgentInput.exists()).toBe(true);
90
140
  expect(provisioningInput.exists()).toBe(true);
91
141
  expect(k8sDistroInput.exists()).toBe(true);
92
142
 
93
- expect(systemAgentInput.attributes('disabled')).toBe('disabled');
94
- expect(provisioningInput.attributes('disabled')).toBe('disabled');
95
- expect(k8sDistroInput.attributes('disabled')).toBe('disabled');
143
+ expect(systemAgentInput.attributes().disabled).toBeDefined();
144
+ expect(provisioningInput.attributes().disabled).toBeDefined();
145
+ expect(k8sDistroInput.attributes().disabled).toBeDefined();
146
+ });
147
+
148
+ it('radio input should be set to DATA_DIR_RADIO_OPTIONS.CUSTOM with all data dir values existing and different (edit scenario)', () => {
149
+ const newMountOptions = clone(mountOptions);
150
+ const inputPath = 'some-data-dir';
151
+
152
+ newMountOptions.propsData.value.systemAgent = `${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`;
153
+ newMountOptions.propsData.value.provisioning = `${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`;
154
+ newMountOptions.propsData.value.k8sDistro = `${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_K3S }`;
155
+ newMountOptions.propsData.mode = _EDIT;
156
+
157
+ wrapper = mount(
158
+ DirectoryConfig,
159
+ newMountOptions
160
+ );
161
+
162
+ expect(wrapper.vm.dataConfigRadioValue).toBe(DATA_DIR_RADIO_OPTIONS.CUSTOM);
163
+
164
+ const radioInput = wrapper.find('[data-testid="rke2-directory-config-radio-input"]');
165
+ const systemAgentInput = wrapper.find('[data-testid="rke2-directory-config-systemAgent-data-dir"]');
166
+ const provisioningInput = wrapper.find('[data-testid="rke2-directory-config-provisioning-data-dir"]');
167
+ const k8sDistroInput = wrapper.find('[data-testid="rke2-directory-config-k8sDistro-data-dir"]');
168
+
169
+ expect(radioInput.isVisible()).toBe(false);
170
+ expect(systemAgentInput.isVisible()).toBe(true);
171
+ expect(provisioningInput.isVisible()).toBe(true);
172
+ expect(k8sDistroInput.isVisible()).toBe(true);
173
+
174
+ expect(systemAgentInput.attributes().disabled).toBeDefined();
175
+ expect(provisioningInput.attributes().disabled).toBeDefined();
176
+ expect(k8sDistroInput.attributes().disabled).toBeDefined();
177
+
178
+ expect(wrapper.vm.value.systemAgent).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.AGENT }`);
179
+ expect(wrapper.vm.value.provisioning).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.PROVISIONING }`);
180
+ expect(wrapper.vm.value.k8sDistro).toStrictEqual(`${ inputPath }/${ DEFAULT_SUBDIRS.K8S_DISTRO_K3S }`);
96
181
  });
97
182
  });
@@ -203,8 +203,9 @@ export default {
203
203
 
204
204
  emberLink() {
205
205
  if (this.value) {
206
+ // set subtype if editing EKS/GKE/AKS cluster -- this ensures that the component provided by extension is loaded instead of iframing old ember ui
206
207
  if (this.value.provisioner) {
207
- const matchingSubtype = this.subTypes.find((st) => st.id.toLowerCase() === this.value.provisioner.toLowerCase() || DRIVER_TO_IMPORT[st.id.toLowerCase()] === this.value.provisioner.toLowerCase());
208
+ const matchingSubtype = this.subTypes.find((st) => DRIVER_TO_IMPORT[st.id.toLowerCase()] === this.value.provisioner.toLowerCase());
208
209
 
209
210
  if (matchingSubtype) {
210
211
  this.selectType(matchingSubtype.id, false);
@@ -395,7 +396,8 @@ export default {
395
396
  disabled: ext.disabled || false,
396
397
  link: ext.link,
397
398
  tag: ext.tag,
398
- component: ext.component
399
+ component: ext.component,
400
+ hidden: ext.hidden,
399
401
  };
400
402
 
401
403
  out.push(subtype);
@@ -440,10 +442,14 @@ export default {
440
442
  }
441
443
  },
442
444
 
445
+ filteredSubTypes() {
446
+ return this.subTypes.filter((subtype) => !subtype.hidden);
447
+ },
448
+
443
449
  groupedSubTypes() {
444
450
  const out = {};
445
451
 
446
- for ( const row of this.subTypes ) {
452
+ for ( const row of this.filteredSubTypes ) {
447
453
  const name = row.group;
448
454
  let entry = out[name];
449
455
 
@@ -605,7 +611,7 @@ export default {
605
611
  <div
606
612
  v-for="(obj, i) in groupedSubTypes"
607
613
  :key="obj.id"
608
- class="mb-20"
614
+ :class="{'mt-5': i === 0, 'mt-20': i !== 0 }"
609
615
  style="width: 100%;"
610
616
  >
611
617
  <h4>
@@ -64,14 +64,12 @@ import AddOnConfig from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnCo
64
64
  import Advanced from '@shell/edit/provisioning.cattle.io.cluster/tabs/Advanced';
65
65
  import ClusterAppearance from '@shell/components/form/ClusterAppearance';
66
66
  import AddOnAdditionalManifest from '@shell/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest';
67
- import VsphereUtils from '@shell/utils/v-sphere';
67
+ import VsphereUtils, { VMWARE_VSPHERE } from '@shell/utils/v-sphere';
68
68
 
69
69
  const HARVESTER = 'harvester';
70
70
  const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
71
71
  const NETBIOS_TRUNCATION_LENGTH = 15;
72
72
 
73
- const VMWARE_VSPHERE = 'vmwarevsphere';
74
-
75
73
  /**
76
74
  * Classes to be adopted by the node badges in Machine pools
77
75
  */
@@ -101,6 +101,7 @@ export default {
101
101
  <template v-if="haveArgInfo">
102
102
  <DirectoryConfig
103
103
  v-model="value.spec.rkeConfig.dataDirectories"
104
+ :k8s-version="value.spec.kubernetesVersion"
104
105
  :mode="mode"
105
106
  />
106
107
  <h3>{{ t('cluster.advanced.argInfo.title') }}</h3>