@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.4
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/apis/impl/apis.ts +6 -0
- package/apis/index.ts +26 -0
- package/apis/intf/resources-api/cluster-api.ts +18 -0
- package/apis/intf/resources-api/mgmt-api.ts +15 -0
- package/apis/intf/resources-api/resource-base.ts +107 -0
- package/apis/intf/resources-api/resource-constants.ts +147 -0
- package/apis/intf/resources-api/resources-api.ts +143 -0
- package/apis/intf/resources.ts +49 -0
- package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
- package/apis/intf/shell-api/proxy.ts +216 -0
- package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
- package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
- package/apis/intf/shell.ts +12 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
- package/apis/resources/index.ts +22 -0
- package/apis/resources/resources-api-class.ts +187 -0
- package/apis/shell/__tests__/proxy.test.ts +369 -0
- package/apis/shell/index.ts +8 -1
- package/apis/shell/modal.ts +4 -1
- package/apis/shell/notifications.ts +9 -6
- package/apis/shell/proxy.ts +256 -0
- package/apis/shell/slide-in.ts +4 -1
- package/apis/vue-shim.d.ts +2 -1
- package/assets/data/aws-regions.json +4 -0
- package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/fonts/_fontstack.scss +132 -8
- package/assets/styles/global/_layout.scss +4 -0
- package/assets/translations/en-us.yaml +165 -45
- package/assets/translations/zh-hans.yaml +1 -7
- package/chart/monitoring/ClusterSelector.vue +0 -21
- package/chart/monitoring/index.vue +10 -1
- package/chart/monitoring/prometheus/index.vue +6 -3
- package/components/ActionDropdownShell.vue +2 -1
- package/components/CruResource.vue +161 -14
- package/components/CruResourceFooter.vue +9 -5
- package/components/ExplorerMembers.vue +8 -4
- package/components/ExplorerProjectsNamespaces.vue +11 -7
- package/components/GrowlManager.vue +4 -0
- package/components/InstallHelmCharts.vue +2 -2
- package/components/LandingPagePreference.vue +14 -5
- package/components/MgmtNodeList.vue +184 -0
- package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
- package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
- package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
- package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +17 -1
- package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
- package/components/Resource/Detail/Metadata/index.vue +6 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
- package/components/Resource/Detail/SpacedRow.vue +3 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -11
- package/components/ResourceDetail/index.vue +1 -1
- package/components/ResourceList/Masthead.vue +19 -9
- package/components/ResourceList/index.vue +82 -1
- package/components/RichTranslation.vue +5 -2
- package/components/SelectIconGrid.vue +0 -10
- package/components/Setting.vue +1 -0
- package/components/SingleClusterInfo.vue +1 -0
- package/components/SortableTable/__tests__/sorting.test.ts +126 -0
- package/components/SortableTable/index.vue +6 -9
- package/components/SortableTable/selection.js +23 -5
- package/components/SortableTable/sorting.js +6 -3
- package/components/SubtleLink.vue +31 -6
- package/components/Tabbed/Tab.vue +29 -3
- package/components/Tabbed/index.vue +25 -3
- package/components/TableOfContents/TableOfContents.vue +109 -0
- package/components/TableOfContents/composables.ts +258 -0
- package/components/Window/ContainerShell.vue +21 -11
- package/components/Window/__tests__/ContainerShell.test.ts +107 -37
- package/components/Wizard.vue +23 -17
- package/components/fleet/AppCoChartGrid.vue +401 -0
- package/components/fleet/AppCoEmptyState.vue +127 -0
- package/components/fleet/AppCoPageHeader.vue +119 -0
- package/components/fleet/AppCoVersionSelect.vue +70 -0
- package/components/fleet/FleetBundles.vue +100 -12
- package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
- package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
- package/components/fleet/FleetClusterTargets/index.vue +226 -161
- package/components/fleet/FleetIntro.vue +7 -3
- package/components/fleet/FleetNoWorkspaces.vue +7 -3
- package/components/fleet/FleetSecretSelector.vue +5 -3
- package/components/fleet/FleetValuesFrom.vue +8 -2
- package/components/fleet/GitRepoTargetTab.vue +0 -2
- package/components/fleet/HelmOpAdvancedTab.vue +19 -53
- package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
- package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
- package/components/fleet/HelmOpResourcesSection.vue +82 -0
- package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
- package/components/fleet/HelmOpTargetTab.vue +64 -60
- package/components/fleet/HelmOpValuesTab.vue +129 -105
- package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
- package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
- package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +402 -115
- package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
- package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
- package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
- package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
- package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
- package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
- package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
- package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
- package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
- package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
- package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
- package/components/fleet/dashboard/Empty.vue +8 -4
- package/components/fleet/dashboard/ResourceCard.vue +28 -0
- package/components/fleet/dashboard/ResourceDetails.vue +28 -0
- package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
- package/components/form/ArrayList.vue +61 -4
- package/components/form/KeyValue.vue +23 -2
- package/components/form/LabeledSelect.vue +59 -4
- package/components/form/Labels.vue +22 -3
- package/components/form/NameNsDescription.vue +24 -5
- package/components/form/ResourceTabs/index.vue +1 -0
- package/components/form/Security.vue +6 -2
- package/components/form/WorkloadPorts.vue +2 -7
- package/components/form/__tests__/NameNsDescription.test.ts +75 -0
- package/components/form/__tests__/Security.test.ts +76 -0
- package/components/formatter/Autoscaler.vue +4 -4
- package/components/formatter/ClusterKubeVersion.vue +27 -0
- package/components/formatter/ClusterLink.vue +1 -7
- package/components/formatter/ClusterProvider.vue +6 -10
- package/components/formatter/FleetSummaryGraph.vue +0 -3
- package/components/formatter/InternalExternalIP.vue +10 -4
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/PodsUsage.vue +2 -2
- package/components/formatter/ServiceTargets.vue +26 -7
- package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
- package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
- package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
- package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
- package/components/nav/Header.vue +4 -0
- package/components/nav/NamespaceFilter.vue +2 -2
- package/components/nav/TopLevelMenu.helper.ts +15 -3
- package/components/nav/TopLevelMenu.vue +22 -6
- package/components/nav/__tests__/Header.test.ts +15 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +263 -21
- package/components/templates/default.vue +9 -4
- package/components/templates/home.vue +23 -0
- package/components/templates/plain.vue +23 -0
- package/components/templates/standalone.vue +17 -0
- package/composables/useFormValidation.ts +93 -0
- package/composables/useHelmOpResources.test.ts +56 -0
- package/composables/useHelmOpResources.ts +32 -0
- package/composables/useStateColor.test.ts +325 -0
- package/composables/useStateColor.ts +128 -0
- package/composables/useVeeValidateField.test.ts +159 -0
- package/composables/useVeeValidateField.ts +67 -0
- package/config/home-links.js +1 -1
- package/config/labels-annotations.js +1 -0
- package/config/pagination-table-headers.js +18 -1
- package/config/product/explorer.js +17 -4
- package/config/product/manager.js +84 -21
- package/config/router/index.js +16 -0
- package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
- package/config/router/navigation-guards/authentication.js +10 -4
- package/config/router/routes.js +26 -6
- package/config/settings.ts +0 -2
- package/config/table-headers.js +23 -5
- package/config/types.js +11 -1
- package/core/__tests__/plugin-products.test.ts +904 -20
- package/core/plugin-products-base.ts +110 -10
- package/core/plugin-products.ts +4 -0
- package/core/plugin-types.ts +194 -31
- package/core/plugin.ts +18 -7
- package/core/productDebugger.js +9 -4
- package/core/types-provisioning.ts +77 -31
- package/core/types.ts +72 -22
- package/detail/__tests__/pod.test.ts +41 -0
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
- package/detail/__tests__/workload.test.ts +3 -152
- package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
- package/detail/harvesterhci.io.management.cluster.vue +6 -2
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +34 -14
- package/detail/workload/index.vue +12 -55
- package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
- package/edit/auth/__tests__/azuread.test.ts +247 -39
- package/edit/auth/__tests__/github.test.ts +234 -0
- package/edit/auth/__tests__/oidc.test.ts +26 -6
- package/edit/auth/__tests__/saml.test.ts +196 -0
- package/edit/auth/azuread.vue +197 -56
- package/edit/auth/github.vue +72 -13
- package/edit/auth/ldap/__tests__/index.test.ts +206 -0
- package/edit/auth/ldap/config.vue +8 -0
- package/edit/auth/ldap/index.vue +75 -1
- package/edit/auth/oidc.vue +119 -73
- package/edit/auth/saml.vue +76 -12
- package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
- package/edit/fleet.cattle.io.helmop.vue +491 -136
- package/edit/management.cattle.io.user.vue +5 -2
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
- package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
- package/edit/networking.k8s.io.ingress/index.vue +75 -20
- package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/rke2.vue +92 -14
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +22 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
- package/edit/secret/__tests__/ssh.test.ts +5 -6
- package/edit/secret/basic.vue +31 -0
- package/edit/secret/index.vue +68 -17
- package/edit/secret/registry.vue +38 -0
- package/edit/secret/ssh.vue +29 -0
- package/edit/secret/tls.vue +30 -0
- package/edit/service.vue +4 -4
- package/edit/workload/Upgrading.vue +3 -3
- package/edit/workload/__tests__/Upgrading.test.ts +6 -9
- package/edit/workload/mixins/workload.js +2 -1
- package/list/fleet.cattle.io.bundle.vue +7 -104
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
- package/list/group.principal.vue +5 -4
- package/list/harvesterhci.io.management.cluster.vue +8 -9
- package/list/management.cattle.io.user.vue +12 -9
- package/list/provisioning.cattle.io.cluster.vue +268 -180
- package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
- package/mixins/__tests__/auth-config.test.ts +90 -0
- package/mixins/__tests__/chart.test.ts +206 -0
- package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
- package/mixins/auth-config.js +7 -0
- package/mixins/brand.js +2 -1
- package/mixins/chart.js +22 -9
- package/mixins/child-hook.js +12 -6
- package/mixins/create-edit-view/impl.js +5 -3
- package/mixins/resource-fetch-api-pagination.js +62 -6
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
- package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
- package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
- package/models/__tests__/fleet-application.test.ts +175 -0
- package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
- package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
- package/models/__tests__/management.cattle.io.node.ts +28 -5
- package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
- package/models/__tests__/namespace.test.ts +36 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +81 -11
- package/models/__tests__/workload.test.ts +401 -26
- package/models/base-cluster.x-k8s.io.js +26 -0
- package/models/catalog.cattle.io.clusterrepo.js +28 -4
- package/models/cluster.js +1 -1
- package/models/cluster.x-k8s.io.machine.js +4 -22
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
- package/models/cluster.x-k8s.io.machineset.js +2 -20
- package/models/compliance.cattle.io.clusterscan.js +165 -2
- package/models/ext.cattle.io.kubeconfig.ts +4 -7
- package/models/fleet-application.js +7 -1
- package/models/fleet.cattle.io.helmop.js +20 -1
- package/models/management.cattle.io.cluster.js +434 -41
- package/models/management.cattle.io.node.js +50 -7
- package/models/management.cattle.io.nodepool.js +1 -1
- package/models/namespace.js +1 -1
- package/models/networking.k8s.io.ingress.js +12 -4
- package/models/pod.js +33 -1
- package/models/provisioning.cattle.io.cluster.js +51 -334
- package/models/rke.cattle.io.etcdsnapshot.js +1 -2
- package/models/workload.js +108 -13
- package/models/workload.service.js +5 -0
- package/package.json +22 -39
- package/pages/__tests__/readme.test.ts +49 -0
- package/pages/about.vue +5 -6
- package/pages/auth/login.vue +0 -35
- package/pages/auth/setup.vue +13 -3
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
- package/pages/c/_cluster/apps/charts/chart.vue +62 -9
- package/pages/c/_cluster/apps/charts/index.vue +48 -10
- package/pages/c/_cluster/apps/charts/install.vue +122 -113
- package/pages/c/_cluster/auth/roles/index.vue +5 -4
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
- package/pages/c/_cluster/explorer/index.vue +5 -49
- package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
- package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
- package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
- package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
- package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
- package/pages/c/_cluster/fleet/application/create.vue +187 -136
- package/pages/c/_cluster/fleet/application/index.vue +5 -3
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
- package/pages/c/_cluster/fleet/index.vue +2 -2
- package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
- package/pages/c/_cluster/istio/index.vue +21 -6
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +815 -2
- package/pages/c/_cluster/uiplugins/index.vue +218 -197
- package/pages/diagnostic.vue +13 -17
- package/pages/fail-whale.vue +30 -7
- package/pages/home.vue +93 -306
- package/pages/readme.vue +88 -0
- package/plugins/clean-html.d.ts +9 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +181 -0
- package/plugins/dashboard-store/actions.js +40 -18
- package/plugins/dashboard-store/resource-class.js +67 -9
- package/plugins/steve/__tests__/actions.test.ts +212 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
- package/plugins/steve/actions.js +96 -0
- package/plugins/steve/steve-pagination-utils.ts +12 -4
- package/plugins/steve/subscribe.js +35 -5
- package/rancher-components/Accordion/Accordion.vue +53 -9
- package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
- package/rancher-components/Form/Radio/RadioButton.vue +17 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
- package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
- package/rancher-components/RcButton/RcButton.test.ts +140 -1
- package/rancher-components/RcButton/RcButton.vue +126 -17
- package/rancher-components/RcButton/types.ts +3 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
- package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
- package/rancher-components/RcSection/RcSection.vue +28 -3
- package/scripts/extension/helm/package/Dockerfile +1 -1
- package/scripts/test-plugins-build.sh +2 -1
- package/store/__tests__/catalog.test.ts +115 -1
- package/store/__tests__/notifications.test.ts +434 -0
- package/store/__tests__/type-map.test.ts +556 -1
- package/store/action-menu.js +8 -3
- package/store/auth.js +1 -1
- package/store/aws.js +27 -16
- package/store/catalog.js +84 -3
- package/store/digitalocean.js +20 -38
- package/store/index.js +2 -0
- package/store/linode.js +25 -40
- package/store/plugins.js +7 -4
- package/store/pnap.js +1 -0
- package/store/type-map.js +111 -29
- package/tsconfig.paths.json +8 -8
- package/types/components/buttonGroup.ts +5 -0
- package/types/kube/kube-api.ts +14 -1
- package/types/rancher/steve.api.ts +12 -12
- package/types/resources/settings.d.ts +2 -1
- package/types/shell/index.d.ts +206 -72
- package/types/store/dashboard-store.types.ts +108 -11
- package/types/store/pagination.types.ts +6 -3
- package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
- package/utils/__tests__/async.test.ts +87 -0
- package/utils/__tests__/auth.test.ts +273 -0
- package/utils/__tests__/aws.test.ts +140 -0
- package/utils/__tests__/banners.test.ts +176 -0
- package/utils/__tests__/chart.test.ts +64 -1
- package/utils/__tests__/color.test.ts +226 -0
- package/utils/__tests__/computed.test.ts +193 -0
- package/utils/__tests__/cspAdaptor.test.ts +163 -0
- package/utils/__tests__/dom.test.ts +81 -0
- package/utils/__tests__/duration.test.ts +176 -0
- package/utils/__tests__/dynamic-importer.test.ts +102 -0
- package/utils/__tests__/fleet-appco.test.ts +312 -0
- package/utils/__tests__/fleet.test.ts +340 -0
- package/utils/__tests__/ingress.test.ts +553 -0
- package/utils/__tests__/kube.test.ts +68 -0
- package/utils/__tests__/monitoring.test.ts +130 -0
- package/utils/__tests__/namespace-filter.test.ts +109 -0
- package/utils/__tests__/object.test.ts +22 -0
- package/utils/__tests__/pagination-utils.test.ts +361 -0
- package/utils/__tests__/parse-externalid.test.ts +137 -0
- package/utils/__tests__/perf-setting.utils.test.ts +98 -0
- package/utils/__tests__/platform.test.ts +91 -0
- package/utils/__tests__/poller-sequential.test.ts +177 -0
- package/utils/__tests__/poller.test.ts +170 -0
- package/utils/__tests__/position.test.ts +237 -0
- package/utils/__tests__/promise.test.ts +346 -0
- package/utils/__tests__/provider.test.ts +51 -1
- package/utils/__tests__/queue.test.ts +232 -0
- package/utils/__tests__/release-notes.test.ts +221 -0
- package/utils/__tests__/router.test.js +254 -1
- package/utils/__tests__/select.test.ts +208 -0
- package/utils/__tests__/settings.test.ts +140 -0
- package/utils/__tests__/sort-utils.test.ts +301 -0
- package/utils/__tests__/string-utils.test.ts +798 -0
- package/utils/__tests__/string.test.ts +23 -1
- package/utils/__tests__/style.test.ts +154 -0
- package/utils/__tests__/svg-filter.test.ts +184 -0
- package/utils/__tests__/time.test.ts +265 -1
- package/utils/__tests__/title.test.ts +47 -0
- package/utils/__tests__/units.test.ts +417 -0
- package/utils/__tests__/versions.test.ts +128 -0
- package/utils/__tests__/width.test.ts +53 -0
- package/utils/__tests__/window.test.ts +158 -0
- package/utils/__tests__/xccdf.test.ts +511 -0
- package/utils/chart.js +36 -0
- package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
- package/utils/crypto/__tests__/index.test.ts +144 -0
- package/utils/duration.ts +104 -0
- package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
- package/utils/dynamic-content/info.ts +2 -1
- package/utils/error.js +13 -0
- package/utils/fleet-appco.ts +323 -0
- package/utils/fleet.ts +13 -3
- package/utils/gatekeeper/__tests__/util.test.ts +174 -0
- package/utils/gc/__tests__/gc-interval.test.ts +119 -0
- package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
- package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
- package/utils/gc/__tests__/gc.test.ts +487 -0
- package/utils/ingress.ts +9 -1
- package/utils/object.js +22 -2
- package/utils/pagination-utils.ts +2 -1
- package/utils/provider.ts +12 -0
- package/utils/string.js +25 -2
- package/utils/uiplugins.ts +5 -5
- package/utils/validators/__tests__/cluster-name.test.ts +110 -0
- package/utils/validators/__tests__/container-images.test.ts +104 -0
- package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
- package/utils/validators/__tests__/flow-output.test.ts +91 -0
- package/utils/validators/__tests__/index.test.ts +481 -0
- package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
- package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
- package/utils/validators/__tests__/misc-validators.test.ts +246 -0
- package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
- package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
- package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
- package/utils/validators/__tests__/role-template.test.ts +149 -0
- package/utils/validators/__tests__/service.test.ts +283 -0
- package/utils/validators/__tests__/setting.test.js +32 -0
- package/utils/validators/formRules/__tests__/index.test.ts +50 -0
- package/utils/validators/formRules/index.ts +5 -5
- package/utils/validators/machine-pool.ts +1 -1
- package/utils/validators/setting.js +18 -3
- package/utils/xccdf.ts +415 -0
- package/vue.config.js +1 -1
- package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
- package/pages/support/index.vue +0 -264
- package/utils/duration.js +0 -43
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import actions from '@shell/plugins/steve/actions';
|
|
2
|
+
import paginationUtils from '@shell/utils/pagination-utils';
|
|
3
|
+
import stevePaginationUtils from '@shell/plugins/steve/steve-pagination-utils';
|
|
4
|
+
import { PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
5
|
+
|
|
6
|
+
const { fetchResourceSummary } = actions;
|
|
7
|
+
|
|
8
|
+
describe('steve: actions:', () => {
|
|
9
|
+
describe('fetchResourceSummary', () => {
|
|
10
|
+
const schema = {
|
|
11
|
+
id: 'pod',
|
|
12
|
+
links: { collection: '/v1/pods' },
|
|
13
|
+
attributes: { namespaced: true },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const baseCtx = () => ({
|
|
17
|
+
getters: {
|
|
18
|
+
normalizeType: (type: string) => type,
|
|
19
|
+
schemaFor: (type: string) => (type === 'pod' ? schema : undefined),
|
|
20
|
+
},
|
|
21
|
+
dispatch: jest.fn(),
|
|
22
|
+
rootGetters: {},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
let warnSpy: jest.SpyInstance;
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
29
|
+
jest.spyOn(paginationUtils, 'isSteveCacheEnabled').mockReturnValue(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
jest.restoreAllMocks();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return undefined and warn when schema is not found', async() => {
|
|
37
|
+
const ctx = baseCtx();
|
|
38
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'nonexistent', opt: { summaryField: 'metadata.state.name' } });
|
|
39
|
+
|
|
40
|
+
expect(result).toBeUndefined();
|
|
41
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('no schema found'));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return undefined and warn when VAI is not enabled', async() => {
|
|
45
|
+
jest.spyOn(paginationUtils, 'isSteveCacheEnabled').mockReturnValue(false);
|
|
46
|
+
const ctx = baseCtx();
|
|
47
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
48
|
+
|
|
49
|
+
expect(result).toBeUndefined();
|
|
50
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('VAI is not enabled'));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should return undefined and warn when summaryField is missing', async() => {
|
|
54
|
+
const ctx = baseCtx();
|
|
55
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: {} });
|
|
56
|
+
|
|
57
|
+
expect(result).toBeUndefined();
|
|
58
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('summaryField is required'));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should construct the correct URL with summary and summaryonly params', async() => {
|
|
62
|
+
const ctx = baseCtx();
|
|
63
|
+
|
|
64
|
+
ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
|
|
65
|
+
|
|
66
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
67
|
+
|
|
68
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
69
|
+
|
|
70
|
+
expect(requestUrl).toContain('summary=metadata.state.name');
|
|
71
|
+
expect(requestUrl).toContain('summaryonly=');
|
|
72
|
+
expect(requestUrl).not.toContain('summarynamespaced');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should not include summaryonly when summaryOnly is false', async() => {
|
|
76
|
+
const ctx = baseCtx();
|
|
77
|
+
|
|
78
|
+
ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
|
|
79
|
+
|
|
80
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', summaryOnly: false } });
|
|
81
|
+
|
|
82
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
83
|
+
|
|
84
|
+
expect(requestUrl).not.toContain('summaryonly');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should include summarynamespaced param when namespaceCounts is true', async() => {
|
|
88
|
+
const ctx = baseCtx();
|
|
89
|
+
|
|
90
|
+
ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
|
|
91
|
+
|
|
92
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespaceCounts: true } });
|
|
93
|
+
|
|
94
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
95
|
+
|
|
96
|
+
expect(requestUrl).toContain('summarynamespaced=');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should append namespace to path for namespaced resources', async() => {
|
|
100
|
+
const ctx = baseCtx();
|
|
101
|
+
|
|
102
|
+
ctx.dispatch.mockResolvedValue({ count: 2, summary: null });
|
|
103
|
+
|
|
104
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespace: 'cattle-system' } });
|
|
105
|
+
|
|
106
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
107
|
+
|
|
108
|
+
expect(requestUrl).toMatch(/\/v1\/pods\/cattle-system\?/);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should not append namespace when schema is not namespaced', async() => {
|
|
112
|
+
const nonNsSchema = { ...schema, attributes: { namespaced: false } };
|
|
113
|
+
const ctx = baseCtx();
|
|
114
|
+
|
|
115
|
+
ctx.getters.schemaFor = () => nonNsSchema;
|
|
116
|
+
ctx.dispatch.mockResolvedValue({ count: 1, summary: null });
|
|
117
|
+
|
|
118
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespace: 'default' } });
|
|
119
|
+
|
|
120
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
121
|
+
|
|
122
|
+
expect(requestUrl).not.toContain('/default');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should append filter params when filters are provided', async() => {
|
|
126
|
+
const ctx = baseCtx();
|
|
127
|
+
const filters = [PaginationParamFilter.createSingleField({ field: 'metadata.namespace', value: 'default' })];
|
|
128
|
+
|
|
129
|
+
jest.spyOn(stevePaginationUtils, 'convertPaginationParams').mockReturnValue('filter=metadata.namespace%3Ddefault');
|
|
130
|
+
ctx.dispatch.mockResolvedValue({ count: 3, summary: null });
|
|
131
|
+
|
|
132
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', filters } });
|
|
133
|
+
|
|
134
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
135
|
+
|
|
136
|
+
expect(requestUrl).toContain('filter=');
|
|
137
|
+
expect(stevePaginationUtils.convertPaginationParams).toHaveBeenCalledWith(expect.objectContaining({ filters }));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should return count and summary from the response', async() => {
|
|
141
|
+
const ctx = baseCtx();
|
|
142
|
+
const apiResponse = {
|
|
143
|
+
count: 10,
|
|
144
|
+
summary: [{ property: 'metadata.state.name', counts: { running: { total: 7 }, error: { total: 3 } } }]
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
ctx.dispatch.mockResolvedValue(apiResponse);
|
|
148
|
+
|
|
149
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
150
|
+
|
|
151
|
+
expect(result).toStrictEqual(apiResponse);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should pass through object-style counts as-is', async() => {
|
|
155
|
+
const ctx = baseCtx();
|
|
156
|
+
const counts = { running: { total: 7 }, error: { total: 3 } };
|
|
157
|
+
const apiResponse = {
|
|
158
|
+
count: 10,
|
|
159
|
+
summary: [{ property: 'metadata.state.name', counts }]
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
ctx.dispatch.mockResolvedValue(apiResponse);
|
|
163
|
+
|
|
164
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
165
|
+
|
|
166
|
+
expect(result).toStrictEqual({
|
|
167
|
+
count: 10,
|
|
168
|
+
summary: [{ property: 'metadata.state.name', counts }]
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should default count to 0 and summary to null when response is empty', async() => {
|
|
173
|
+
const ctx = baseCtx();
|
|
174
|
+
|
|
175
|
+
ctx.dispatch.mockResolvedValue({});
|
|
176
|
+
|
|
177
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
178
|
+
|
|
179
|
+
expect(result).toStrictEqual({ count: 0, summary: null });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should append label selector params when labelSelector is provided', async() => {
|
|
183
|
+
const ctx = baseCtx();
|
|
184
|
+
const labelSelector = {
|
|
185
|
+
matchExpressions: [{
|
|
186
|
+
key: 'app', operator: 'In', values: ['nginx']
|
|
187
|
+
}]
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
jest.spyOn(stevePaginationUtils, 'convertLabelSelectorPaginationParams').mockReturnValue('filter=metadata.labels[app] IN (nginx)');
|
|
191
|
+
ctx.dispatch.mockResolvedValue({ count: 2, summary: null });
|
|
192
|
+
|
|
193
|
+
await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', labelSelector } });
|
|
194
|
+
|
|
195
|
+
const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
|
|
196
|
+
|
|
197
|
+
expect(requestUrl).toContain('filter=');
|
|
198
|
+
expect(stevePaginationUtils.convertLabelSelectorPaginationParams).toHaveBeenCalledWith({ labelSelector });
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should return undefined and warn when the request fails', async() => {
|
|
202
|
+
const ctx = baseCtx();
|
|
203
|
+
|
|
204
|
+
ctx.dispatch.mockRejectedValue(new Error('network error'));
|
|
205
|
+
|
|
206
|
+
const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
|
|
207
|
+
|
|
208
|
+
expect(result).toBeUndefined();
|
|
209
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('summary API request failed'), expect.any(Error));
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
@@ -14,7 +14,8 @@ describe('steve: subscribe', () => {
|
|
|
14
14
|
schemaFor: () => null,
|
|
15
15
|
inError: () => false,
|
|
16
16
|
watchStarted: () => false,
|
|
17
|
-
listenerManager: state.listenerManager
|
|
17
|
+
listenerManager: state.listenerManager,
|
|
18
|
+
typeRegistered: () => true,
|
|
18
19
|
};
|
|
19
20
|
const rootGetters = {
|
|
20
21
|
'type-map/isSpoofed': () => false,
|
|
@@ -343,7 +344,7 @@ describe('steve: subscribe', () => {
|
|
|
343
344
|
|
|
344
345
|
// call watch
|
|
345
346
|
actions.watch({
|
|
346
|
-
state, dispatch, getters, rootGetters
|
|
347
|
+
state, dispatch, getters, rootGetters, commit
|
|
347
348
|
}, {
|
|
348
349
|
...obj,
|
|
349
350
|
revision,
|
|
@@ -488,6 +489,7 @@ describe('steve: subscribe', () => {
|
|
|
488
489
|
const state = {
|
|
489
490
|
started: [],
|
|
490
491
|
inError: {},
|
|
492
|
+
queue: [],
|
|
491
493
|
listenerManager: new SteveWatchEventListenerManager()
|
|
492
494
|
};
|
|
493
495
|
const _getters = {
|
|
@@ -498,7 +500,8 @@ describe('steve: subscribe', () => {
|
|
|
498
500
|
watchStarted: (...args) => getters.watchStarted(state)(...args),
|
|
499
501
|
backOffId: (...args) => getters.backOffId()(...args),
|
|
500
502
|
canBackoff: () => true,
|
|
501
|
-
listenerManager: state.listenerManager
|
|
503
|
+
listenerManager: state.listenerManager,
|
|
504
|
+
typeRegistered: () => true,
|
|
502
505
|
};
|
|
503
506
|
const commit = (type, ...args) => mutations[type](state, ...args);
|
|
504
507
|
|
package/plugins/steve/actions.js
CHANGED
|
@@ -10,6 +10,7 @@ import { NAMESPACE } from '@shell/config/types';
|
|
|
10
10
|
import { handleKubeApiHeaderWarnings } from '@shell/plugins/steve/header-warnings';
|
|
11
11
|
import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
|
|
12
12
|
import paginationUtils from '@shell/utils/pagination-utils';
|
|
13
|
+
import stevePaginationUtils from '@shell/plugins/steve/steve-pagination-utils';
|
|
13
14
|
|
|
14
15
|
export default {
|
|
15
16
|
|
|
@@ -221,6 +222,101 @@ export default {
|
|
|
221
222
|
}
|
|
222
223
|
},
|
|
223
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Fetch aggregated state counts for a resource type via the Steve summary API.
|
|
227
|
+
* Requires VAI (ui-sql-cache) to be enabled; returns undefined otherwise.
|
|
228
|
+
*
|
|
229
|
+
* Uses `summaryonly` by default so no resource data is returned.
|
|
230
|
+
*
|
|
231
|
+
* @param {string} type - Resource type (e.g. 'pod', 'service')
|
|
232
|
+
* @param {object} [opt] - Options object
|
|
233
|
+
* @param {string} opt.summaryField - Field to aggregate counts by.
|
|
234
|
+
* Must be a field indexed by the VAI cache (see StevePaginationUtils.VALID_FIELDS in steve-pagination-utils.ts)
|
|
235
|
+
* @param {string} [opt.namespace] - Namespace to scope the request to (only applies to namespaced resource types)
|
|
236
|
+
* @param {boolean} [opt.summaryOnly=true] - Omit resource data from the response (set to false to include data)
|
|
237
|
+
* @param {boolean} [opt.namespaceCounts] - Include per-namespace breakdowns in counts
|
|
238
|
+
* @param {PaginationParamFilter[]} [opt.filters] - Pre-built filters from PaginationParamFilter.createSingleField()
|
|
239
|
+
* @param {KubeLabelSelector} [opt.labelSelector] - Kube label selector to filter by (converted via convertLabelSelectorPaginationParams)
|
|
240
|
+
* @returns {Promise<{ count: number, summary: { property: string, counts: Record<string, { total: number, namespace?: Record<string, number> }> }[] | null } | undefined>}
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* const result = await dispatch('fetchResourceSummary', {
|
|
244
|
+
* type: 'pod',
|
|
245
|
+
* opt: { summaryField: 'metadata.state.name', labelSelector: { matchExpressions: podMatchExpression } }
|
|
246
|
+
* });
|
|
247
|
+
* // result.summary[0].counts => { running: { total: 3 }, error: { total: 1 } }
|
|
248
|
+
*
|
|
249
|
+
* // With namespace breakdowns:
|
|
250
|
+
* const result = await dispatch('fetchResourceSummary', {
|
|
251
|
+
* type: 'pod',
|
|
252
|
+
* opt: { summaryField: 'metadata.state.name', namespaceCounts: true }
|
|
253
|
+
* });
|
|
254
|
+
* // result.summary[0].counts => { running: { total: 3, namespace: { default: 2, 'kube-system': 1 } } }
|
|
255
|
+
*/
|
|
256
|
+
async fetchResourceSummary({ getters, dispatch, rootGetters }, { type, opt = {} }) {
|
|
257
|
+
type = getters.normalizeType(type);
|
|
258
|
+
const schema = getters.schemaFor(type);
|
|
259
|
+
|
|
260
|
+
if (!schema) {
|
|
261
|
+
console.warn(`fetchResourceSummary: no schema found for type "${ type }"`); // eslint-disable-line no-console
|
|
262
|
+
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (!paginationUtils.isSteveCacheEnabled({ rootGetters })) {
|
|
267
|
+
console.warn(`fetchResourceSummary: VAI is not enabled, summary API unavailable for type "${ type }"`); // eslint-disable-line no-console
|
|
268
|
+
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (!opt.summaryField) {
|
|
273
|
+
console.warn(`fetchResourceSummary: summaryField is required and must be a string for type "${ type }"`); // eslint-disable-line no-console
|
|
274
|
+
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
const url = new URL(schema.links.collection, window.location.origin);
|
|
280
|
+
|
|
281
|
+
if (schema.attributes?.namespaced && opt.namespace) {
|
|
282
|
+
url.pathname += `/${ opt.namespace }`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
url.searchParams.set('summary', opt.summaryField);
|
|
286
|
+
|
|
287
|
+
if (opt.summaryOnly !== false) {
|
|
288
|
+
url.searchParams.set('summaryonly', '');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (opt.namespaceCounts) {
|
|
292
|
+
url.searchParams.set('summarynamespaced', '');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (opt.filters?.length) {
|
|
296
|
+
const filterParams = new URLSearchParams(stevePaginationUtils.convertPaginationParams({ schema, filters: opt.filters }));
|
|
297
|
+
|
|
298
|
+
filterParams.forEach((v, k) => url.searchParams.append(k, v));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (opt.labelSelector) {
|
|
302
|
+
const labelParams = new URLSearchParams(stevePaginationUtils.convertLabelSelectorPaginationParams({ labelSelector: opt.labelSelector }));
|
|
303
|
+
|
|
304
|
+
labelParams.forEach((v, k) => url.searchParams.append(k, v));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const res = await dispatch('request', { opt: { url: url.pathname + url.search } });
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
count: res.count ?? 0,
|
|
311
|
+
summary: res.summary || null
|
|
312
|
+
};
|
|
313
|
+
} catch (e) {
|
|
314
|
+
console.warn(`fetchResourceSummary: summary API request failed for type "${ type }"`, e); // eslint-disable-line no-console
|
|
315
|
+
|
|
316
|
+
return undefined;
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
|
|
224
320
|
promptRestore({ commit, state }, resources ) {
|
|
225
321
|
commit('action-menu/togglePromptRestore', resources, { root: true });
|
|
226
322
|
},
|
|
@@ -258,6 +258,11 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
258
258
|
{ field: 'spec.displayName' },
|
|
259
259
|
{ field: `status.provider` },
|
|
260
260
|
{ field: `status.connected` },
|
|
261
|
+
{ field: `status.info.machineProvider` },
|
|
262
|
+
{ field: `status.driver` },
|
|
263
|
+
{ field: `status.provider` },
|
|
264
|
+
{ field: `status.info.kubernetesVersion` },
|
|
265
|
+
{ field: `spec.fleetWorkspaceName` },
|
|
261
266
|
],
|
|
262
267
|
[SECRET]: [
|
|
263
268
|
{ field: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]` },
|
|
@@ -265,7 +270,10 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
265
270
|
[NAMESPACE]: [
|
|
266
271
|
],
|
|
267
272
|
[CAPI.MACHINE]: [
|
|
268
|
-
{ field: 'spec.clusterName' }
|
|
273
|
+
{ field: 'spec.clusterName' },
|
|
274
|
+
],
|
|
275
|
+
[CAPI.MACHINE_DEPLOYMENT]: [
|
|
276
|
+
{ field: 'spec.clusterName' },
|
|
269
277
|
],
|
|
270
278
|
[EVENT]: [
|
|
271
279
|
{ field: '_type' },
|
|
@@ -648,7 +656,7 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
648
656
|
* A lot of the requirements and details are taken directly from
|
|
649
657
|
* https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
|
650
658
|
*/
|
|
651
|
-
|
|
659
|
+
convertLabelSelectorPaginationParams({ labelSelector }: { labelSelector: KubeLabelSelector}): string {
|
|
652
660
|
// Get a list of matchExpressions
|
|
653
661
|
const expressions: KubeLabelSelectorExpression[] = labelSelector.matchExpressions ? [...labelSelector.matchExpressions] : [];
|
|
654
662
|
|
|
@@ -770,8 +778,8 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStores = {
|
|
|
770
778
|
enableAll: false,
|
|
771
779
|
enableSome: {
|
|
772
780
|
enabled: [
|
|
773
|
-
{ resource: CAPI.RANCHER_CLUSTER, context: ['side-bar'] },
|
|
774
|
-
{ resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
|
|
781
|
+
{ resource: CAPI.RANCHER_CLUSTER, context: ['side-bar', 'home', 'cluster-management'] },
|
|
782
|
+
{ resource: MANAGEMENT.CLUSTER, context: ['side-bar', 'home', 'cluster-management'] },
|
|
775
783
|
{ resource: CATALOG.APP, context: ['branding'] },
|
|
776
784
|
SECRET
|
|
777
785
|
],
|
|
@@ -469,8 +469,10 @@ const sharedActions = {
|
|
|
469
469
|
const worker = (this.$workers || {})[getters.storeName];
|
|
470
470
|
|
|
471
471
|
if (worker) {
|
|
472
|
+
const storeName = getters.storeName;
|
|
473
|
+
|
|
472
474
|
worker.postMessage({ destroyWorker: true }); // we're only passing the boolean here because the key needs to be something truthy to ensure it's passed on the object.
|
|
473
|
-
cleanupTasks.push(waitFor(() => !this.$workers[
|
|
475
|
+
cleanupTasks.push(waitFor(() => !this.$workers?.[storeName], 'Worker to be destroyed', 30000, 10, true));
|
|
474
476
|
}
|
|
475
477
|
|
|
476
478
|
if ( socket ) {
|
|
@@ -553,17 +555,32 @@ const sharedActions = {
|
|
|
553
555
|
* @param {STEVE_WATCH_PARAMS} params
|
|
554
556
|
*/
|
|
555
557
|
watch({
|
|
556
|
-
state, dispatch, getters, rootGetters
|
|
558
|
+
state, dispatch, getters, rootGetters, commit
|
|
557
559
|
}, params) {
|
|
558
560
|
state.debugSocket && console.info(`Watch Request [${ getters.storeName }]`, JSON.stringify(params)); // eslint-disable-line no-console
|
|
559
561
|
let {
|
|
560
562
|
// eslint-disable-next-line prefer-const
|
|
561
|
-
type, selector, id, revision, namespace, stop, force, mode, standardWatch = true
|
|
563
|
+
type, selector, id, revision, namespace, stop, force, mode, standardWatch = true, registerType = false
|
|
562
564
|
} = params;
|
|
563
565
|
|
|
564
566
|
namespace = acceptOrRejectSocketMessage.subscribeNamespace(namespace);
|
|
565
567
|
type = getters.normalizeType(type);
|
|
566
568
|
|
|
569
|
+
if ( !getters.typeRegistered(type) ) {
|
|
570
|
+
if (registerType) {
|
|
571
|
+
commit('registerType', type);
|
|
572
|
+
} else if (mode !== STEVE_WATCH_MODE.RESOURCE_CHANGES) {
|
|
573
|
+
// - If we continue and open up a watch whenever we receive a `resource.` notification we go to queueChanges (bar resource.changes mode).
|
|
574
|
+
// - queueChanges ignores any change that's for a type that hasn't been registered
|
|
575
|
+
// - So here we're just exiting early, avoiding the watch --> queueChanges --> ignore loop
|
|
576
|
+
//
|
|
577
|
+
// Interestingly this is hit quite a few times (on cluster create screens there's token, cluster, project, projectRoleTemplateBinding, etc)
|
|
578
|
+
state.debugSocket && console.info('Will not Watch (type is not registered)', JSON.stringify(params)); // eslint-disable-line no-console
|
|
579
|
+
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
567
584
|
if (rootGetters['type-map/isSpoofed'](type)) {
|
|
568
585
|
state.debugSocket && console.info('Will not Watch (type is spoofed)', JSON.stringify(params)); // eslint-disable-line no-console
|
|
569
586
|
|
|
@@ -620,6 +637,9 @@ const sharedActions = {
|
|
|
620
637
|
if (debounceMs) {
|
|
621
638
|
msg.debounceMs = debounceMs;
|
|
622
639
|
}
|
|
640
|
+
|
|
641
|
+
// Anything in the queue will pollute the result set, so clear (and print to console so we know it's working)
|
|
642
|
+
commit('clearFromQueue', { type, log: true });
|
|
623
643
|
}
|
|
624
644
|
}
|
|
625
645
|
|
|
@@ -1556,10 +1576,20 @@ const defaultMutations = {
|
|
|
1556
1576
|
state.socketListenerManager = new SteveWatchEventListenerManager(state.config.namespace);
|
|
1557
1577
|
},
|
|
1558
1578
|
|
|
1559
|
-
clearFromQueue(state,
|
|
1579
|
+
clearFromQueue(state, args) {
|
|
1580
|
+
const safeArgs = typeof args === 'object' ? args : { type: args };
|
|
1581
|
+
const { type, log } = safeArgs;
|
|
1582
|
+
|
|
1560
1583
|
// Remove anything in the queue that is a resource update for the given type
|
|
1561
1584
|
state.queue = state.queue.filter((item) => {
|
|
1562
|
-
|
|
1585
|
+
const keep = item.body?.type !== type;
|
|
1586
|
+
|
|
1587
|
+
if (!keep && log) {
|
|
1588
|
+
// eslint-disable-next-line no-console
|
|
1589
|
+
console.info(`Clearing queued item of type \`${ type }\` from queue`, item);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
return keep;
|
|
1563
1593
|
});
|
|
1564
1594
|
},
|
|
1565
1595
|
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
computed, defineComponent, nextTick, ref, useTemplateRef
|
|
4
|
+
} from 'vue';
|
|
5
|
+
import { mapGetters, useStore } from 'vuex';
|
|
6
|
+
import { useInSummary } from '@shell/components/TableOfContents/composables';
|
|
7
|
+
import { useI18n } from '@shell/composables/useI18n';
|
|
4
8
|
|
|
5
9
|
export default defineComponent({
|
|
10
|
+
name: 'Accordion',
|
|
11
|
+
|
|
6
12
|
props: {
|
|
7
13
|
title: {
|
|
8
14
|
type: String,
|
|
@@ -20,22 +26,59 @@ export default defineComponent({
|
|
|
20
26
|
}
|
|
21
27
|
},
|
|
22
28
|
|
|
29
|
+
setup(props) {
|
|
30
|
+
const store = useStore();
|
|
31
|
+
const { t } = useI18n(store);
|
|
32
|
+
const label = computed(() => props.titleKey && typeof t === 'function' ? t(props.titleKey) : props.title);
|
|
33
|
+
|
|
34
|
+
const isOpen = ref(props.openInitially);
|
|
35
|
+
const accordionSummarizedContainer = useTemplateRef<HTMLElement>('accordion-summarized-container');
|
|
36
|
+
|
|
37
|
+
const scrollTo = () => {
|
|
38
|
+
isOpen.value = true;
|
|
39
|
+
nextTick(() => {
|
|
40
|
+
accordionSummarizedContainer.value?.scrollIntoView();
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const { summary } = useInSummary({
|
|
45
|
+
scrollTo,
|
|
46
|
+
label,
|
|
47
|
+
elementRef: accordionSummarizedContainer,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
summary,
|
|
52
|
+
isOpen,
|
|
53
|
+
scrollTo,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
|
|
23
57
|
data() {
|
|
24
|
-
return {
|
|
58
|
+
return {};
|
|
25
59
|
},
|
|
26
60
|
|
|
27
|
-
computed: {
|
|
61
|
+
computed: {
|
|
62
|
+
...mapGetters({ t: 'i18n/t' }),
|
|
63
|
+
|
|
64
|
+
displayTitle() {
|
|
65
|
+
return this.titleKey ? this.t(this.titleKey) : this.title;
|
|
66
|
+
},
|
|
67
|
+
},
|
|
28
68
|
|
|
29
69
|
methods: {
|
|
30
70
|
toggle() {
|
|
31
71
|
this.isOpen = !this.isOpen;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
72
|
+
},
|
|
73
|
+
},
|
|
34
74
|
});
|
|
35
75
|
</script>
|
|
36
76
|
|
|
37
77
|
<template>
|
|
38
|
-
<div
|
|
78
|
+
<div
|
|
79
|
+
ref="accordion-summarized-container"
|
|
80
|
+
class="accordion-container"
|
|
81
|
+
>
|
|
39
82
|
<div
|
|
40
83
|
class="accordion-header"
|
|
41
84
|
data-testid="accordion-header"
|
|
@@ -51,7 +94,7 @@ export default defineComponent({
|
|
|
51
94
|
data-testid="accordion-title-slot-content"
|
|
52
95
|
class="mb-0"
|
|
53
96
|
>
|
|
54
|
-
{{
|
|
97
|
+
{{ displayTitle }}
|
|
55
98
|
</h2>
|
|
56
99
|
</slot>
|
|
57
100
|
</div>
|
|
@@ -67,7 +110,8 @@ export default defineComponent({
|
|
|
67
110
|
|
|
68
111
|
<style lang="scss" scoped>
|
|
69
112
|
.accordion-container {
|
|
70
|
-
border: 1px solid var(--border)
|
|
113
|
+
border: 1px solid var(--border);
|
|
114
|
+
border-radius: var(--border-radius);
|
|
71
115
|
}
|
|
72
116
|
.accordion-header {
|
|
73
117
|
padding: 16px 16px 16px 11px;
|
|
@@ -125,6 +125,14 @@ export default defineComponent({
|
|
|
125
125
|
default: undefined
|
|
126
126
|
},
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Use body text color for the label instead of the default input-label color.
|
|
130
|
+
*/
|
|
131
|
+
useBodyTextColor: {
|
|
132
|
+
type: Boolean,
|
|
133
|
+
default: false
|
|
134
|
+
},
|
|
135
|
+
|
|
128
136
|
/**
|
|
129
137
|
* Inherited global identifier prefix for tests
|
|
130
138
|
* Define a term based on the parent component to avoid conflicts on multiple components
|
|
@@ -316,6 +324,7 @@ export default defineComponent({
|
|
|
316
324
|
<span
|
|
317
325
|
v-if="labelKey"
|
|
318
326
|
:id="idForLabel"
|
|
327
|
+
:class="{ 'body-text-color': useBodyTextColor }"
|
|
319
328
|
>
|
|
320
329
|
<t
|
|
321
330
|
:k="labelKey"
|
|
@@ -325,6 +334,7 @@ export default defineComponent({
|
|
|
325
334
|
<span
|
|
326
335
|
v-else-if="label"
|
|
327
336
|
:id="idForLabel"
|
|
337
|
+
:class="{ 'body-text-color': useBodyTextColor }"
|
|
328
338
|
>{{ label }}</span>
|
|
329
339
|
<i
|
|
330
340
|
v-if="tooltipKey"
|
|
@@ -403,6 +413,10 @@ $fontColor: var(--input-label);
|
|
|
403
413
|
display: inline-flex;
|
|
404
414
|
margin: 0px 10px 0px 5px;
|
|
405
415
|
|
|
416
|
+
.body-text-color {
|
|
417
|
+
color: var(--body-text);
|
|
418
|
+
}
|
|
419
|
+
|
|
406
420
|
&.checkbox-primary {
|
|
407
421
|
color: inherit;
|
|
408
422
|
font-weight: 600;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent, nextTick } from 'vue';
|
|
1
|
+
import { defineComponent, nextTick, provide, ref } from 'vue';
|
|
2
2
|
import { mount, flushPromises } from '@vue/test-utils';
|
|
3
3
|
import { useForm } from 'vee-validate';
|
|
4
4
|
import { LabeledInput } from './index';
|
|
@@ -195,21 +195,27 @@ describe('component: LabeledInput', () => {
|
|
|
195
195
|
|
|
196
196
|
it('with name prop: form-level validation schema error is shown when the form validates', async() => {
|
|
197
197
|
const errorMessage = 'Username is required';
|
|
198
|
+
const showAllErrors = ref(false);
|
|
198
199
|
let triggerFormValidation!: () => Promise<unknown>;
|
|
199
200
|
|
|
200
201
|
const TestWrapper = defineComponent({
|
|
201
202
|
components: { LabeledInput },
|
|
202
203
|
setup() {
|
|
204
|
+
provide('vee-show-all-errors', showAllErrors);
|
|
205
|
+
|
|
203
206
|
const { validate } = useForm({
|
|
204
207
|
validationSchema: { username: (v: string) => (!v ? errorMessage : true) },
|
|
205
|
-
initialValues: { username: '' }
|
|
208
|
+
initialValues: { username: '' },
|
|
206
209
|
});
|
|
207
210
|
|
|
208
|
-
triggerFormValidation =
|
|
211
|
+
triggerFormValidation = async() => {
|
|
212
|
+
await validate();
|
|
213
|
+
showAllErrors.value = true;
|
|
214
|
+
};
|
|
209
215
|
|
|
210
216
|
return {};
|
|
211
217
|
},
|
|
212
|
-
template: '<LabeledInput name="username" value="" />'
|
|
218
|
+
template: '<LabeledInput name="username" value="" />',
|
|
213
219
|
});
|
|
214
220
|
|
|
215
221
|
const wrapper = mount(TestWrapper, { global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } } });
|