@rancher/shell 3.0.1-rc.4 → 3.0.1
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/data/aws-regions.json +1 -0
- package/assets/styles/base/_basic.scss +5 -0
- package/assets/styles/base/_mixins.scss +8 -0
- package/assets/styles/global/_button.scss +5 -0
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +2 -0
- package/assets/translations/en-us.yaml +27 -11
- package/assets/translations/zh-hans.yaml +1 -1
- package/chart/monitoring/StorageClassSelector.vue +1 -1
- package/components/AssignTo.vue +1 -0
- package/components/AsyncButton.vue +1 -0
- package/components/BackLink.vue +8 -2
- package/components/PaginatedResourceTable.vue +135 -0
- package/components/ResourceList/index.vue +0 -1
- package/components/ResourceTable.vue +6 -1
- package/components/SortableTable/index.vue +8 -6
- package/components/Tabbed/index.vue +35 -2
- package/components/form/ResourceLabeledSelect.vue +2 -2
- package/components/form/ResourceTabs/index.vue +0 -23
- package/components/form/Taints.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +546 -0
- package/components/nav/TopLevelMenu.vue +124 -159
- package/components/nav/__tests__/TopLevelMenu.test.ts +338 -326
- package/config/pagination-table-headers.js +4 -4
- package/config/product/explorer.js +2 -0
- package/config/router/routes.js +1 -1
- package/config/settings.ts +13 -1
- package/core/plugin.ts +8 -1
- package/core/types-provisioning.ts +5 -0
- package/core/types.ts +26 -1
- package/dialog/DrainNode.vue +6 -6
- package/edit/catalog.cattle.io.clusterrepo.vue +95 -52
- package/edit/provisioning.cattle.io.cluster/index.vue +8 -3
- package/list/node.vue +8 -5
- package/mixins/resource-fetch-api-pagination.js +40 -5
- package/mixins/resource-fetch.js +48 -5
- package/models/management.cattle.io.nodepool.js +5 -4
- package/models/provisioning.cattle.io.cluster.js +2 -10
- package/package.json +6 -6
- package/pages/about.vue +22 -0
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +36 -24
- package/pages/c/_cluster/explorer/index.vue +100 -59
- package/pages/home.vue +308 -123
- package/plugins/dashboard-store/__tests__/mutations.test.ts +2 -0
- package/plugins/dashboard-store/actions.js +29 -19
- package/plugins/dashboard-store/getters.js +5 -2
- package/plugins/dashboard-store/mutations.js +4 -2
- package/plugins/steve/__tests__/mutations.test.ts +2 -1
- package/plugins/steve/steve-pagination-utils.ts +25 -2
- package/plugins/steve/subscribe.js +22 -8
- package/scripts/extension/parse-tag-name +2 -0
- package/scripts/test-plugins-build.sh +1 -0
- package/store/index.js +31 -9
- package/tsconfig.json +7 -1
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +1107 -1276
- package/types/store/dashboard-store.types.ts +4 -0
- package/types/store/pagination.types.ts +13 -0
- package/types/store/vuex.d.ts +8 -0
- package/types/vue-shim.d.ts +6 -31
- package/utils/cluster.js +92 -1
- package/utils/pagination-utils.ts +17 -8
- package/utils/pagination-wrapper.ts +70 -0
- package/utils/uiplugins.ts +18 -4
|
@@ -38,5 +38,9 @@ export interface ActionFindPageArgs extends ActionCoreFindArgs {
|
|
|
38
38
|
* The single namespace to filter by (used in url path, not part of pagination params)
|
|
39
39
|
*/
|
|
40
40
|
namespaced?: string,
|
|
41
|
+
/**
|
|
42
|
+
* Result of request is transient and not persisted to store
|
|
43
|
+
*/
|
|
44
|
+
transient?: boolean,
|
|
41
45
|
hasManualRefresh?: boolean,
|
|
42
46
|
}
|
|
@@ -455,3 +455,16 @@ export interface StorePagination {
|
|
|
455
455
|
*/
|
|
456
456
|
result: StorePaginationResult
|
|
457
457
|
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* The resource and context that the pagination request will be used
|
|
461
|
+
*
|
|
462
|
+
* Used to determine if the request is supported
|
|
463
|
+
*/
|
|
464
|
+
export interface PaginationResourceContext {
|
|
465
|
+
store: string,
|
|
466
|
+
resource?: {
|
|
467
|
+
id: string,
|
|
468
|
+
context?: string,
|
|
469
|
+
}
|
|
470
|
+
}
|
package/types/store/vuex.d.ts
CHANGED
package/types/vue-shim.d.ts
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export default Vue;
|
|
5
|
-
}
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import type { DefineComponent } from 'vue'
|
|
3
|
+
import { ComponentCustomProperties } from 'vue';
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
declare module 'vue/types/vue' {
|
|
11
|
-
// eslint-disable-next-line no-unused-vars
|
|
12
|
-
interface Vue {
|
|
13
|
-
/**
|
|
14
|
-
* Lookup a given string with the given arguments
|
|
15
|
-
* @param raw if set, do not do HTML escaping.
|
|
16
|
-
*/
|
|
17
|
-
t: {
|
|
18
|
-
(key: string, args?: Record<string, any>, raw?: boolean): string;
|
|
19
|
-
(options: { k: string; raw?: boolean; tag?: string | Record<string, any>; escapehtml?: boolean }): string;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
5
|
+
declare module '*.vue' {
|
|
6
|
+
const component: DefineComponent<{}, {}, any>
|
|
7
|
+
export default component
|
|
22
8
|
}
|
|
23
9
|
|
|
24
10
|
declare module '@vue/runtime-core' {
|
|
25
|
-
// eslint-disable-next-line no-unused-vars
|
|
26
|
-
interface Vue {
|
|
27
|
-
t: {
|
|
28
|
-
(key: string, args?: Record<string, any>, raw?: boolean): string;
|
|
29
|
-
(options: { k: string; raw?: boolean; tag?: string | Record<string, any>; escapehtml?: boolean }): string;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// eslint-disable-next-line no-unused-vars
|
|
34
11
|
interface ComponentCustomProperties {
|
|
35
12
|
t: {
|
|
36
13
|
(key: string, args?: Record<string, any>, raw?: boolean): string;
|
|
@@ -47,5 +24,3 @@ declare module '@vue/runtime-core' {
|
|
|
47
24
|
}
|
|
48
25
|
}
|
|
49
26
|
}
|
|
50
|
-
|
|
51
|
-
declare module 'js-yaml';
|
package/utils/cluster.js
CHANGED
|
@@ -3,8 +3,99 @@ import { camelToTitle } from '@shell/utils/string';
|
|
|
3
3
|
import { CAPI } from '@shell/config/labels-annotations';
|
|
4
4
|
import { MANAGEMENT, VIRTUAL_HARVESTER_PROVIDER } from '@shell/config/types';
|
|
5
5
|
import { SETTING } from '@shell/config/settings';
|
|
6
|
+
import { PaginationFilterField, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Combination of paginationFilterHiddenLocalCluster and paginationFilterOnlyKubernetesClusters
|
|
10
|
+
*
|
|
11
|
+
* @param {*} store
|
|
12
|
+
* @returns PaginationParam[]
|
|
13
|
+
*/
|
|
14
|
+
export function paginationFilterClusters(store, filterMgmtCluster = true) {
|
|
15
|
+
const paginationRequestFilters = [];
|
|
16
|
+
|
|
17
|
+
// Commenting out for the moment. This is broken for non-paginated world
|
|
18
|
+
// filterOnlyKubernetesClusters expects a mgmt cluster, however in the home page it's given a prov cluster
|
|
19
|
+
// note - filterHiddenLocalCluster works because it uses model isLocal which is on both cluster types
|
|
20
|
+
// const pFilterOnlyKubernetesClusters = paginationFilterOnlyKubernetesClusters(store);
|
|
21
|
+
// if (pFilterOnlyKubernetesClusters) {
|
|
22
|
+
// paginationRequestFilters.push(pFilterOnlyKubernetesClusters);
|
|
23
|
+
// }
|
|
24
|
+
const pFilterHiddenLocalCluster = paginationFilterHiddenLocalCluster(store, filterMgmtCluster);
|
|
25
|
+
|
|
26
|
+
if (pFilterHiddenLocalCluster) {
|
|
27
|
+
paginationRequestFilters.push(pFilterHiddenLocalCluster);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return paginationRequestFilters;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The vai backed api's `filter` equivalent of `filterHiddenLocalCluster`
|
|
35
|
+
*
|
|
36
|
+
* @export
|
|
37
|
+
* @param {*} store
|
|
38
|
+
* @returns PaginationParam | null
|
|
39
|
+
*/
|
|
40
|
+
export function paginationFilterHiddenLocalCluster(store, filterMgmtCluster = true) {
|
|
41
|
+
const hideLocalSetting = store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.HIDE_LOCAL_CLUSTER) || {};
|
|
42
|
+
const value = hideLocalSetting.value || hideLocalSetting.default || 'false';
|
|
43
|
+
const hideLocal = value === 'true';
|
|
44
|
+
|
|
45
|
+
if (!hideLocal) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const filter = filterMgmtCluster ? [
|
|
50
|
+
new PaginationFilterField({
|
|
51
|
+
field: `spec.internal`,
|
|
52
|
+
value: false,
|
|
53
|
+
})
|
|
54
|
+
] : [
|
|
55
|
+
new PaginationFilterField({
|
|
56
|
+
field: `id`,
|
|
57
|
+
value: 'fleet-local/local',
|
|
58
|
+
exact: true,
|
|
59
|
+
equals: false,
|
|
60
|
+
})
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
return PaginationParamFilter.createMultipleFields(filter);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The vai backed api's `filter` equivalent of `filterOnlyKubernetesClusters`
|
|
68
|
+
*
|
|
69
|
+
* @export
|
|
70
|
+
* @param {*} store
|
|
71
|
+
* @returns PaginationParam | null
|
|
72
|
+
*/
|
|
73
|
+
export function paginationFilterOnlyKubernetesClusters(store) {
|
|
74
|
+
const openHarvesterContainerWorkload = store.getters['features/get']('harvester-baremetal-container-workload');
|
|
75
|
+
|
|
76
|
+
if (!openHarvesterContainerWorkload) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return PaginationParamFilter.createMultipleFields([
|
|
81
|
+
new PaginationFilterField({
|
|
82
|
+
field: `metadata.labels."${ CAPI.PROVIDER }"`, // Pending API Support - https://github.com/rancher/rancher/issues/48256
|
|
83
|
+
equals: false,
|
|
84
|
+
value: VIRTUAL_HARVESTER_PROVIDER,
|
|
85
|
+
exact: true
|
|
86
|
+
}),
|
|
87
|
+
new PaginationFilterField({
|
|
88
|
+
field: `status.provider`, // Pending API Support - https://github.com/rancher/rancher/issues/48256
|
|
89
|
+
equals: false,
|
|
90
|
+
value: VIRTUAL_HARVESTER_PROVIDER,
|
|
91
|
+
exact: true
|
|
92
|
+
}),
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Filter out any clusters that are not Kubernetes Clusters
|
|
98
|
+
**/
|
|
8
99
|
export function filterOnlyKubernetesClusters(mgmtClusters, store) {
|
|
9
100
|
const openHarvesterContainerWorkload = store.getters['features/get']('harvester-baremetal-container-workload');
|
|
10
101
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
NAMESPACE_FILTER_NS_FULL_PREFIX,
|
|
10
10
|
NAMESPACE_FILTER_P_FULL_PREFIX,
|
|
11
11
|
} from '@shell/utils/namespace-filter';
|
|
12
|
-
import { PaginationArgs, PaginationParam, PaginationSort } from '@shell/types/store/pagination.types';
|
|
12
|
+
import { PaginationArgs, PaginationResourceContext, PaginationParam, PaginationSort } from '@shell/types/store/pagination.types';
|
|
13
13
|
import { sameArrayObjects } from '@shell/utils/array';
|
|
14
14
|
import { isEqual } from '@shell/utils/object';
|
|
15
15
|
import { STEVE_CACHE } from '@shell/store/features';
|
|
@@ -40,12 +40,7 @@ class PaginationUtils {
|
|
|
40
40
|
/**
|
|
41
41
|
* Is pagination enabled at a global level or for a specific resource
|
|
42
42
|
*/
|
|
43
|
-
isEnabled({ rootGetters }: any, enabledFor: {
|
|
44
|
-
store: string,
|
|
45
|
-
resource?: {
|
|
46
|
-
id: string,
|
|
47
|
-
}
|
|
48
|
-
}) {
|
|
43
|
+
isEnabled({ rootGetters }: any, enabledFor: PaginationResourceContext) {
|
|
49
44
|
// Cache must be enabled to support pagination api
|
|
50
45
|
if (!this.isSteveCacheEnabled({ rootGetters })) {
|
|
51
46
|
return false;
|
|
@@ -95,7 +90,21 @@ class PaginationUtils {
|
|
|
95
90
|
return true;
|
|
96
91
|
}
|
|
97
92
|
|
|
98
|
-
if (storeSettings.resources.enableSome.enabled.
|
|
93
|
+
if (storeSettings.resources.enableSome.enabled.find((setting) => {
|
|
94
|
+
if (typeof setting === 'string') {
|
|
95
|
+
return setting === enabledFor.resource?.id;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (setting.resource === enabledFor.resource?.id) {
|
|
99
|
+
if (!!setting.context) {
|
|
100
|
+
return enabledFor.resource?.context ? setting.context.includes(enabledFor.resource.context) : false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return false;
|
|
107
|
+
})) {
|
|
99
108
|
return true;
|
|
100
109
|
}
|
|
101
110
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import paginationUtils from '@shell/utils/pagination-utils';
|
|
2
|
+
import { PaginationArgs, PaginationResourceContext, StorePagination } from '@shell/types/store/pagination.types';
|
|
3
|
+
import { VuexStore } from '@shell/types/store/vuex';
|
|
4
|
+
import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
|
|
5
|
+
|
|
6
|
+
interface Result<T> {
|
|
7
|
+
data: Array<T>
|
|
8
|
+
pagination: StorePagination
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This is a helper class that will assist in fetching a resource
|
|
13
|
+
* - Handle if the resource can be fetched by the new pagination api
|
|
14
|
+
* - Make a request to get a page (including classify)
|
|
15
|
+
* - Provide updates when the resource changes
|
|
16
|
+
*
|
|
17
|
+
* This is designed to work in places where we don't/can't store the resource in the store
|
|
18
|
+
* - There already exists a resource we don't want to overwrite
|
|
19
|
+
* - We're transient and want something nicer than just cluster/request
|
|
20
|
+
*/
|
|
21
|
+
class PaginationWrapper<T = any> {
|
|
22
|
+
private $store: VuexStore;
|
|
23
|
+
private enabledFor: PaginationResourceContext;
|
|
24
|
+
|
|
25
|
+
// Blocked on https://github.com/rancher/rancher/issues/40773 / https://github.com/rancher/dashboard/issues/12734
|
|
26
|
+
private onUpdate: (out: Result<T>) => void;
|
|
27
|
+
|
|
28
|
+
public isEnabled: boolean;
|
|
29
|
+
|
|
30
|
+
constructor({
|
|
31
|
+
$store,
|
|
32
|
+
enabledFor,
|
|
33
|
+
onUpdate,
|
|
34
|
+
}: {
|
|
35
|
+
$store: VuexStore,
|
|
36
|
+
onUpdate: (res: Result<T>) => void,
|
|
37
|
+
enabledFor: PaginationResourceContext,
|
|
38
|
+
}) {
|
|
39
|
+
this.$store = $store;
|
|
40
|
+
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters }, enabledFor);
|
|
41
|
+
this.enabledFor = enabledFor;
|
|
42
|
+
this.onUpdate = onUpdate;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async request(args: {
|
|
46
|
+
pagination: PaginationArgs,
|
|
47
|
+
classify?: boolean,
|
|
48
|
+
}): Promise<Result<T>> {
|
|
49
|
+
if (!this.isEnabled) {
|
|
50
|
+
throw new Error(`Wrapper for type '${ this.enabledFor.store }/${ this.enabledFor.resource?.id }' in context '${ this.enabledFor.resource?.context }' not supported`);
|
|
51
|
+
}
|
|
52
|
+
const { pagination, classify: doClassify } = args;
|
|
53
|
+
const opt: ActionFindPageArgs = {
|
|
54
|
+
transient: true,
|
|
55
|
+
pagination
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const out: Result<T> = await this.$store.dispatch(`${ this.enabledFor.store }/findPage`, { opt, type: this.enabledFor.resource?.id });
|
|
59
|
+
|
|
60
|
+
if (doClassify) {
|
|
61
|
+
for (let i = 0; i < out.data.length; i++) {
|
|
62
|
+
out.data[i] = await this.$store.dispatch(`${ this.enabledFor.store }/create`, out.data[i]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default PaginationWrapper;
|
package/utils/uiplugins.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
2
2
|
import { CATALOG } from '@shell/config/types';
|
|
3
|
-
import { UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
|
|
3
|
+
import { UI_PLUGIN_BASE_URL, isSupportedChartVersion } from '@shell/config/uiplugins';
|
|
4
4
|
|
|
5
5
|
const MAX_RETRIES = 10;
|
|
6
6
|
const RETRY_WAIT = 2500;
|
|
@@ -13,15 +13,29 @@ export type HelmChart = any;
|
|
|
13
13
|
*
|
|
14
14
|
* @param store Vue store
|
|
15
15
|
* @param chartName The chartName
|
|
16
|
+
* @param rancherVersion Rancher version
|
|
17
|
+
* @param kubeVersion K8s version
|
|
16
18
|
* @param opt Store options
|
|
17
|
-
* @returns The latest compatible version of the extension
|
|
19
|
+
* @returns The latest compatible version of the extension; return null If there are no compatible versions.
|
|
18
20
|
*/
|
|
19
|
-
export async function getLatestExtensionVersion(
|
|
21
|
+
export async function getLatestExtensionVersion(
|
|
22
|
+
store: any,
|
|
23
|
+
chartName: string,
|
|
24
|
+
rancherVersion: string,
|
|
25
|
+
kubeVersion: string,
|
|
26
|
+
opt = { reset: true, force: true },
|
|
27
|
+
) {
|
|
20
28
|
await store.dispatch('catalog/load', opt);
|
|
21
29
|
|
|
22
30
|
const chart = store.getters['catalog/chart']({ chartName });
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
const versions = chart?.versions || [];
|
|
33
|
+
|
|
34
|
+
const compatibleVersions = versions.filter((version: any) => isSupportedChartVersion({
|
|
35
|
+
version, rancherVersion, kubeVersion
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
return compatibleVersions[0]?.version;
|
|
25
39
|
}
|
|
26
40
|
|
|
27
41
|
/**
|