From 7e5ad5de3473c3356afe92a85a370f30dc329fee Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 28 Apr 2023 11:09:38 +0100 Subject: [PATCH 01/10] Expand enforced namespace filtering to multiple namespaces and projects > This uses a new endpoint that has yet to merge. See https://github.com/rancher/rancher/issues/40140 WIP - Contains console.warns (via custom logger, can be disabled) - Waiting for final BE endpoint changes to merge - Contains TODOs to resolve on final enpoint changes delivered Pertinent Points - Incompatible with incremental loading / manual refresh - Harder to get counts (need to sum up from different namespaces) - Requires use of new steve pagination - Enforced NS threshold has been removed - The threshold only applies to the primary resource. This has issues when loading a low count primary (daemon sets) which depends on a very high count secondary (pods) - Fixing this would involve knowing all secondary resources a list uses, which isn't currently possible (each resource is requested individually, need to know them all first) - There is no way to subscribe to multiple namespaces (one or all) - We mock this in subscribe by only persisting changes to resources from within target namespaces - Everything should work with Advanced Worker enabled --- pkg/epinio/store/epinio-store/getters.ts | 6 +- shell/assets/translations/en-us.yaml | 16 +-- shell/components/ResourceList/Masthead.vue | 5 - .../ResourceList/ResourceLoadingIndicator.vue | 10 +- shell/components/ResourceList/index.vue | 10 +- shell/components/ResourceTable.vue | 23 +++- shell/components/nav/NamespaceFilter.vue | 108 +++++++++++------- shell/config/settings.ts | 3 +- shell/mixins/resource-fetch-namespaced.js | 42 ++++--- shell/mixins/resource-fetch.js | 7 +- .../pages/c/_cluster/settings/performance.vue | 69 ++++++++--- shell/plugins/dashboard-store/actions.js | 12 +- shell/plugins/dashboard-store/getters.js | 7 ++ shell/plugins/dashboard-store/mutations.js | 3 + shell/plugins/steve/actions.js | 9 +- shell/plugins/steve/getters.js | 10 +- .../projectAndNamespaceFiltering.utils.ts | 71 ++++++++++++ shell/plugins/steve/subscribe.js | 83 +++++++++++++- shell/store/index.js | 31 +---- shell/utils/namespace-filter.js | 22 +++- shell/utils/richards-logger.ts | 18 +++ 21 files changed, 405 insertions(+), 160 deletions(-) create mode 100644 shell/plugins/steve/projectAndNamespaceFiltering.utils.ts create mode 100644 shell/utils/richards-logger.ts diff --git a/pkg/epinio/store/epinio-store/getters.ts b/pkg/epinio/store/epinio-store/getters.ts index 5727b593661..ed8e811fcb9 100644 --- a/pkg/epinio/store/epinio-store/getters.ts +++ b/pkg/epinio/store/epinio-store/getters.ts @@ -1,7 +1,7 @@ import { EPINIO_TYPES } from '../../types'; import { - NAMESPACE_FILTER_SPECIAL as SPECIAL, - NAMESPACE_FILTER_ALL as ALL + NAMESPACE_FILTER_ALL as ALL, + NAMESPACE_FILTER_KINDS } from '@shell/utils/namespace-filter'; export default { @@ -51,7 +51,7 @@ export default { }: any) => { const out = [{ id: ALL, - kind: SPECIAL, + kind: NAMESPACE_FILTER_KINDS.SPECIAL, label: rootGetters['i18n/t']('nav.ns.all'), }]; diff --git a/shell/assets/translations/en-us.yaml b/shell/assets/translations/en-us.yaml index 5d1c04999ef..50ca5adc387 100644 --- a/shell/assets/translations/en-us.yaml +++ b/shell/assets/translations/en-us.yaml @@ -4591,8 +4591,8 @@ resourceList: create: Create createFromYaml: Create from YAML createResource: "Create {resourceName}" - nsFiltering: "There are too many {resource}.
Please filter them by selecting a Namespace above." - nsFilterToolTip: "There are too many resources, filtering is restricted to a single {mode}." + nsFiltering: "There are too many {resource}.
Please filter them by selecting Namespaces / Projects above." + nsFilterToolTip: "There are too many resources, filtering is restricted to projects and namespaces" resourceLoadingIndicator: loading: Loading @@ -6994,6 +6994,7 @@ performance: When enabled, resources will appear more quickly, but it may take slightly longer to load the entire set of resources. This setting only applies to resources that come from the Kubernetes API checkboxLabel: Enable incremental loading inputLabel: Resource Threshold + incompatibleDescription: "Incremental Loading is incomaptible with Namespace/Project filtering. Enabling this will disable it." manualRefresh: label: Manual Refresh setting: You can configure a threshold above which manual refresh will be enabled. @@ -7002,6 +7003,7 @@ performance: When enabled, list data will not auto-update but instead the user must manually trigger a list-view refresh. This setting only applies to resources that come from the Kubernetes API checkboxLabel: Enable manual refresh of data for lists inputLabel: Resource Threshold + incompatibleDescription: "Manual Refresh is incomaptible with Namespace/Project filtering. Enabling this will disable it." websocketNotification: label: Websocket Notifications description: |- @@ -7029,12 +7031,10 @@ performance: description: Resource types must exceed this amount to be considered for garbage collection. inputLabel: Resource Count nsFiltering: - label: Require Namespace Filtering - description: When there are too many resources to show in a list, require the user to select a single namespace and only fetch resources from within it. - checkboxLabel: Enable Required Namespace Filtering - count: - inputLabel: Resource Threshold - description: The threshold above which filtering by a namespace is required + label: Require Namespace / Project Filtering + description: Require the user to select namespaces and/or projects. This restricts the number of resources fetched when viewing lists and should help the responsiveness of the UI in systems with a lot of resources. + checkboxLabel: Enable Required Namespace / Project Filtering + incompatibleDescription: "Required Namespace / Project Filtering is incomaptible with Manual Refresh and Incremental Loading. Enabling this will disable them." advancedWorker: label: Websocket Web Worker description: Updates to resources pushed to the UI come via WebSocket and are handled in the UI thread. Enable this option to handle cluster WebSocket updates in a Web Worker in a separate thread. This should help the responsiveness of the UI in systems where resources change often. diff --git a/shell/components/ResourceList/Masthead.vue b/shell/components/ResourceList/Masthead.vue index c2c5e49d6a4..ce9de88817d 100644 --- a/shell/components/ResourceList/Masthead.vue +++ b/shell/components/ResourceList/Masthead.vue @@ -65,10 +65,6 @@ export default { default: false }, - loadNamespace: { - type: String, - default: null - }, showIncrementalLoadingIndicator: { type: Boolean, @@ -183,7 +179,6 @@ export default { v-if="showIncrementalLoadingIndicator" :resources="loadResources" :indeterminate="loadIndeterminate" - :namespace="loadNamespace" />
diff --git a/shell/components/ResourceList/ResourceLoadingIndicator.vue b/shell/components/ResourceList/ResourceLoadingIndicator.vue index fb2b6c91017..7240cb99b96 100644 --- a/shell/components/ResourceList/ResourceLoadingIndicator.vue +++ b/shell/components/ResourceList/ResourceLoadingIndicator.vue @@ -17,10 +17,6 @@ export default { type: Boolean, default: false, }, - namespace: { - type: String, - default: undefined - }, }, data() { @@ -44,10 +40,6 @@ export default { // Have we loaded all resources for the types that are needed haveAll() { return this.resources.reduce((acc, r) => { - if (this.namespace) { - return acc && this.$store.getters[`${ this.inStore }/haveAllNamespace`](r, this.namespace); - } - return acc && this.$store.getters[`${ this.inStore }/haveAll`](r); }, true); }, @@ -58,7 +50,7 @@ export default { return this.resources.reduce((acc, r) => { const resourceCounts = clusterCounts?.[0]?.counts?.[r]; - const resourceCount = this.namespace ? resourceCounts?.namespaces?.[this.namespace]?.count : resourceCounts?.summary?.count; + const resourceCount = resourceCounts?.summary?.count; const count = resourceCount || 0; return acc + count; diff --git a/shell/components/ResourceList/index.vue b/shell/components/ResourceList/index.vue index 8d556ed82a3..046092573f2 100644 --- a/shell/components/ResourceList/index.vue +++ b/shell/components/ResourceList/index.vue @@ -8,6 +8,7 @@ import IconMessage from '@shell/components/IconMessage.vue'; import { ResourceListComponentName } from './resource-list.config'; import { PanelLocation, ExtensionPoint } from '@shell/core/types'; import ExtensionPanel from '@shell/components/ExtensionPanel'; +import { sameContents } from 'utils/array'; export default { name: ResourceListComponentName, @@ -146,8 +147,12 @@ export default { * * This covers case 1 */ - namespaceFilter(neu) { - if (neu && !this.hasFetch) { + namespaceFilter(neu, old) { + if (sameContents(neu, old)) { + return; + } + + if (neu && !this.hasFetch) { this.$fetchType(this.resource); } } @@ -191,7 +196,6 @@ export default { :show-incremental-loading-indicator="showIncrementalLoadingIndicator" :load-resources="loadResources" :load-indeterminate="loadIndeterminate" - :load-namespace="namespaceFilter" >