@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.
Files changed (64) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/styles/base/_basic.scss +5 -0
  3. package/assets/styles/base/_mixins.scss +8 -0
  4. package/assets/styles/global/_button.scss +5 -0
  5. package/assets/styles/themes/_dark.scss +2 -0
  6. package/assets/styles/themes/_light.scss +2 -0
  7. package/assets/translations/en-us.yaml +27 -11
  8. package/assets/translations/zh-hans.yaml +1 -1
  9. package/chart/monitoring/StorageClassSelector.vue +1 -1
  10. package/components/AssignTo.vue +1 -0
  11. package/components/AsyncButton.vue +1 -0
  12. package/components/BackLink.vue +8 -2
  13. package/components/PaginatedResourceTable.vue +135 -0
  14. package/components/ResourceList/index.vue +0 -1
  15. package/components/ResourceTable.vue +6 -1
  16. package/components/SortableTable/index.vue +8 -6
  17. package/components/Tabbed/index.vue +35 -2
  18. package/components/form/ResourceLabeledSelect.vue +2 -2
  19. package/components/form/ResourceTabs/index.vue +0 -23
  20. package/components/form/Taints.vue +1 -1
  21. package/components/nav/TopLevelMenu.helper.ts +546 -0
  22. package/components/nav/TopLevelMenu.vue +124 -159
  23. package/components/nav/__tests__/TopLevelMenu.test.ts +338 -326
  24. package/config/pagination-table-headers.js +4 -4
  25. package/config/product/explorer.js +2 -0
  26. package/config/router/routes.js +1 -1
  27. package/config/settings.ts +13 -1
  28. package/core/plugin.ts +8 -1
  29. package/core/types-provisioning.ts +5 -0
  30. package/core/types.ts +26 -1
  31. package/dialog/DrainNode.vue +6 -6
  32. package/edit/catalog.cattle.io.clusterrepo.vue +95 -52
  33. package/edit/provisioning.cattle.io.cluster/index.vue +8 -3
  34. package/list/node.vue +8 -5
  35. package/mixins/resource-fetch-api-pagination.js +40 -5
  36. package/mixins/resource-fetch.js +48 -5
  37. package/models/management.cattle.io.nodepool.js +5 -4
  38. package/models/provisioning.cattle.io.cluster.js +2 -10
  39. package/package.json +6 -6
  40. package/pages/about.vue +22 -0
  41. package/pages/c/_cluster/explorer/__tests__/index.test.ts +36 -24
  42. package/pages/c/_cluster/explorer/index.vue +100 -59
  43. package/pages/home.vue +308 -123
  44. package/plugins/dashboard-store/__tests__/mutations.test.ts +2 -0
  45. package/plugins/dashboard-store/actions.js +29 -19
  46. package/plugins/dashboard-store/getters.js +5 -2
  47. package/plugins/dashboard-store/mutations.js +4 -2
  48. package/plugins/steve/__tests__/mutations.test.ts +2 -1
  49. package/plugins/steve/steve-pagination-utils.ts +25 -2
  50. package/plugins/steve/subscribe.js +22 -8
  51. package/scripts/extension/parse-tag-name +2 -0
  52. package/scripts/test-plugins-build.sh +1 -0
  53. package/store/index.js +31 -9
  54. package/tsconfig.json +7 -1
  55. package/types/resources/settings.d.ts +1 -1
  56. package/types/shell/index.d.ts +1107 -1276
  57. package/types/store/dashboard-store.types.ts +4 -0
  58. package/types/store/pagination.types.ts +13 -0
  59. package/types/store/vuex.d.ts +8 -0
  60. package/types/vue-shim.d.ts +6 -31
  61. package/utils/cluster.js +92 -1
  62. package/utils/pagination-utils.ts +17 -8
  63. package/utils/pagination-wrapper.ts +70 -0
  64. 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
+ }
@@ -7,3 +7,11 @@
7
7
  export interface VuexStoreGetters {
8
8
  [name:string]: Function
9
9
  }
10
+
11
+ export interface VuexStore {
12
+ getters: VuexStoreGetters,
13
+ dispatch: any,
14
+
15
+ // When we have exact properties above we can remove below
16
+ [name:string]: any
17
+ }
@@ -1,36 +1,13 @@
1
- // eslint-disable-next-line no-unused-vars
2
- import Vue, { ComponentCustomProperties } from 'vue';
3
- declare module '*.vue' {
4
- export default Vue;
5
- }
1
+ /* eslint-disable */
2
+ import type { DefineComponent } from 'vue'
3
+ import { ComponentCustomProperties } from 'vue';
6
4
 
7
- // This is required to keep typescript from complaining. It is required for
8
- // our i18n plugin. For more info see:
9
- // https://v2.vuejs.org/v2/guide/typescript.html?redirect=true#Augmenting-Types-for-Use-with-Plugins
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
- // Filter out any clusters that are not Kubernetes Clusters
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.includes(enabledFor.resource.id)) {
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;
@@ -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(store: any, chartName: string, opt = { reset: true, force: true }) {
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
- return chart?.versions?.[0]?.version;
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
  /**