@rancher/shell 3.0.0-rc.7 → 3.0.0-rc.8
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.
- package/assets/styles/global/_tooltip.scss +1 -12
- package/assets/translations/en-us.yaml +13 -1
- package/components/CodeMirror.vue +18 -15
- package/components/PromptRemove.vue +2 -2
- package/components/Questions/index.vue +2 -2
- package/components/ResourceDetail/Masthead.vue +1 -0
- package/components/ResourceDetail/index.vue +6 -7
- package/components/auth/RoleDetailEdit.vue +1 -6
- package/components/auth/__tests__/RoleDetailEdit.test.ts +53 -16
- package/components/form/ArrayList.vue +7 -3
- package/components/formatter/CloudCredExpired.vue +69 -0
- package/components/formatter/Date.vue +1 -1
- package/components/nav/TopLevelMenu.vue +115 -51
- package/components/nav/__tests__/TopLevelMenu.test.ts +49 -23
- package/config/labels-annotations.js +9 -5
- package/core/types.ts +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +0 -4
- package/edit/management.cattle.io.project.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +7 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +28 -5
- package/list/provisioning.cattle.io.cluster.vue +57 -10
- package/machine-config/vmwarevsphere.vue +133 -95
- package/mixins/vue-select-overrides.js +0 -1
- package/models/catalog.cattle.io.app.js +4 -3
- package/models/cloudcredential.js +158 -2
- package/models/management.cattle.io.globalrole.js +6 -0
- package/models/management.cattle.io.roletemplate.js +6 -0
- package/models/nodedriver.js +5 -0
- package/models/provisioning.cattle.io.cluster.js +35 -1
- package/package.json +1 -1
- package/pages/c/_cluster/apps/charts/index.vue +0 -6
- package/pages/c/_cluster/manager/cloudCredential/index.vue +68 -4
- package/pages/home.vue +1 -0
- package/plugins/dashboard-store/mutations.js +24 -3
- package/plugins/dashboard-store/resource-class.js +6 -0
- package/store/type-map.js +4 -2
- package/types/shell/index.d.ts +12 -1
|
@@ -5,7 +5,7 @@ import { mount, Wrapper } from '@vue/test-utils';
|
|
|
5
5
|
// DISCLAIMER: This should not be added here, although we have several store requests which are irrelevant
|
|
6
6
|
const defaultStore = {
|
|
7
7
|
'management/byId': jest.fn(),
|
|
8
|
-
'management/schemaFor':
|
|
8
|
+
'management/schemaFor': () => ({}),
|
|
9
9
|
'i18n/t': jest.fn(),
|
|
10
10
|
'features/get': jest.fn(),
|
|
11
11
|
'prefs/theme': jest.fn(),
|
|
@@ -21,7 +21,11 @@ describe('topLevelMenu', () => {
|
|
|
21
21
|
mocks: {
|
|
22
22
|
$store: {
|
|
23
23
|
getters: {
|
|
24
|
-
'management/all': () => [{
|
|
24
|
+
'management/all': () => [{
|
|
25
|
+
name: 'whatever',
|
|
26
|
+
id: 'an-id1',
|
|
27
|
+
mgmt: { id: 'an-id1' },
|
|
28
|
+
}],
|
|
25
29
|
...defaultStore
|
|
26
30
|
},
|
|
27
31
|
},
|
|
@@ -53,21 +57,21 @@ describe('topLevelMenu', () => {
|
|
|
53
57
|
'management/all': () => [
|
|
54
58
|
{
|
|
55
59
|
name: 'x32-cwf5-name',
|
|
56
|
-
id: '
|
|
60
|
+
id: 'an-id1',
|
|
57
61
|
mgmt: { id: 'an-id1' },
|
|
58
62
|
nameDisplay: 'c-cluster',
|
|
59
63
|
isReady: true
|
|
60
64
|
},
|
|
61
65
|
{
|
|
62
66
|
name: 'x33-cwf5-name',
|
|
63
|
-
id: '
|
|
67
|
+
id: 'an-id2',
|
|
64
68
|
mgmt: { id: 'an-id2' },
|
|
65
69
|
nameDisplay: 'a-cluster',
|
|
66
70
|
isReady: true
|
|
67
71
|
},
|
|
68
72
|
{
|
|
69
73
|
name: 'x34-cwf5-name',
|
|
70
|
-
id: '
|
|
74
|
+
id: 'an-id3',
|
|
71
75
|
mgmt: { id: 'an-id3' },
|
|
72
76
|
nameDisplay: 'b-cluster',
|
|
73
77
|
isReady: true
|
|
@@ -75,7 +79,7 @@ describe('topLevelMenu', () => {
|
|
|
75
79
|
{
|
|
76
80
|
name: 'local-name',
|
|
77
81
|
id: 'local',
|
|
78
|
-
mgmt: { id: '
|
|
82
|
+
mgmt: { id: 'local' },
|
|
79
83
|
nameDisplay: 'local',
|
|
80
84
|
isReady: true
|
|
81
85
|
},
|
|
@@ -112,21 +116,21 @@ describe('topLevelMenu', () => {
|
|
|
112
116
|
'management/all': () => [
|
|
113
117
|
{
|
|
114
118
|
name: 'x32-cwf5-name',
|
|
115
|
-
id: '
|
|
119
|
+
id: 'an-id1',
|
|
116
120
|
mgmt: { id: 'an-id1' },
|
|
117
121
|
nameDisplay: 'c-cluster',
|
|
118
122
|
isReady: true
|
|
119
123
|
},
|
|
120
124
|
{
|
|
121
125
|
name: 'x33-cwf5-name',
|
|
122
|
-
id: '
|
|
126
|
+
id: 'an-id2',
|
|
123
127
|
mgmt: { id: 'an-id2' },
|
|
124
128
|
nameDisplay: 'a-cluster',
|
|
125
129
|
isReady: false
|
|
126
130
|
},
|
|
127
131
|
{
|
|
128
132
|
name: 'x34-cwf5-name',
|
|
129
|
-
id: '
|
|
133
|
+
id: 'an-id3',
|
|
130
134
|
mgmt: { id: 'an-id3' },
|
|
131
135
|
nameDisplay: 'b-cluster',
|
|
132
136
|
isReady: true
|
|
@@ -134,7 +138,7 @@ describe('topLevelMenu', () => {
|
|
|
134
138
|
{
|
|
135
139
|
name: 'local-name',
|
|
136
140
|
id: 'local',
|
|
137
|
-
mgmt: { id: '
|
|
141
|
+
mgmt: { id: 'local' },
|
|
138
142
|
nameDisplay: 'local',
|
|
139
143
|
isReady: true
|
|
140
144
|
},
|
|
@@ -171,7 +175,7 @@ describe('topLevelMenu', () => {
|
|
|
171
175
|
'management/all': () => [
|
|
172
176
|
{
|
|
173
177
|
name: 'x32-cwf5-name',
|
|
174
|
-
id: '
|
|
178
|
+
id: 'an-id1',
|
|
175
179
|
mgmt: { id: 'an-id1' },
|
|
176
180
|
nameDisplay: 'c-cluster',
|
|
177
181
|
isReady: true,
|
|
@@ -179,7 +183,7 @@ describe('topLevelMenu', () => {
|
|
|
179
183
|
},
|
|
180
184
|
{
|
|
181
185
|
name: 'x33-cwf5-name',
|
|
182
|
-
id: '
|
|
186
|
+
id: 'an-id2',
|
|
183
187
|
mgmt: { id: 'an-id2' },
|
|
184
188
|
nameDisplay: 'a-cluster',
|
|
185
189
|
isReady: true,
|
|
@@ -187,7 +191,7 @@ describe('topLevelMenu', () => {
|
|
|
187
191
|
},
|
|
188
192
|
{
|
|
189
193
|
name: 'x34-cwf5-name',
|
|
190
|
-
id: '
|
|
194
|
+
id: 'an-id3',
|
|
191
195
|
mgmt: { id: 'an-id3' },
|
|
192
196
|
nameDisplay: 'b-cluster',
|
|
193
197
|
isReady: true,
|
|
@@ -196,7 +200,7 @@ describe('topLevelMenu', () => {
|
|
|
196
200
|
{
|
|
197
201
|
name: 'local-name',
|
|
198
202
|
id: 'local',
|
|
199
|
-
mgmt: { id: '
|
|
203
|
+
mgmt: { id: 'local' },
|
|
200
204
|
nameDisplay: 'local',
|
|
201
205
|
isReady: true,
|
|
202
206
|
pinned: true
|
|
@@ -234,7 +238,7 @@ describe('topLevelMenu', () => {
|
|
|
234
238
|
'management/all': () => [
|
|
235
239
|
{
|
|
236
240
|
name: 'x32-cwf5-name',
|
|
237
|
-
id: '
|
|
241
|
+
id: 'an-id1',
|
|
238
242
|
mgmt: { id: 'an-id1' },
|
|
239
243
|
nameDisplay: 'c-cluster',
|
|
240
244
|
isReady: true,
|
|
@@ -242,7 +246,7 @@ describe('topLevelMenu', () => {
|
|
|
242
246
|
},
|
|
243
247
|
{
|
|
244
248
|
name: 'x33-cwf5-name',
|
|
245
|
-
id: '
|
|
249
|
+
id: 'an-id2',
|
|
246
250
|
mgmt: { id: 'an-id2' },
|
|
247
251
|
nameDisplay: 'a-cluster',
|
|
248
252
|
isReady: true,
|
|
@@ -250,7 +254,7 @@ describe('topLevelMenu', () => {
|
|
|
250
254
|
},
|
|
251
255
|
{
|
|
252
256
|
name: 'x34-cwf5-name',
|
|
253
|
-
id: '
|
|
257
|
+
id: 'an-id3',
|
|
254
258
|
mgmt: { id: 'an-id3' },
|
|
255
259
|
nameDisplay: 'b-cluster',
|
|
256
260
|
isReady: false,
|
|
@@ -259,7 +263,7 @@ describe('topLevelMenu', () => {
|
|
|
259
263
|
{
|
|
260
264
|
name: 'local-name',
|
|
261
265
|
id: 'local',
|
|
262
|
-
mgmt: { id: '
|
|
266
|
+
mgmt: { id: 'local' },
|
|
263
267
|
nameDisplay: 'local',
|
|
264
268
|
isReady: true,
|
|
265
269
|
pinned: true
|
|
@@ -356,7 +360,7 @@ describe('topLevelMenu', () => {
|
|
|
356
360
|
it('should show description if it is available on the mgmt cluster (relevant for RKE1/ember world)', async() => {
|
|
357
361
|
const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
|
|
358
362
|
data: () => {
|
|
359
|
-
return { hasProvCluster:
|
|
363
|
+
return { hasProvCluster: true, showPinClusters: true };
|
|
360
364
|
},
|
|
361
365
|
|
|
362
366
|
global: {
|
|
@@ -372,6 +376,7 @@ describe('topLevelMenu', () => {
|
|
|
372
376
|
{
|
|
373
377
|
name: 'whatever',
|
|
374
378
|
id: 'an-id1',
|
|
379
|
+
mgmt: { id: 'an-id1' },
|
|
375
380
|
description: 'some-description1',
|
|
376
381
|
nameDisplay: 'some-label',
|
|
377
382
|
isReady: true,
|
|
@@ -381,6 +386,7 @@ describe('topLevelMenu', () => {
|
|
|
381
386
|
{
|
|
382
387
|
name: 'whatever',
|
|
383
388
|
id: 'an-id2',
|
|
389
|
+
mgmt: { id: 'an-id2' },
|
|
384
390
|
description: 'some-description2',
|
|
385
391
|
nameDisplay: 'some-label',
|
|
386
392
|
pinned: true
|
|
@@ -389,6 +395,7 @@ describe('topLevelMenu', () => {
|
|
|
389
395
|
{
|
|
390
396
|
name: 'whatever',
|
|
391
397
|
id: 'an-id3',
|
|
398
|
+
mgmt: { id: 'an-id3' },
|
|
392
399
|
description: 'some-description3',
|
|
393
400
|
nameDisplay: 'some-label',
|
|
394
401
|
isReady: true
|
|
@@ -397,6 +404,7 @@ describe('topLevelMenu', () => {
|
|
|
397
404
|
{
|
|
398
405
|
name: 'whatever',
|
|
399
406
|
id: 'an-id4',
|
|
407
|
+
mgmt: { id: 'an-id4' },
|
|
400
408
|
description: 'some-description4',
|
|
401
409
|
nameDisplay: 'some-label'
|
|
402
410
|
},
|
|
@@ -466,7 +474,11 @@ describe('topLevelMenu', () => {
|
|
|
466
474
|
mocks: {
|
|
467
475
|
$store: {
|
|
468
476
|
getters: {
|
|
469
|
-
'management/all': () => [{
|
|
477
|
+
'management/all': () => [{
|
|
478
|
+
id: 'an-id1',
|
|
479
|
+
mgmt: { id: 'an-id1' },
|
|
480
|
+
nameDisplay: 'something else'
|
|
481
|
+
}],
|
|
470
482
|
...defaultStore
|
|
471
483
|
},
|
|
472
484
|
},
|
|
@@ -489,7 +501,12 @@ describe('topLevelMenu', () => {
|
|
|
489
501
|
mocks: {
|
|
490
502
|
$store: {
|
|
491
503
|
getters: {
|
|
492
|
-
'management/all': () => [{
|
|
504
|
+
'management/all': () => [{
|
|
505
|
+
id: 'an-id1',
|
|
506
|
+
mgmt: { id: 'an-id1' },
|
|
507
|
+
nameDisplay: 'something else',
|
|
508
|
+
pinned: true
|
|
509
|
+
}],
|
|
493
510
|
...defaultStore
|
|
494
511
|
},
|
|
495
512
|
},
|
|
@@ -515,7 +532,11 @@ describe('topLevelMenu', () => {
|
|
|
515
532
|
mocks: {
|
|
516
533
|
$store: {
|
|
517
534
|
getters: {
|
|
518
|
-
'management/all': () => [{
|
|
535
|
+
'management/all': () => [{
|
|
536
|
+
id: 'an-id1',
|
|
537
|
+
mgmt: { id: 'an-id1' },
|
|
538
|
+
nameDisplay: search
|
|
539
|
+
}],
|
|
519
540
|
...defaultStore
|
|
520
541
|
},
|
|
521
542
|
},
|
|
@@ -540,7 +561,12 @@ describe('topLevelMenu', () => {
|
|
|
540
561
|
mocks: {
|
|
541
562
|
$store: {
|
|
542
563
|
getters: {
|
|
543
|
-
'management/all': () => [{
|
|
564
|
+
'management/all': () => [{
|
|
565
|
+
nameDisplay: search,
|
|
566
|
+
pinned: true,
|
|
567
|
+
id: 'an-id1',
|
|
568
|
+
mgmt: { id: 'an-id1' },
|
|
569
|
+
}],
|
|
544
570
|
...defaultStore
|
|
545
571
|
},
|
|
546
572
|
},
|
|
@@ -11,6 +11,7 @@ export const CATTLE_PUBLIC_ENDPOINTS = 'field.cattle.io/publicEndpoints';
|
|
|
11
11
|
export const TARGET_WORKLOADS = 'field.cattle.io/targetWorkloadIds';
|
|
12
12
|
export const UI_MANAGED = 'management.cattle.io/ui-managed';
|
|
13
13
|
export const CREATOR_ID = 'field.cattle.io/creatorId';
|
|
14
|
+
export const CREATOR_PRINCIPAL_ID = 'field.cattle.io/creator-principal-name';
|
|
14
15
|
export const RESOURCE_QUOTA = 'field.cattle.io/resourceQuota';
|
|
15
16
|
export const AZURE_MIGRATED = 'auth.cattle.io/azuread-endpoint-migrated';
|
|
16
17
|
export const WORKSPACE_ANNOTATION = 'objectset.rio.cattle.io/id';
|
|
@@ -90,11 +91,12 @@ export const CATALOG = {
|
|
|
90
91
|
_CLUSTER_TPL: 'cluster-template',
|
|
91
92
|
_CLUSTER_TOOL: 'cluster-tool',
|
|
92
93
|
|
|
93
|
-
COMPONENT:
|
|
94
|
-
SOURCE_REPO_TYPE:
|
|
95
|
-
SOURCE_REPO_NAME:
|
|
96
|
-
COLOR:
|
|
97
|
-
DISPLAY_NAME:
|
|
94
|
+
COMPONENT: 'catalog.cattle.io/ui-component',
|
|
95
|
+
SOURCE_REPO_TYPE: 'catalog.cattle.io/ui-source-repo-type',
|
|
96
|
+
SOURCE_REPO_NAME: 'catalog.cattle.io/ui-source-repo',
|
|
97
|
+
COLOR: 'catalog.cattle.io/ui-color',
|
|
98
|
+
DISPLAY_NAME: 'catalog.cattle.io/display-name',
|
|
99
|
+
CLUSTER_REPO_NAME: 'catalog.cattle.io/cluster-repo-name',
|
|
98
100
|
|
|
99
101
|
SUPPORTED_OS: 'catalog.cattle.io/os',
|
|
100
102
|
PERMITTED_OS: 'catalog.cattle.io/permits-os',
|
|
@@ -172,3 +174,5 @@ export const SYSTEM_LABELS = [
|
|
|
172
174
|
'node.kubernetes.io',
|
|
173
175
|
'egress.rke2.io'
|
|
174
176
|
];
|
|
177
|
+
|
|
178
|
+
export const CLOUD_CREDENTIALS = { EXPIRATION: 'rancher.io/expiration-timestamp' };
|
package/core/types.ts
CHANGED
|
@@ -235,7 +235,7 @@ export interface ProductOptions {
|
|
|
235
235
|
/**
|
|
236
236
|
* The route that the product will lead to if click on in navigation.
|
|
237
237
|
*/
|
|
238
|
-
to?:
|
|
238
|
+
to?: PluginRouteRecordRaw;
|
|
239
239
|
|
|
240
240
|
/**
|
|
241
241
|
* Leaving these here for completeness but I don't think these should be advertised as useable to plugin creators.
|
|
@@ -14,7 +14,7 @@ import { MANAGEMENT } from '@shell/config/types';
|
|
|
14
14
|
import { NAME } from '@shell/config/product/explorer';
|
|
15
15
|
import { PROJECT_ID, _VIEW, _CREATE, _EDIT } from '@shell/config/query-params';
|
|
16
16
|
import ProjectMembershipEditor, { canViewProjectMembershipEditor } from '@shell/components/form/Members/ProjectMembershipEditor';
|
|
17
|
-
|
|
17
|
+
import { CREATOR_PRINCIPAL_ID } from '@shell/config/labels-annotations';
|
|
18
18
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
19
19
|
import { Banner } from '@components/Banner';
|
|
20
20
|
|
|
@@ -103,6 +103,9 @@ export default {
|
|
|
103
103
|
this.value.metadata['namespace'] = this.$store.getters['currentCluster'].id;
|
|
104
104
|
this.value['spec'] = this.value.spec || {};
|
|
105
105
|
this.value.spec['containerDefaultResourceLimit'] = this.value.spec.containerDefaultResourceLimit || {};
|
|
106
|
+
if (!this.$store.getters['auth/principalId'].includes('local://')) {
|
|
107
|
+
this.value.metadata.annotations[CREATOR_PRINCIPAL_ID] = this.$store.getters['auth/principalId'];
|
|
108
|
+
}
|
|
106
109
|
},
|
|
107
110
|
methods: {
|
|
108
111
|
async save(saveCb) {
|
|
@@ -86,10 +86,15 @@ export default {
|
|
|
86
86
|
// These aren't explicitly used, but need to be listening for change events
|
|
87
87
|
mgmtClusters: this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER }),
|
|
88
88
|
provClusters: this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER }),
|
|
89
|
-
|
|
90
|
-
catalog: this.$store.dispatch('catalog/load'),
|
|
91
89
|
};
|
|
92
90
|
|
|
91
|
+
// No need to fetch charts when editing an RKE1 cluster
|
|
92
|
+
// The computed property `isRke1` in this file is based on the RKE1/RKE2 toggle, which is not applicable in this case
|
|
93
|
+
// Instead, we should rely on the value from the model: `this.value.isRke1`
|
|
94
|
+
if (!this.value.isRke1 || (this.value.isRke1 && this.mode !== 'edit')) {
|
|
95
|
+
hash['catalog'] = this.$store.dispatch('catalog/load');
|
|
96
|
+
}
|
|
97
|
+
|
|
93
98
|
if (this.$store.getters[`management/canList`](MANAGEMENT.NODE_DRIVER)) {
|
|
94
99
|
hash.nodeDrivers = this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE_DRIVER });
|
|
95
100
|
}
|
|
@@ -42,6 +42,7 @@ import Tabbed from '@shell/components/Tabbed';
|
|
|
42
42
|
import { canViewClusterMembershipEditor } from '@shell/components/form/Members/ClusterMembershipEditor';
|
|
43
43
|
import semver from 'semver';
|
|
44
44
|
|
|
45
|
+
import { CLOUD_CREDENTIAL_OVERRIDE } from '@shell/models/nodedriver';
|
|
45
46
|
import { SETTING } from '@shell/config/settings';
|
|
46
47
|
import { base64Encode } from '@shell/utils/crypto';
|
|
47
48
|
import { CAPI as CAPI_ANNOTATIONS, CLUSTER_BADGE } from '@shell/config/labels-annotations';
|
|
@@ -413,11 +414,22 @@ export default {
|
|
|
413
414
|
},
|
|
414
415
|
|
|
415
416
|
needCredential() {
|
|
416
|
-
|
|
417
|
+
// Check non-provider specific config
|
|
418
|
+
if (
|
|
419
|
+
this.provider === 'custom' ||
|
|
420
|
+
this.provider === 'import' ||
|
|
421
|
+
this.isElementalCluster || // Elemental cluster can make use of `cloud-credential`: false
|
|
422
|
+
this.mode === _VIEW
|
|
423
|
+
) {
|
|
417
424
|
return false;
|
|
418
425
|
}
|
|
419
426
|
|
|
420
|
-
|
|
427
|
+
// Check provider specific config
|
|
428
|
+
if (this.cloudCredentialsOverride === true || this.cloudCredentialsOverride === false) {
|
|
429
|
+
return this.cloudCredentialsOverride;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (this.providerConfig?.spec?.builtin === false && this.providerConfig?.spec?.addCloudCredential === false) {
|
|
421
433
|
return false;
|
|
422
434
|
}
|
|
423
435
|
|
|
@@ -425,10 +437,21 @@ export default {
|
|
|
425
437
|
},
|
|
426
438
|
|
|
427
439
|
/**
|
|
428
|
-
*
|
|
440
|
+
* Override the native way of determining if cloud credentials are required (builtin ++ node driver spec.addCloudCredentials)
|
|
441
|
+
*
|
|
442
|
+
* 1) Override via extensions
|
|
443
|
+
* - `true` or actual component - return true
|
|
444
|
+
* - `false` - return false
|
|
445
|
+
* 2) Override via hardcoded setting
|
|
429
446
|
*/
|
|
430
|
-
|
|
431
|
-
|
|
447
|
+
cloudCredentialsOverride() {
|
|
448
|
+
const cloudCredential = this.$plugin.getDynamic('cloud-credential', this.provider);
|
|
449
|
+
|
|
450
|
+
if (cloudCredential === undefined) {
|
|
451
|
+
return CLOUD_CREDENTIAL_OVERRIDE[this.provider];
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return !!cloudCredential;
|
|
432
455
|
},
|
|
433
456
|
|
|
434
457
|
hasMachinePools() {
|
|
@@ -10,10 +10,11 @@ import { mapFeature, HARVESTER as HARVESTER_FEATURE } from '@shell/store/feature
|
|
|
10
10
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
11
11
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
12
12
|
import { BadgeState } from '@components/BadgeState';
|
|
13
|
+
import CloudCredExpired from '@shell/components/formatter/CloudCredExpired';
|
|
13
14
|
|
|
14
15
|
export default {
|
|
15
16
|
components: {
|
|
16
|
-
Banner, ResourceTable, Masthead, BadgeState
|
|
17
|
+
Banner, ResourceTable, Masthead, BadgeState, CloudCredExpired
|
|
17
18
|
},
|
|
18
19
|
mixins: [ResourceFetch],
|
|
19
20
|
props: {
|
|
@@ -41,6 +42,8 @@ export default {
|
|
|
41
42
|
mgmtClusters: this.$fetchType(MANAGEMENT.CLUSTER),
|
|
42
43
|
};
|
|
43
44
|
|
|
45
|
+
this.$store.dispatch('rancher/findAll', { type: NORMAN.CLOUD_CREDENTIAL });
|
|
46
|
+
|
|
44
47
|
if ( this.$store.getters['management/canList'](SNAPSHOT) ) {
|
|
45
48
|
hash.etcdSnapshots = this.$fetchType(SNAPSHOT);
|
|
46
49
|
}
|
|
@@ -141,17 +144,36 @@ export default {
|
|
|
141
144
|
// This will be used when there's clusters from extension based provisioners
|
|
142
145
|
// We should re-visit this for scaling reasons
|
|
143
146
|
return this.filteredRows.some((c) => c.metadata.namespace !== 'fleet-local' && c.metadata.namespace !== 'fleet-default');
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
tokenExpiredData() {
|
|
150
|
+
const counts = this.rows.reduce((res, provCluster) => {
|
|
151
|
+
const expireData = provCluster.cloudCredential?.expireData;
|
|
152
|
+
|
|
153
|
+
if (expireData?.expiring) {
|
|
154
|
+
res.expiring++;
|
|
155
|
+
}
|
|
156
|
+
if (expireData?.expired) {
|
|
157
|
+
res.expired++;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return res;
|
|
161
|
+
}, {
|
|
162
|
+
expiring: 0,
|
|
163
|
+
expired: 0
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
expiring: counts.expiring ? this.t('cluster.cloudCredentials.banners.expiring', { count: counts.expiring }) : '',
|
|
168
|
+
expired: counts.expired ? this.t('cluster.cloudCredentials.banners.expired', { count: counts.expired }) : '',
|
|
169
|
+
};
|
|
144
170
|
}
|
|
145
171
|
},
|
|
146
172
|
|
|
147
173
|
$loadingResources() {
|
|
148
174
|
// results are filtered so we wouldn't get the correct count on indicator...
|
|
149
175
|
return { loadIndeterminate: true };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
mounted() {
|
|
153
|
-
window.c = this;
|
|
154
|
-
},
|
|
176
|
+
}
|
|
155
177
|
};
|
|
156
178
|
</script>
|
|
157
179
|
|
|
@@ -186,6 +208,17 @@ export default {
|
|
|
186
208
|
</template>
|
|
187
209
|
</Masthead>
|
|
188
210
|
|
|
211
|
+
<Banner
|
|
212
|
+
v-if="tokenExpiredData.expiring"
|
|
213
|
+
color="warning"
|
|
214
|
+
:label="tokenExpiredData.expiring"
|
|
215
|
+
/>
|
|
216
|
+
<Banner
|
|
217
|
+
v-if="tokenExpiredData.expired"
|
|
218
|
+
color="error"
|
|
219
|
+
:label="tokenExpiredData.expired"
|
|
220
|
+
/>
|
|
221
|
+
|
|
189
222
|
<ResourceTable
|
|
190
223
|
:schema="schema"
|
|
191
224
|
:rows="filteredRows"
|
|
@@ -194,6 +227,7 @@ export default {
|
|
|
194
227
|
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
195
228
|
:data-testid="'cluster-list'"
|
|
196
229
|
:force-update-live-and-delayed="forceUpdateLiveAndDelayed"
|
|
230
|
+
:sub-rows="true"
|
|
197
231
|
>
|
|
198
232
|
<!-- Why are state column and subrow overwritten here? -->
|
|
199
233
|
<!-- for rke1 clusters, where they try to use the mgmt cluster stateObj instead of prov cluster stateObj, -->
|
|
@@ -207,19 +241,32 @@ export default {
|
|
|
207
241
|
</template>
|
|
208
242
|
<template #sub-row="{fullColspan, row, keyField, componentTestid, i, onRowMouseEnter, onRowMouseLeave}">
|
|
209
243
|
<tr
|
|
210
|
-
v-if="row.stateDescription"
|
|
211
244
|
:key="row[keyField] + '-description'"
|
|
212
245
|
:data-testid="componentTestid + '-' + i + '-row-description'"
|
|
213
246
|
class="state-description sub-row"
|
|
214
247
|
@mouseenter="onRowMouseEnter"
|
|
215
248
|
@mouseleave="onRowMouseLeave"
|
|
216
249
|
>
|
|
217
|
-
<td
|
|
250
|
+
<td v-if="row.cloudCredentialWarning || row.stateDescription">
|
|
251
|
+
|
|
252
|
+
</td>
|
|
218
253
|
<td
|
|
254
|
+
v-if="row.cloudCredentialWarning || row.stateDescription"
|
|
219
255
|
:colspan="fullColspan - 1"
|
|
220
|
-
:class="{ 'text-error' : row.stateObj.error }"
|
|
221
256
|
>
|
|
222
|
-
|
|
257
|
+
<CloudCredExpired
|
|
258
|
+
v-if="row.cloudCredentialWarning"
|
|
259
|
+
:value="row.cloudCredential.expires"
|
|
260
|
+
:row="row.cloudCredential"
|
|
261
|
+
:verbose="true"
|
|
262
|
+
:class="{'mb-10': row.stateDescription}"
|
|
263
|
+
/>
|
|
264
|
+
<div
|
|
265
|
+
v-if="row.stateDescription"
|
|
266
|
+
:class="{ 'text-error' : row.stateObj.error }"
|
|
267
|
+
>
|
|
268
|
+
{{ row.stateDescription }}
|
|
269
|
+
</div>
|
|
223
270
|
</td>
|
|
224
271
|
</tr>
|
|
225
272
|
</template>
|