@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
@@ -1,63 +1,214 @@
1
1
 
2
2
  <script>
3
3
  import { LabeledInput } from '@components/Form/LabeledInput';
4
- import { _CREATE } from '@shell/config/query-params';
4
+ import { _CREATE, _EDIT } from '@shell/config/query-params';
5
+ import RadioGroup from '@components/Form/Radio/RadioGroup.vue';
6
+ import { Banner } from '@components/Banner';
7
+
8
+ export const DATA_DIR_RADIO_OPTIONS = {
9
+ DEFAULT: 'defaultDataDir',
10
+ COMMON: 'commonBaseDataDir',
11
+ CUSTOM: 'customDataDir',
12
+ };
13
+
14
+ export const DEFAULT_COMMON_BASE_PATH = '/var/lib/rancher';
15
+
16
+ export const DEFAULT_SUBDIRS = {
17
+ AGENT: 'agent',
18
+ PROVISIONING: 'provisioning',
19
+ K8S_DISTRO_RKE2: 'rke2',
20
+ K8S_DISTRO_K3S: 'k3s',
21
+ };
5
22
 
6
23
  export default {
7
24
  name: 'DirectoryConfig',
8
- components: { LabeledInput },
9
- props: {
25
+ components: {
26
+ LabeledInput,
27
+ RadioGroup,
28
+ Banner
29
+ },
30
+ props: {
10
31
  mode: {
11
32
  type: String,
12
33
  required: true,
13
34
  },
14
35
 
36
+ k8sVersion: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+
15
41
  value: {
16
42
  type: Object,
17
43
  required: true,
18
44
  },
19
45
  },
46
+ data() {
47
+ let dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
48
+ let k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
49
+
50
+ if (this.k8sVersion && this.k8sVersion.includes('k3s')) {
51
+ k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_K3S;
52
+ }
53
+
54
+ if (this.mode !== _CREATE) {
55
+ dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
56
+ }
57
+
58
+ return {
59
+ DATA_DIR_RADIO_OPTIONS,
60
+ dataConfigRadioValue,
61
+ k8sDistroSubDir,
62
+ commonConfig: '',
63
+ };
64
+ },
65
+ watch: {
66
+ commonConfig(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
+ }
84
+ }
85
+ }
86
+ },
20
87
  computed: {
21
- disableEditInput() {
22
- return this.mode !== _CREATE;
88
+ isDisabled() {
89
+ return this.mode === _EDIT;
90
+ },
91
+ dataConfigRadioOptions() {
92
+ const defaultDataDirOption = {
93
+ value: DATA_DIR_RADIO_OPTIONS.DEFAULT,
94
+ label: this.t('cluster.directoryConfig.radioInput.defaultLabel')
95
+ };
96
+ const customDataDirOption = {
97
+ value: DATA_DIR_RADIO_OPTIONS.CUSTOM,
98
+ label: this.t('cluster.directoryConfig.radioInput.customLabel')
99
+ };
100
+
101
+ if (this.mode === _CREATE) {
102
+ return [
103
+ defaultDataDirOption,
104
+ { value: DATA_DIR_RADIO_OPTIONS.COMMON, label: this.t('cluster.directoryConfig.radioInput.commonLabel') },
105
+ customDataDirOption
106
+ ];
107
+ } else {
108
+ return [
109
+ defaultDataDirOption,
110
+ customDataDirOption
111
+ ];
112
+ }
113
+ }
114
+ },
115
+ methods: {
116
+ handleRadioInput(val) {
117
+ switch (val) {
118
+ case DATA_DIR_RADIO_OPTIONS.DEFAULT:
119
+ if (this.mode === _CREATE) {
120
+ this.commonConfig = '';
121
+ }
122
+ this.value.systemAgent = '';
123
+ this.value.provisioning = '';
124
+ this.value.k8sDistro = '';
125
+
126
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
127
+ break;
128
+ case DATA_DIR_RADIO_OPTIONS.COMMON:
129
+ this.commonConfig = DEFAULT_COMMON_BASE_PATH;
130
+
131
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.COMMON;
132
+ break;
133
+ // default is custom config
134
+ default:
135
+ if (this.mode === _CREATE) {
136
+ this.commonConfig = '';
137
+ }
138
+
139
+ this.value.systemAgent = '';
140
+ this.value.provisioning = '';
141
+ this.value.k8sDistro = '';
142
+
143
+ this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
144
+ break;
145
+ }
23
146
  }
24
- }
147
+ },
25
148
  };
