@rancher/shell 3.0.6 → 3.0.7
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/images/pl/dark/rancher-logo.svg +131 -44
- package/assets/images/pl/rancher-logo.svg +120 -44
- package/assets/styles/base/_basic.scss +2 -2
- package/assets/styles/base/_color-classic.scss +51 -0
- package/assets/styles/base/_color.scss +3 -3
- package/assets/styles/base/_mixins.scss +1 -1
- package/assets/styles/base/_variables-classic.scss +47 -0
- package/assets/styles/global/_button.scss +49 -17
- package/assets/styles/global/_form.scss +1 -1
- package/assets/styles/themes/_dark.scss +4 -0
- package/assets/styles/themes/_light.scss +3 -69
- package/assets/styles/themes/_modern.scss +194 -50
- package/assets/styles/vendor/vue-select.scss +1 -2
- package/assets/translations/en-us.yaml +33 -21
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/CodeMirror.vue +1 -1
- package/components/IconOrSvg.vue +40 -29
- package/components/ResourceDetail/index.vue +1 -0
- package/components/SortableTable/sorting.js +3 -1
- package/components/Tabbed/index.vue +5 -5
- package/components/form/ResourceTabs/index.vue +37 -18
- package/components/form/SecretSelector.vue +6 -2
- package/components/nav/Group.vue +29 -9
- package/components/nav/Header.vue +6 -8
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +47 -20
- package/components/nav/TopLevelMenu.vue +44 -14
- package/components/nav/Type.vue +0 -5
- package/components/nav/__tests__/TopLevelMenu.test.ts +2 -0
- package/config/pagination-table-headers.js +10 -2
- package/config/product/explorer.js +4 -3
- package/config/table-headers.js +9 -0
- package/core/plugin.ts +18 -6
- package/core/types.ts +8 -0
- package/detail/provisioning.cattle.io.cluster.vue +1 -0
- package/dialog/InstallExtensionDialog.vue +71 -45
- package/dialog/UninstallExtensionDialog.vue +2 -1
- package/dialog/__tests__/InstallExtensionDialog.test.ts +111 -0
- package/edit/auth/oidc.vue +86 -16
- package/mixins/__tests__/chart.test.ts +1 -1
- package/mixins/chart.js +1 -1
- package/models/event.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +9 -0
- package/package.json +1 -1
- package/pages/c/_cluster/explorer/EventsTable.vue +3 -6
- package/pages/c/_cluster/settings/performance.vue +1 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +159 -62
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +102 -0
- package/pages/c/_cluster/uiplugins/__tests__/{index.spec.ts → index.test.ts} +121 -55
- package/pages/c/_cluster/uiplugins/index.vue +110 -94
- package/plugins/__tests__/subscribe.events.test.ts +194 -0
- package/plugins/dashboard-store/actions.js +3 -0
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/resource-class.js +3 -3
- package/plugins/steve/__tests__/subscribe.spec.ts +27 -24
- package/plugins/steve/index.js +18 -10
- package/plugins/steve/mutations.js +2 -2
- package/plugins/steve/resourceWatcher.js +2 -2
- package/plugins/steve/steve-pagination-utils.ts +12 -9
- package/plugins/steve/subscribe.js +113 -85
- package/plugins/subscribe-events.ts +211 -0
- package/rancher-components/BadgeState/BadgeState.vue +8 -6
- package/rancher-components/Banner/Banner.vue +2 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
- package/rancher-components/Form/Radio/RadioButton.vue +3 -3
- package/store/index.js +12 -22
- package/types/extension-manager.ts +8 -1
- package/types/resources/settings.d.ts +24 -17
- package/types/shell/index.d.ts +352 -335
- package/types/store/subscribe-events.types.ts +70 -0
- package/types/store/subscribe.types.ts +6 -22
- package/utils/pagination-utils.ts +87 -28
- package/utils/pagination-wrapper.ts +6 -8
- package/utils/sort.js +5 -0
- package/utils/unit-tests/pagination-utils.spec.ts +283 -0
- package/utils/validators/formRules/__tests__/index.test.ts +7 -0
- package/utils/validators/formRules/index.ts +2 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { shallowMount, VueWrapper } from '@vue/test-utils';
|
|
2
|
+
import InstallExtensionDialog from '@shell/dialog/InstallExtensionDialog.vue';
|
|
3
|
+
|
|
4
|
+
jest.mock('@shell/config/uiplugins', () => ({
|
|
5
|
+
...jest.requireActual('@shell/config/uiplugins'),
|
|
6
|
+
isChartVersionHigher: jest.fn((v1: string, v2: string) => v1 > v2),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
const t = (key: string): string => key;
|
|
10
|
+
|
|
11
|
+
describe('component: InstallExtensionDialog', () => {
|
|
12
|
+
let wrapper: VueWrapper<any>;
|
|
13
|
+
|
|
14
|
+
const mountComponent = (propsData = {}) => {
|
|
15
|
+
const store = { dispatch: () => Promise.resolve() };
|
|
16
|
+
|
|
17
|
+
const defaultProps = {
|
|
18
|
+
plugin: { installableVersions: [] },
|
|
19
|
+
action: 'install',
|
|
20
|
+
updateStatus: jest.fn(),
|
|
21
|
+
closed: jest.fn(),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return shallowMount(InstallExtensionDialog, {
|
|
25
|
+
propsData: {
|
|
26
|
+
...defaultProps,
|
|
27
|
+
...propsData,
|
|
28
|
+
},
|
|
29
|
+
global: {
|
|
30
|
+
mocks: {
|
|
31
|
+
$store: store,
|
|
32
|
+
t,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
describe('fetch', () => {
|
|
39
|
+
it('should set currentVersion if plugin is installed', async() => {
|
|
40
|
+
wrapper = mountComponent({ plugin: { installed: true, installedVersion: '1.0.0' } });
|
|
41
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
42
|
+
expect(wrapper.vm.currentVersion).toBe('1.0.0');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should set version from initialVersion if provided', async() => {
|
|
46
|
+
wrapper = mountComponent({ initialVersion: '1.2.3', plugin: { installed: false } });
|
|
47
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
48
|
+
expect(wrapper.vm.version).toBe('1.2.3');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should set version to latest for upgrade action', async() => {
|
|
52
|
+
const plugin = { installableVersions: [{ version: '1.1.0' }, { version: '1.0.0' }] };
|
|
53
|
+
|
|
54
|
+
wrapper = mountComponent({ plugin, action: 'upgrade' });
|
|
55
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
56
|
+
expect(wrapper.vm.version).toBe('1.1.0');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should set version to next oldest for downgrade action', async() => {
|
|
60
|
+
const plugin = {
|
|
61
|
+
installed: true,
|
|
62
|
+
installedVersion: '1.1.0',
|
|
63
|
+
installableVersions: [{ version: '1.1.0' }, { version: '1.0.0' }]
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
wrapper = mountComponent({ plugin, action: 'downgrade' });
|
|
67
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
68
|
+
expect(wrapper.vm.version).toBe('1.0.0');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('versionOptions', () => {
|
|
73
|
+
it('should include and disable the current version', () => {
|
|
74
|
+
const plugin = {
|
|
75
|
+
installableVersions: [
|
|
76
|
+
{ version: '1.1.0' },
|
|
77
|
+
{ version: '1.0.0' },
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
wrapper = mountComponent({ plugin });
|
|
82
|
+
wrapper.vm.currentVersion = '1.0.0';
|
|
83
|
+
|
|
84
|
+
const options = wrapper.vm.versionOptions;
|
|
85
|
+
const currentOption = options.find((o: any) => o.value === '1.0.0');
|
|
86
|
+
|
|
87
|
+
expect(currentOption).toBeDefined();
|
|
88
|
+
expect(currentOption.disabled).toBe(true);
|
|
89
|
+
expect(currentOption.label).toContain('(plugins.labels.current)');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('buttonMode', () => {
|
|
94
|
+
beforeEach(() => {
|
|
95
|
+
wrapper = mountComponent({ action: 'upgrade' });
|
|
96
|
+
wrapper.vm.currentVersion = '1.0.0';
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should be "upgrade" if selected version is higher', async() => {
|
|
100
|
+
wrapper.vm.version = '1.1.0';
|
|
101
|
+
await wrapper.vm.$nextTick();
|
|
102
|
+
expect(wrapper.vm.buttonMode).toBe('upgrade');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should be "downgrade" if selected version is lower', async() => {
|
|
106
|
+
wrapper.vm.version = '0.9.0';
|
|
107
|
+
await wrapper.vm.$nextTick();
|
|
108
|
+
expect(wrapper.vm.buttonMode).toBe('downgrade');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
package/edit/auth/oidc.vue
CHANGED
|
@@ -59,11 +59,16 @@ export default {
|
|
|
59
59
|
userInfoEndpoint: null,
|
|
60
60
|
},
|
|
61
61
|
// TODO #13457: this is duplicated due wrong format
|
|
62
|
-
oidcScope:
|
|
63
|
-
SLO_OPTION_VALUES
|
|
62
|
+
oidcScope: [],
|
|
63
|
+
SLO_OPTION_VALUES,
|
|
64
|
+
addCustomClaims: false,
|
|
64
65
|
};
|
|
65
66
|
},
|
|
66
67
|
|
|
68
|
+
created() {
|
|
69
|
+
this.registerBeforeHook(this.willSave, 'willSave');
|
|
70
|
+
},
|
|
71
|
+
|
|
67
72
|
computed: {
|
|
68
73
|
tArgs() {
|
|
69
74
|
return {
|
|
@@ -140,6 +145,10 @@ export default {
|
|
|
140
145
|
return this.model?.id === 'cognito';
|
|
141
146
|
},
|
|
142
147
|
|
|
148
|
+
isGenericOidc() {
|
|
149
|
+
return this.model?.id === 'genericoidc';
|
|
150
|
+
},
|
|
151
|
+
|
|
143
152
|
isLogoutAllSupported() {
|
|
144
153
|
return this.model?.logoutAllSupported;
|
|
145
154
|
},
|
|
@@ -220,6 +229,15 @@ export default {
|
|
|
220
229
|
this.model.logoutAllForced = false;
|
|
221
230
|
break;
|
|
222
231
|
}
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
model: {
|
|
235
|
+
handler(newVal) {
|
|
236
|
+
if (newVal?.nameClaim || newVal?.groupsClaim || newVal?.emailClaim) {
|
|
237
|
+
this.addCustomClaims = true;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
once: true
|
|
223
241
|
}
|
|
224
242
|
},
|
|
225
243
|
|
|
@@ -248,6 +266,14 @@ export default {
|
|
|
248
266
|
|
|
249
267
|
updateScope() {
|
|
250
268
|
this.model.scope = this.oidcScope.join(' ');
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
willSave() {
|
|
272
|
+
if (this.isGenericOidc && !this.addCustomClaims) {
|
|
273
|
+
this.model.nameClaim = undefined;
|
|
274
|
+
this.model.groupsClaim = undefined;
|
|
275
|
+
this.model.emailClaim = undefined;
|
|
276
|
+
}
|
|
251
277
|
}
|
|
252
278
|
}
|
|
253
279
|
};
|
|
@@ -390,21 +416,60 @@ export default {
|
|
|
390
416
|
</div>
|
|
391
417
|
</div>
|
|
392
418
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
419
|
+
<template v-if="isGenericOidc || supportsGroupSearch">
|
|
420
|
+
<div
|
|
421
|
+
class="row mb-20"
|
|
422
|
+
>
|
|
423
|
+
<div class="col span-6 checkbox-flex">
|
|
424
|
+
<!-- Allow group search -->
|
|
425
|
+
<Checkbox
|
|
426
|
+
v-if="supportsGroupSearch"
|
|
427
|
+
v-model:value="model.groupSearchEnabled"
|
|
428
|
+
data-testid="input-group-search"
|
|
429
|
+
:label="t('authConfig.oidc.groupSearch.label')"
|
|
430
|
+
:tooltip="t('authConfig.oidc.groupSearch.tooltip')"
|
|
431
|
+
:mode="mode"
|
|
432
|
+
/>
|
|
433
|
+
<Checkbox
|
|
434
|
+
v-if="isGenericOidc"
|
|
435
|
+
v-model:value="addCustomClaims"
|
|
436
|
+
data-testid="input-add-custom-claims"
|
|
437
|
+
:label="t('authConfig.oidc.customClaims.enable.label')"
|
|
438
|
+
:tooltip="t('authConfig.oidc.customClaims.enable.tooltip')"
|
|
439
|
+
:mode="mode"
|
|
440
|
+
/>
|
|
441
|
+
</div>
|
|
406
442
|
</div>
|
|
407
|
-
</
|
|
443
|
+
</template>
|
|
444
|
+
|
|
445
|
+
<template v-if="addCustomClaims">
|
|
446
|
+
<h4>{{ t('authConfig.oidc.customClaims.label') }}</h4>
|
|
447
|
+
<div class="row mb-20">
|
|
448
|
+
<div class="col span-6">
|
|
449
|
+
<LabeledInput
|
|
450
|
+
v-model:value="model.nameClaim"
|
|
451
|
+
:label="t(`authConfig.oidc.customClaims.nameClaim.label`)"
|
|
452
|
+
:mode="mode"
|
|
453
|
+
/>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="col span-6">
|
|
456
|
+
<LabeledInput
|
|
457
|
+
v-model:value="model.groupsClaim"
|
|
458
|
+
:label="t(`authConfig.oidc.customClaims.groupsClaim.label`)"
|
|
459
|
+
:mode="mode"
|
|
460
|
+
/>
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
<div class="row mb-20">
|
|
464
|
+
<div class="col span-6">
|
|
465
|
+
<LabeledInput
|
|
466
|
+
v-model:value="model.emailClaim"
|
|
467
|
+
:label="t(`authConfig.oidc.customClaims.emailClaim.label`)"
|
|
468
|
+
:mode="mode"
|
|
469
|
+
/>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
</template>
|
|
408
473
|
|
|
409
474
|
<!-- Scopes -->
|
|
410
475
|
<div class="row mb-20">
|
|
@@ -608,4 +673,9 @@ export default {
|
|
|
608
673
|
margin: 0 3px;
|
|
609
674
|
}
|
|
610
675
|
}
|
|
676
|
+
|
|
677
|
+
.checkbox-flex {
|
|
678
|
+
display: flex;
|
|
679
|
+
flex-direction: column;
|
|
680
|
+
}
|
|
611
681
|
</style>
|
package/mixins/chart.js
CHANGED
package/models/event.js
CHANGED
|
@@ -25,6 +25,13 @@ export default class K8sEvent extends SteveModel {
|
|
|
25
25
|
return this._type;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
get firstSeen() {
|
|
29
|
+
const schema = this.$getters['schemaFor'](this.type);
|
|
30
|
+
const rowValueGetter = this.$rootGetters['type-map/rowValueGetter'];
|
|
31
|
+
|
|
32
|
+
return schema && rowValueGetter ? rowValueGetter(schema, 'First Seen')(this) : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
get lastSeen() {
|
|
29
36
|
const schema = this.$getters['schemaFor'](this.type);
|
|
30
37
|
const rowValueGetter = this.$rootGetters['type-map/rowValueGetter'];
|
|
@@ -391,6 +391,15 @@ export default class ProvCluster extends SteveModel {
|
|
|
391
391
|
const pCluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, this.id);
|
|
392
392
|
const name = this.status?.clusterName || pCluster?.status?.clusterName;
|
|
393
393
|
|
|
394
|
+
try {
|
|
395
|
+
if (name) {
|
|
396
|
+
// Just in case we're not generically watching all mgmt clusters and...
|
|
397
|
+
// thus won't receive new mgmt cluster over socket...
|
|
398
|
+
// fire and forget a request to fetch it (this won't make multiple requests if one is already running)
|
|
399
|
+
this.$dispatch('find', { type: MANAGEMENT.CLUSTER, id: name });
|
|
400
|
+
}
|
|
401
|
+
} catch {}
|
|
402
|
+
|
|
394
403
|
return name && !!this.$rootGetters['management/byId'](MANAGEMENT.CLUSTER, name);
|
|
395
404
|
}, this.$rootGetters['i18n/t']('cluster.managementTimeout'), timeout, interval);
|
|
396
405
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { MESSAGE, NAME, OBJECT, REASON } from '@shell/config/table-headers';
|
|
4
4
|
import { EVENT } from '@shell/config/types';
|
|
5
5
|
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
|
|
6
|
-
import { STEVE_EVENT_OBJECT, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
|
|
6
|
+
import { STEVE_EVENT_FIRST_SEEN, STEVE_EVENT_LAST_SEEN, STEVE_EVENT_OBJECT, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
|
|
7
7
|
import { headerFromSchemaColString } from '@shell/store/type-map.utils';
|
|
8
8
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
9
9
|
|
|
@@ -59,11 +59,8 @@ export default {
|
|
|
59
59
|
...STEVE_NAME_COL,
|
|
60
60
|
defaultSort: false,
|
|
61
61
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
...headerFromSchemaColString('Last Seen', schema, this.$store.getters, true),
|
|
65
|
-
defaultSort: true,
|
|
66
|
-
},
|
|
62
|
+
STEVE_EVENT_FIRST_SEEN,
|
|
63
|
+
STEVE_EVENT_LAST_SEEN,
|
|
67
64
|
headerFromSchemaColString('Count', schema, this.$store.getters, true),
|
|
68
65
|
] : [];
|
|
69
66
|
|
|
@@ -105,7 +105,7 @@ export default {
|
|
|
105
105
|
if (settings.resources.enableAll) {
|
|
106
106
|
resources.push(this.t('performance.serverPagination.resources.all'));
|
|
107
107
|
} else {
|
|
108
|
-
settings.resources.enableSome.enabled
|
|
108
|
+
settings.resources.enableSome.enabled?.forEach((resource) => {
|
|
109
109
|
resources.push(!!resource.length ? resource : `${ resource.resource } (${ resource.context })`);
|
|
110
110
|
});
|
|
111
111
|
if (settings.resources.enableSome.generic) {
|