26
149
  </script>
27
150
 
28
151
  <template>
29
152
  <div class="row">
30
153
  <div class="col span-8">
31
- <h3 class="mb-20">
154
+ <h3>
32
155
  {{ t('cluster.directoryConfig.title') }}
33
156
  </h3>
34
- <LabeledInput
35
- v-model="value.systemAgent"
157
+ <Banner
36
158
  class="mb-20"
37
- :mode="mode"
38
- :label="t('cluster.directoryConfig.systemAgent.label')"
39
- :tooltip="t('cluster.directoryConfig.systemAgent.tooltip')"
40
- :disabled="disableEditInput"
41
- data-testid="rke2-directory-config-systemAgent-data-dir"
159
+ :closable="false"
160
+ color="info"
161
+ label-key="cluster.directoryConfig.banner"
42
162
  />
43
- <LabeledInput
44
- v-model="value.provisioning"
45
- class="mb-20"
163
+ <RadioGroup
164
+ v-show="!isDisabled"
165
+ :value="dataConfigRadioValue"
166
+ class="mb-10"
46
167
  :mode="mode"
47
- :label="t('cluster.directoryConfig.provisioning.label')"
48
- :tooltip="t('cluster.directoryConfig.provisioning.tooltip')"
49
- :disabled="disableEditInput"
50
- data-testid="rke2-directory-config-provisioning-data-dir"
168
+ :options="dataConfigRadioOptions"
169
+ name="directory-config-radio"
170
+ data-testid="rke2-directory-config-radio-input"
171
+ @input="handleRadioInput"
51
172
  />
52
173
  <LabeledInput
53
- v-model="value.k8sDistro"
174
+ v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.COMMON"
175
+ v-model="commonConfig"
54
176
  class="mb-20"
55
177
  :mode="mode"
56
- :label="t('cluster.directoryConfig.k8sDistro.label')"
57
- :tooltip="t('cluster.directoryConfig.k8sDistro.tooltip')"
58
- :disabled="disableEditInput"
59
- data-testid="rke2-directory-config-k8sDistro-data-dir"
178
+ :label="t('cluster.directoryConfig.common.label')"
179
+ :tooltip="t('cluster.directoryConfig.common.tooltip')"
180
+ :disabled="isDisabled"
181
+ data-testid="rke2-directory-config-common-data-dir"
60
182
  />
183
+ <div v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.CUSTOM">
184
+ <LabeledInput
185
+ v-model="value.systemAgent"
186
+ class="mb-20"
187
+ :mode="mode"
188
+ :label="t('cluster.directoryConfig.systemAgent.label')"
189
+ :tooltip="t('cluster.directoryConfig.systemAgent.tooltip')"
190
+ :disabled="isDisabled"
191
+ data-testid="rke2-directory-config-systemAgent-data-dir"
192
+ />
193
+ <LabeledInput
194
+ v-model="value.provisioning"
195
+ class="mb-20"
196
+ :mode="mode"
197
+ :label="t('cluster.directoryConfig.provisioning.label')"
198
+ :tooltip="t('cluster.directoryConfig.provisioning.tooltip')"
199
+ :disabled="isDisabled"
200
+ data-testid="rke2-directory-config-provisioning-data-dir"
201
+ />
202
+ <LabeledInput
203
+ v-model="value.k8sDistro"
204
+ class="mb-20"
205
+ :mode="mode"
206
+ :label="t('cluster.directoryConfig.k8sDistro.label')"
207
+ :tooltip="t('cluster.directoryConfig.k8sDistro.tooltip')"
208
+ :disabled="isDisabled"
209
+ data-testid="rke2-directory-config-k8sDistro-data-dir"
210
+ />
211
+ </div>
61
212
  <div class="mb-40" />
62
213
  </div>
63
214
  </div>
@@ -7,9 +7,9 @@ jest.mock('@shell/utils/clipboard', () => {
7
7
  describe('class MgmtCluster', () => {
8
8
  describe('provisioner', () => {
9
9
  const testCases = [
10
- [{ provider: 'rke', driver: 'imported' }, 'rke'],
11
- [{ provider: 'k3s', driver: 'K3S' }, 'k3s'],
12
- [{ provider: 'aks', driver: 'AKS' }, 'aks'],
10
+ [{ provider: 'rke', driver: 'imported' }, 'imported'],
11
+ [{ provider: 'k3s', driver: 'K3S' }, 'K3S'],
12
+ [{ provider: 'aks', driver: 'AKS' }, 'AKS'],
13
13
  [{}, 'imported'],
14
14
  ];
15
15
 
@@ -1,31 +1,6 @@
1
1
  import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
2
2
 
3
3
  describe('class ProvCluster', () => {
4
- const importedClusterInfo = {
5
- clusterName: 'test', provisioner: 'imported', mgmt: { spec: { gkeConfig: {} } }, spec: {}
6
- };
7
- const importedGkeClusterInfo = {
8
- clusterName: 'test', provisioner: 'rke2', mgmt: { spec: { gkeConfig: { imported: true } } }
9
- };
10
- const importedAksClusterInfo = {
11
- clusterName: 'test', provisioner: 'rke2', mgmt: { spec: { aksConfig: { imported: true } } }
12
- };
13
- const importedEksClusterInfo = {
14
- clusterName: 'test', provisioner: 'rke2', mgmt: { spec: { eksConfig: { imported: true } } }
15
- };
16
- const notImportedGkeClusterInfo = {
17
- clusterName: 'test', provisioner: 'rke2', mgmt: { spec: { gkeConfig: { imported: false } }, rkeConfig: {} }
18
- };
19
- const importedClusterInfoWithProviderForEmberParam = {
20
- clusterName: 'test', provisioner: 'rke2', mgmt: { providerForEmberParam: 'import' }
21
- };
22
- const localClusterInfo = {
23
- clusterName: 'test', provisioner: 'imported', mgmt: { isLocal: true, spec: { gkeConfig: {} } }, spec: {}
24
- };
25
- const doRke2Info = {
26
- clusterName: 'test', provisioner: 'rke2', mgmt: { isLocal: false, providerForEmberParam: 'import' }, spec: { rkeConfig: {} }
27
- };
28
-
29
4
  const gkeClusterWithPrivateEndpoint = {
30
5
  clusterName: 'test',
31
6
  provisioner: 'GKE',
@@ -76,67 +51,6 @@ describe('class ProvCluster', () => {
76
51
  });
77
52
  });
78
53
 
79
- describe('isImported', () => {
80
- const testCases = [
81
- [importedClusterInfo, true],
82
- [importedGkeClusterInfo, true],
83
- [importedAksClusterInfo, true],
84
- [importedEksClusterInfo, true],
85
- [notImportedGkeClusterInfo, false],
86
- [importedClusterInfoWithProviderForEmberParam, true],
87
- [localClusterInfo, false],
88
- [doRke2Info, false],
89
- [{}, false],
90
- ];
91
- const resetMocks = () => {
92
- // Clear all mock function calls:
93
- jest.clearAllMocks();
94
- };
95
-
96
- it.each(testCases)('should return the isImported value properly based on the props data', (clusterData: Object, expected: Boolean) => {
97
- const cluster = new ProvCluster({ spec: clusterData.spec });
98
-
99
- jest.spyOn(cluster, 'mgmt', 'get').mockReturnValue(
100
- clusterData.mgmt
101
- );
102
- jest.spyOn(cluster, 'provisioner', 'get').mockReturnValue(
103
- clusterData.provisioner
104
- );
105
-
106
- expect(cluster.isImported).toBe(expected);
107
- resetMocks();
108
- }
109
- );
110
- });
111
-
112
- describe('mgmt', () => {
113
- const testCases = [
114
- [importedClusterInfo, importedClusterInfo.mgmt],
115
- [importedGkeClusterInfo, importedGkeClusterInfo.mgmt],
116
- [importedAksClusterInfo, importedAksClusterInfo.mgmt],
117
- [importedEksClusterInfo, importedEksClusterInfo.mgmt],
118
- [notImportedGkeClusterInfo, notImportedGkeClusterInfo.mgmt],
119
- [importedClusterInfoWithProviderForEmberParam, importedClusterInfoWithProviderForEmberParam.mgmt],
120
- [localClusterInfo, localClusterInfo.mgmt],
121
- [doRke2Info, doRke2Info.mgmt],
122
- [{}, null],
123
- ];
124
-
125
- const resetMocks = () => {
126
- // Clear all mock function calls:
127
- jest.clearAllMocks();
128
- };
129
-
130
- it.each(testCases)('should return the isImported value properly based on the props data', (clusterData: Object, expected: Object) => {
131
- const clusterMock = jest.fn(() => clusterData.mgmt);
132
- const ctx = { rootGetters: { 'management/byId': clusterMock } };
133
- const cluster = new ProvCluster({ status: { clusterName: clusterData.clusterName } }, ctx);
134
-
135
- expect(cluster.mgmt).toBe(expected);
136
- resetMocks();
137
- });
138
- });
139
-
140
54
  describe('hasError', () => {
141
55
  const conditionsWithoutError = [
142
56
  {
@@ -30,7 +30,9 @@ export default class FleetBundle extends SteveModel {
30
30
  }
31
31
 
32
32
  get repoName() {
33
- return this.metadata.labels['fleet.cattle.io/repo-name'];
33
+ const labels = this.metadata?.labels || {};
34
+
35
+ return labels['fleet.cattle.io/repo-name'];
34
36
  }
35
37
 
36
38
  get targetClusters() {
@@ -1,16 +1,17 @@
1
1
  import Vue from 'vue';
2
2
  import { convert, matching, convertSelectorObj } from '@shell/utils/selector';
3
3
  import jsyaml from 'js-yaml';
4
- import { escapeHtml, randomStr } from '@shell/utils/string';
4
+ import { escapeHtml } from '@shell/utils/string';
5
5
  import { FLEET } from '@shell/config/types';
6
6
  import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
7
7
  import { addObject, addObjects, findBy, insertAt } from '@shell/utils/array';
8
8
  import { set } from '@shell/utils/object';
9
9
  import SteveModel from '@shell/plugins/steve/steve-class';
10
10
  import {
11
- STATES_ENUM, colorForState, mapStateToEnum, primaryDisplayStatusFromCount, stateDisplay, stateSort
11
+ colorForState, mapStateToEnum, primaryDisplayStatusFromCount, stateDisplay, stateSort
12
12
  } from '@shell/plugins/dashboard-store/resource-class';
13
13
  import { NAME } from '@shell/config/product/explorer';
14
+ import FleetUtils from '@shell/utils/fleet';
14
15
 
15
16
  function quacksLikeAHash(str) {
16
17
  if (str.match(/^[a-f0-9]{40,}$/i)) {
@@ -322,35 +323,29 @@ export default class GitRepo extends SteveModel {
322
323
  }
323
324
 
324
325
  get resourcesStatuses() {
325
- const clusters = this.targetClusters || [];
326
- const resources = this.status?.resources || [];
327
- const conditions = this.status?.conditions || [];
326
+ const bundleDeployments = this.bundleDeployments || [];
327
+ const clusters = (this.targetClusters || []).reduce((res, c) => {
328
+ res[c.id] = c;
329
+
330
+ return res;
331
+ }, {});
328
332
 
329
333
  const out = [];
330
334
 
331
- for (const c of clusters) {
332
- const clusterBundleDeploymentResources = this.bundleDeployments
333
- .find((bd) => bd.metadata?.labels?.[FLEET_ANNOTATIONS.CLUSTER] === c.metadata.name)
334
- ?.status?.resources || [];
335
+ for (const bd of bundleDeployments) {
336
+ const clusterId = FleetUtils.clusterIdFromBundleDeploymentLabels(bd.metadata?.labels);
337
+ const c = clusters[clusterId];
335
338
 
336
- resources.forEach((r, i) => {
337
- let namespacedName = r.name;
339
+ if (!c) {
340
+ continue;
341
+ }
338
342
 
339
- if (r.namespace) {
340
- namespacedName = `${ r.namespace }:${ r.name }`;
341
- }
343
+ const resources = FleetUtils.resourcesFromBundleDeploymentStatus(bd.status);
342
344
 
343
- let state = r.state;
344
- const perEntry = r.perClusterState?.find((x) => x.clusterId === c.id);
345
- const tooMany = r.perClusterState?.length >= 10 || false;
346
-
347
- if (perEntry) {
348
- state = perEntry.state;
349
- } else if (tooMany) {
350
- state = STATES_ENUM.UNKNOWN;
351
- } else {
352
- state = STATES_ENUM.READY;
353
- }
345
+ resources.forEach((r) => {
346
+ const id = FleetUtils.resourceId(r);
347
+ const type = FleetUtils.resourceType(r);
348
+ const state = r.state;
354
349
 
355
350
  const color = colorForState(state).replace('text-', 'bg-');
356
351
  const display = stateDisplay(state);
@@ -360,33 +355,38 @@ export default class GitRepo extends SteveModel {
360
355
  params: {
361
356
  product: NAME,
362
357
  cluster: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME],
363
- resource: r.type,
358
+ resource: type,
364
359
  namespace: r.namespace,
365
360
  id: r.name,
366
361
  }
367
362
  };
368
363
 
364
+ const key = `${ c.id }-${ type }-${ r.namespace }-${ r.name }`;
365
+
369
366
  out.push({
370
- key: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }`,
371
- tableKey: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }-${ randomStr(8) }`,
372
- kind: r.kind,
373
- apiVersion: r.apiVersion,
374
- type: r.type,
375
- id: r.id,
376
- namespace: r.namespace,
377
- name: r.name,
378
- clusterId: c.id,
379
- clusterLabel: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME],
380
- clusterName: c.nameDisplay,
381
- state: mapStateToEnum(state),
382
- stateBackground: color,
383
- stateDisplay: display,
384
- stateSort: stateSort(color, display),
385
- namespacedName,
367
+ key,
368
+ tableKey: key,
369
+
370
+ // Needed?
371
+ id,
372
+ type,
373
+ clusterId: c.id,
374
+
375
+ // columns, see FleetResources.vue
376
+ state: mapStateToEnum(state),
377
+ clusterName: c.nameDisplay,
378
+ apiVersion: r.apiVersion,
379
+ kind: r.kind,
380
+ name: r.name,
381
+ namespace: r.namespace,
382
+ creationTimestamp: r.createdAt,
383
+
384
+ // other properties
385
+ clusterLabel: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME],
386
+ stateBackground: color,
387
+ stateDisplay: display,
388
+ stateSort: stateSort(color, display),
386
389
  detailLocation,
387
- conditions: conditions[i],
388
- bundleDeploymentStatus: clusterBundleDeploymentResources?.[i],
389
- creationTimestamp: clusterBundleDeploymentResources?.[i]?.createdAt
390
390
  });
391
391
  });
392
392
  }
@@ -407,9 +407,7 @@ export default class GitRepo extends SteveModel {
407
407
 
408
408
  get clusterResourceStatus() {
409
409
  const clusterStatuses = this.resourcesStatuses.reduce((prev, curr) => {
410
- const { clusterId, clusterLabel } = curr;
411
-
412
- const state = curr.state;
410
+ const { clusterId, clusterLabel, state } = curr;
413
411
 
414
412
  if (!prev[clusterId]) {
415
413
  prev[clusterId] = {
@@ -90,10 +90,6 @@ export default class MgmtCluster extends SteveModel {
90
90
  }
91
91
 
92
92
  get provisioner() {
93
- if (this.status?.provider ) {
94
- return this.status.provider;
95
- }
96
-
97
93
  // For imported K3s clusters, this.status.driver is 'k3s.'
98
94
  return this.status?.driver ? this.status.driver : 'imported';
99
95
  }
@@ -117,7 +113,8 @@ export default class MgmtCluster extends SteveModel {
117
113
  get providerForEmberParam() {
118
114
  // Ember wants one word called provider to tell what component to show, but has much indirect mapping to figure out what it is.
119
115
  let provider;
120
- // Provisioner is the "<something>Config" in the model
116
+
117
+ // provisioner is status.driver
121
118
  const provisioner = KONTAINER_TO_DRIVER[(this.provisioner || '').toLowerCase()] || this.provisioner;
122
119
 
123
120
  if ( provisioner === 'rancherKubernetesEngine' ) {
@@ -282,19 +282,29 @@ export default class ProvCluster extends SteveModel {
282
282
  }
283
283
 
284
284
  get isImported() {
285
- // As of Rancher v2.6.7, this returns false for imported K3s clusters,
286
- // in which this.provisioner is `k3s`.
285
+ if (this.isLocal) {
286
+ return false;
287
+ }
288
+
289
+ // imported rke2 and k3s have status.driver === rke2 and k3s respectively
290
+ // Provisioned rke2 and k3s have status.driver === imported
291
+ if (this.mgmt?.status?.provider === 'k3s' || this.mgmt?.status?.provider === 'rke2') {
292
+ return this.mgmt?.status?.driver === this.mgmt?.status?.provider;
293
+ }
287
294
 
288
- const isImportedProvisioner = this.provisioner === 'imported';
289
- const isImportedSpecialCases = this.mgmt?.providerForEmberParam === 'import' ||
290
- // when imported cluster is GKE
291
- !!this.mgmt?.spec?.gkeConfig?.imported ||
292
- // or AKS
293
- !!this.mgmt?.spec?.aksConfig?.imported ||
294
- // or EKS
295
- !!this.mgmt?.spec?.eksConfig?.imported;
295
+ // imported KEv2
296
+ // we can't rely on this.provisioner to determine imported-ness for these clusters, as it will return 'aks' 'eks' 'gke' for both provisioned and imported clusters
297
+ const kontainerConfigs = ['aksConfig', 'eksConfig', 'gkeConfig'];
298
+
299
+ const isImportedKontainer = kontainerConfigs.filter((key) => {
300
+ return this.mgmt?.spec?.[key]?.imported === true;
301
+ }).length;
302
+
303
+ if (isImportedKontainer) {
304
+ return true;
305
+ }
296
306
 
297
- return !this.isLocal && (isImportedProvisioner || (!this.isRke2 && !this.mgmt?.machineProvider && isImportedSpecialCases));
307
+ return this.provisioner === 'imported';
298
308
  }
299
309
 
300
310
  get isCustom() {
@@ -330,7 +340,8 @@ export default class ProvCluster extends SteveModel {
330
340
  }
331
341
 
332
342
  get isRke1() {
333
- return !!this.mgmt?.spec?.rancherKubernetesEngineConfig || this.labels['provider.cattle.io'] === 'rke';
343
+ // rancherKubernetesEngineConfig is not defined on imported RKE1 clusters
344
+ return !!this.mgmt?.spec?.rancherKubernetesEngineConfig || this.mgmt?.labels['provider.cattle.io'] === 'rke';
334
345
  }
335
346
 
336
347
  get isHarvester() {
@@ -407,6 +418,8 @@ export default class ProvCluster extends SteveModel {
407
418
  provisioner = 'k3s';
408
419
  } else if ( this.isImportedRke2 ) {
409
420
  provisioner = 'rke2';
421
+ } else if ((this.isImported || this.isLocal) && this.isRke1) {
422
+ provisioner = 'rke';
410
423
  }
411
424
 
412
425
  return this.$rootGetters['i18n/withFallback'](`cluster.provider."${ provisioner }"`, null, ucFirst(provisioner));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -40,6 +40,7 @@ export default {
40
40
  allBundles: {
41
41
  inStoreType: 'management',
42
42
  type: FLEET.BUNDLE,
43
+ opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] },
43
44
  },
44
45
  gitRepos: {
45
46
  inStoreType: 'management',
@@ -1,10 +1,8 @@
1
1
  annotations:
2
2
  catalog.cattle.io/certified: rancher # Any application we are adding as a helm chart
3
- catalog.cattle.io/kube-version: '>= 1.16.0-0'
4
3
  catalog.cattle.io/namespace: cattle-ui-plugin-system # Must prefix with cattle- and suffix with -system=
5
4
  catalog.cattle.io/os: linux
6
5
  catalog.cattle.io/permits-os: linux, windows
7
- catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.9.0-0'
8
6
  catalog.cattle.io/scope: management
9
7
  catalog.cattle.io/ui-component: plugins
10
8
  apiVersion: v2
@@ -4,27 +4,36 @@ GITHUB_RELEASE_TAG=$1
4
4
  GITHUB_RUN_ID=$2
5
5
  GITHUB_WORKFLOW_TYPE=$3
6
6
 
7
- # Ensure "catalog" workflow release tag name does not match a pkg/<pkg-name>
7
+ echo "Parse tag name - evaluating release tag $GITHUB_RELEASE_TAG"
8
+
9
+ # Ensure "catalog" workflow release tag name matches the root <pkg-name>
8
10
  if [[ "${GITHUB_WORKFLOW_TYPE}" == "catalog" ]]; then
11
+ BASE_EXT=$(jq -r .name package.json)
12
+ EXT_VERSION=$(jq -r .version package.json)
13
+
14
+ if [[ "${GITHUB_RELEASE_TAG}" != "${BASE_EXT}-${EXT_VERSION}" ]]; then
15
+ echo -e "release tag doesn't match catalog tag: release tag -> ${GITHUB_RELEASE_TAG} ::: curr catalog tag -> ${BASE_EXT}-${EXT_VERSION}"
16
+ gh run cancel ${GITHUB_RUN_ID}
17
+ exit 1
18
+ fi
19
+ # Ensure "chart" workflow release tag name matches some pkg/<pkg-name>
20
+ else
21
+ NO_MATCHES="true"
22
+
9
23
  for d in pkg/*/ ; do
10
24
  pkg=$(basename $d)
11
25
 
12
26
  PKG_VERSION=$(jq -r .version pkg/${pkg}/package.json)
13
- PKG_NAME="${pkg}-${PKG_VERSION}"
27
+ CURR_PKG_TAG="${pkg}-${PKG_VERSION}"
14
28
 
15
- if [[ "${GITHUB_RELEASE_TAG}" == "${PKG_NAME}" ]]; then
16
- gh run cancel ${GITHUB_RUN_ID}
17
- else
18
- continue
29
+ if [[ "${GITHUB_RELEASE_TAG}" == "${CURR_PKG_TAG}" ]]; then
30
+ NO_MATCHES="false"
19
31
  fi
20
32
  done
21
- else
22
- # Ensure "charts" workflow release tag name does not match the root <pkg-name>
23
- BASE_EXT=$(jq -r .name package.json)
24
- EXT_VERSION=$(jq -r .version package.json)
25
33
 
26
- if [[ "${GITHUB_RELEASE_TAG}" == "${BASE_EXT}-${EXT_VERSION}" ]]; then
27
- echo -e "tag: ${GITHUB_RELEASE_TAG}"
34
+ if [[ "${NO_MATCHES}" == "true" ]]; then
35
+ echo -e "release tag doesn't match any chart tag: ${GITHUB_RELEASE_TAG}. Check your pkg/<!-YOUR-EXT-> folders and corresponding versions to complete the match"
28
36
  gh run cancel ${GITHUB_RUN_ID}
37
+ exit 1
29
38
  fi
30
39
  fi