@rancher/shell 0.5.3 → 2.0.0
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 +9 -0
- package/assets/images/vendor/openid.svg +18 -0
- package/assets/styles/app.scss +1 -2
- package/assets/styles/fonts/_icons.scss +3 -3
- package/assets/styles/global/_columns.scss +1 -1
- package/assets/styles/global/_labeled-input.scss +2 -0
- package/assets/styles/themes/_csp.scss +2 -2
- package/assets/styles/themes/_dark.scss +8 -2
- package/assets/styles/themes/_light.scss +2 -1
- package/assets/styles/themes/_suse.scss +1 -1
- package/assets/styles/vendor/vue-select.scss +5 -0
- package/assets/translations/en-us.yaml +296 -58
- package/assets/translations/zh-hans.yaml +5 -27
- package/babel.config.js +1 -1
- package/chart/__tests__/S3.test.ts +9 -2
- package/chart/monitoring/grafana/index.vue +6 -2
- package/chart/monitoring/prometheus/index.vue +2 -2
- package/chart/rancher-backup/S3.vue +11 -9
- package/chart/rancher-backup/index.vue +15 -5
- package/cloud-credential/__tests__/harvester.test.ts +18 -0
- package/cloud-credential/generic.vue +18 -9
- package/cloud-credential/harvester.vue +11 -3
- package/components/AppModal.vue +167 -0
- package/components/AssignTo.vue +7 -4
- package/components/AsyncButton.vue +18 -5
- package/components/BackLink.vue +4 -4
- package/components/BannerGraphic.vue +1 -0
- package/components/BrandImage.vue +47 -1
- package/components/Carousel.vue +14 -8
- package/components/Certificates.vue +8 -11
- package/components/ClusterBadge.vue +12 -3
- package/components/ClusterIconMenu.vue +44 -16
- package/components/ClusterProviderIcon.vue +14 -3
- package/components/CodeMirror.vue +73 -38
- package/components/CommunityLinks.vue +12 -8
- package/components/CreateDriver.vue +81 -0
- package/components/CruResource.vue +51 -27
- package/components/DetailTop.vue +2 -2
- package/components/Dialog.vue +6 -5
- package/components/DisableAuthProviderModal.vue +14 -8
- package/components/DraggableZone.vue +2 -2
- package/components/ExplorerMembers.vue +3 -3
- package/components/ExplorerProjectsNamespaces.vue +6 -6
- package/components/FixedBanner.vue +47 -36
- package/components/GlobalRoleBindings.vue +26 -0
- package/components/Import.vue +10 -6
- package/components/Inactivity.vue +1 -5
- package/components/KeyValueView.vue +14 -10
- package/components/MessageLink.vue +2 -2
- package/components/ModalWithCard.vue +5 -8
- package/components/MoveModal.vue +35 -33
- package/components/PodSecurityAdmission.vue +3 -3
- package/components/PromptChangePassword.vue +33 -33
- package/components/PromptModal.vue +11 -21
- package/components/PromptRemove.vue +11 -17
- package/components/PromptRestore.vue +18 -16
- package/components/Questions/__tests__/Boolean.test.ts +9 -19
- package/components/Questions/__tests__/Float.test.ts +9 -19
- package/components/Questions/__tests__/Int.test.ts +9 -19
- package/components/Questions/__tests__/String.test.ts +9 -19
- package/components/Questions/__tests__/Yaml.test.ts +9 -20
- package/components/Questions/__tests__/utils/questions-defaults.ts +20 -0
- package/components/Questions/index.vue +18 -2
- package/components/ResourceCancelModal.vue +34 -29
- package/components/ResourceDetail/Masthead.vue +23 -7
- package/components/ResourceDetail/index.vue +5 -0
- package/components/ResourceList/Masthead.vue +28 -10
- package/components/ResourceList/index.vue +65 -14
- package/components/ResourceTable.vue +73 -19
- package/components/ResourceYaml.vue +1 -0
- package/components/SelectIconGrid.vue +3 -3
- package/components/SideNav.vue +15 -37
- package/components/SingleClusterInfo.vue +4 -4
- package/components/SortableTable/THead.vue +26 -12
- package/components/SortableTable/filtering.js +9 -1
- package/components/SortableTable/grouping.js +8 -1
- package/components/SortableTable/index.vue +142 -42
- package/components/SortableTable/paging.js +36 -7
- package/components/SortableTable/selection.js +2 -1
- package/components/SortableTable/sorting.js +24 -7
- package/components/TabTitle.vue +84 -0
- package/components/Tabbed/index.vue +6 -1
- package/components/TableDataUserIcon.vue +47 -0
- package/components/TypeDescription.vue +1 -0
- package/components/Wizard.vue +1 -0
- package/components/__tests__/AppModal.test.ts +98 -0
- package/components/__tests__/AsyncButton.test.ts +1 -3
- package/components/__tests__/BackLink.test.ts +1 -1
- package/components/__tests__/ButtonGroup.test.ts +3 -6
- package/components/__tests__/Carousel.test.ts +43 -0
- package/components/__tests__/Certificates.test.ts +29 -0
- package/components/__tests__/{CodeMirror.spec.ts → CodeMirror.test.ts} +5 -17
- package/components/__tests__/CruResource.test.ts +10 -9
- package/components/__tests__/EtcdInfoBanner.test.ts +37 -0
- package/components/__tests__/FixedBanner.test.ts +5 -20
- package/components/__tests__/NamespaceFilter.test.ts +9 -18
- package/components/__tests__/TabTitle.test.ts +129 -0
- package/components/auth/AzureWarning.vue +2 -2
- package/components/auth/RoleDetailEdit.vue +10 -0
- package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
- package/components/auth/login/oidc.vue +7 -1
- package/components/fleet/FleetClusters.vue +9 -9
- package/components/fleet/FleetIntro.vue +11 -17
- package/components/fleet/FleetNoWorkspaces.vue +2 -2
- package/components/fleet/FleetRepos.vue +1 -0
- package/components/fleet/ForceDirectedTreeChart/index.vue +9 -3
- package/components/form/ArrayList.vue +30 -19
- package/components/form/ArrayListSelect.vue +9 -4
- package/components/form/ClusterAppearance.vue +132 -0
- package/components/form/ColorInput.vue +1 -0
- package/components/form/Error.vue +3 -3
- package/components/form/Footer.vue +2 -2
- package/components/form/GitPicker.vue +83 -38
- package/components/form/KeyValue.vue +67 -48
- package/components/form/LabeledSelect.vue +143 -43
- package/components/form/Labels.vue +3 -1
- package/components/form/NameNsDescription.vue +26 -9
- package/components/form/ResourceLabeledSelect.vue +187 -0
- package/components/form/ResourceTabs/index.vue +31 -15
- package/components/form/SecretSelector.vue +93 -18
- package/components/form/Select.vue +1 -1
- package/components/form/SelectOrCreateAuthSecret.vue +135 -62
- package/components/form/SimpleSecretSelector.vue +88 -28
- package/components/form/__tests__/BannerSettings.test.ts +53 -0
- package/components/form/__tests__/KeyValue.test.ts +121 -12
- package/components/form/__tests__/LabeledSelect.test.ts +0 -18
- package/components/form/__tests__/NameNsDescription.test.ts +25 -15
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +151 -0
- package/components/form/labeled-select-utils/labeled-select.utils.ts +122 -0
- package/components/formatter/AppSummaryGraph.vue +2 -2
- package/components/formatter/CloudCredPublicData.vue +30 -0
- package/components/formatter/ClusterLink.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +2 -1
- package/components/formatter/ImagePercentageBar.vue +0 -4
- package/components/formatter/IngressTarget.vue +18 -7
- package/components/formatter/Link.vue +2 -2
- package/components/formatter/LinkDetail.vue +2 -2
- package/components/formatter/LinkDetailImage.vue +2 -2
- package/components/formatter/LinkName.vue +2 -2
- package/components/formatter/LiveDate.vue +16 -0
- package/components/formatter/PrincipalGroupBindings.vue +2 -2
- package/components/formatter/SecretType.vue +2 -2
- package/components/formatter/VirtualServiceGateways.vue +2 -2
- package/components/formatter/__tests__/LinkDetail.test.ts +5 -5
- package/components/nav/Group.vue +7 -5
- package/components/nav/Header.vue +82 -43
- package/components/nav/NamespaceFilter.vue +8 -1
- package/components/nav/TopLevelMenu.vue +336 -125
- package/components/nav/Type.vue +58 -102
- package/components/nav/__tests__/TopLevelMenu.test.ts +370 -9
- package/components/nav/__tests__/Type.test.ts +321 -126
- package/components/nuxt/nuxt-child.js +0 -5
- package/components/nuxt/nuxt-error.vue +1 -1
- package/components/nuxt/nuxt-link.client.js +13 -95
- package/components/templates/default.vue +3 -3
- package/components/templates/error.vue +6 -10
- package/components/templates/standalone.vue +0 -4
- package/components/templates/unauthenticated.vue +1 -2
- package/components/user.retention/user-retention-header.vue +34 -0
- package/composables/useCompactInput.test.ts +36 -0
- package/composables/useCompactInput.ts +2 -2
- package/composables/useI18n.ts +26 -0
- package/composables/useLabeledFormElement.test.ts +135 -0
- package/composables/useStore.ts +16 -0
- package/config/home-links.js +32 -1
- package/config/labels-annotations.js +2 -1
- package/config/middleware.js +0 -6
- package/config/pagination-table-headers.js +57 -0
- package/config/pod-security-admission.ts +1 -1
- package/config/private-label.js +1 -3
- package/config/product/auth.js +1 -0
- package/config/product/explorer.js +167 -46
- package/config/product/legacy.js +3 -95
- package/config/product/manager.js +44 -11
- package/config/query-params.js +1 -0
- package/config/roles.ts +23 -0
- package/config/router/index.js +23 -0
- package/config/router/navigation-guards/attempt-first-login.js +73 -0
- package/config/router/navigation-guards/authentication.js +63 -0
- package/config/router/navigation-guards/index.js +15 -0
- package/config/router/navigation-guards/load-initial-settings.js +15 -0
- package/config/router/routes.js +487 -0
- package/config/settings.ts +38 -2
- package/config/store.js +7 -3
- package/config/table-headers.js +46 -1
- package/config/types.js +36 -16
- package/config/uiplugins.js +10 -5
- package/core/plugin-helpers.js +1 -1
- package/core/plugin.ts +2 -1
- package/core/plugins.js +289 -282
- package/creators/app/files/.eslintignore +0 -2
- package/creators/app/files/.vscode/settings.json +0 -1
- package/creators/pkg/files/.github/workflows/build-extension-catalog.yml +2 -6
- package/creators/pkg/files/.github/workflows/build-extension-charts.yml +2 -6
- package/creators/pkg/init +32 -0
- package/detail/__tests__/service.test.ts +62 -0
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/cis.cattle.io.clusterscan.vue +14 -3
- package/detail/fleet.cattle.io.gitrepo.vue +15 -9
- package/detail/namespace.vue +2 -2
- package/detail/networking.k8s.io.ingress.vue +52 -19
- package/detail/node.vue +20 -43
- package/detail/pod.vue +1 -68
- package/detail/provisioning.cattle.io.cluster.vue +2 -1
- package/detail/service.vue +1 -1
- package/detail/workload/index.vue +2 -15
- package/dialog/AddCustomBadgeDialog.vue +318 -161
- package/dialog/DeactivateDriverDialog.vue +118 -0
- package/dialog/RollbackWorkloadDialog.vue +2 -2
- package/dialog/RotateCertificatesDialog.vue +0 -21
- package/directives/clean-html.js +15 -0
- package/directives/clean-tooltip.js +32 -0
- package/directives/focus.js +41 -0
- package/directives/int-number.js +21 -0
- package/directives/positive-int-number.js +19 -0
- package/directives/trim-whitespace.js +19 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +3 -2
- package/edit/__tests__/kontainerDriver.test.ts +107 -0
- package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +12 -1
- package/edit/__tests__/management.cattle.io.setting.test.ts +2 -1
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +2 -3
- package/edit/__tests__/nodeDriver.test.ts +107 -0
- package/edit/__tests__/service.test.ts +1 -5
- package/edit/__tests__/ui.cattle.io.navlink.test.ts +3 -1
- package/edit/auth/AuthProviderWarningBanners.vue +34 -0
- package/edit/auth/__tests__/AuthProviderWarningBanners.test.ts +19 -0
- package/edit/auth/__tests__/azuread.test.ts +241 -0
- package/edit/auth/__tests__/oidc.test.ts +137 -0
- package/edit/auth/azuread.vue +133 -31
- package/edit/auth/github.vue +5 -17
- package/edit/auth/googleoauth.vue +5 -18
- package/edit/auth/ldap/index.vue +5 -17
- package/edit/auth/oidc.vue +143 -42
- package/edit/auth/saml.vue +5 -14
- package/edit/catalog.cattle.io.clusterrepo.vue +175 -20
- package/edit/cis.cattle.io.clusterscan.vue +5 -2
- package/edit/cis.cattle.io.clusterscanbenchmark.vue +41 -9
- package/edit/cloudcredential.vue +26 -4
- package/edit/configmap.vue +10 -4
- package/edit/fleet.cattle.io.gitrepo.vue +7 -4
- package/edit/helm.cattle.io.projecthelmchart.vue +29 -19
- package/edit/kontainerDriver.vue +65 -0
- package/edit/logging-flow/Match.vue +10 -9
- package/edit/logging-flow/index.vue +4 -19
- package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +232 -2
- package/edit/logging.banzaicloud.io.output/index.vue +43 -26
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +3 -3
- package/edit/management.cattle.io.project.vue +2 -1
- package/edit/management.cattle.io.setting.vue +20 -0
- package/edit/management.cattle.io.user.vue +2 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +10 -7
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +21 -16
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +1 -0
- package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +3 -0
- package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +2 -0
- package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +2 -0
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +2 -0
- package/edit/networking.k8s.io.ingress/Rules.vue +8 -3
- package/edit/networking.k8s.io.ingress/index.vue +64 -8
- package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +6 -2
- package/edit/networking.k8s.io.networkpolicy/__tests__/{PolicyRuleTarget.spec.ts → PolicyRuleTarget.test.ts} +45 -6
- package/edit/networking.k8s.io.networkpolicy/__tests__/utils/selectors.test.ts +1 -1
- package/edit/networking.k8s.io.networkpolicy/index.vue +2 -0
- package/edit/nodeDriver.vue +65 -0
- package/edit/persistentvolume/index.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +18 -9
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +165 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +1 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +0 -3
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +228 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +70 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +5 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/index.vue +21 -15
- package/edit/provisioning.cattle.io.cluster/rke2.vue +185 -114
- package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +67 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +19 -6
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +132 -0
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +7 -0
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +3 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -0
- package/edit/resources.cattle.io.backup.vue +139 -124
- package/edit/resources.cattle.io.restore.vue +146 -126
- package/edit/service.vue +1 -0
- package/edit/serviceaccount.vue +46 -4
- package/edit/workload/__tests__/Job.test.ts +1 -3
- package/edit/workload/__tests__/Upgrading.test.ts +2 -2
- package/edit/workload/mixins/workload.js +34 -1
- package/edit/workload/storage/emptyDir.vue +2 -2
- package/initialize/App.vue +75 -0
- package/initialize/app-extended.js +128 -0
- package/initialize/entry-helpers.js +549 -0
- package/initialize/entry.js +32 -0
- package/initialize/install-components.js +23 -0
- package/initialize/install-directives.js +59 -0
- package/initialize/install-plugins.js +123 -0
- package/list/__tests__/workload.test.ts +1 -1
- package/list/cis.cattle.io.clusterscan.vue +16 -10
- package/list/group.principal.vue +2 -2
- package/list/management.cattle.io.feature.vue +11 -7
- package/list/management.cattle.io.user.vue +36 -3
- package/list/networking.k8s.io.ingress.vue +36 -0
- package/list/node.vue +211 -73
- package/list/provisioning.cattle.io.cluster.vue +17 -4
- package/list/ui.cattle.io.navlink.vue +2 -2
- package/list/workload.vue +22 -0
- package/machine-config/__tests__/vmwarevsphere-pool-config-merge.test.ts +30 -0
- package/machine-config/__tests__/vmwarevsphere.test.ts +162 -59
- package/machine-config/amazonec2.vue +1 -1
- package/machine-config/azure.vue +38 -21
- package/machine-config/generic.vue +11 -15
- package/machine-config/vmwarevsphere-pool-config-merge.ts +25 -0
- package/machine-config/vmwarevsphere.vue +20 -11
- package/middleware/authenticated.js +9 -361
- package/mixins/__tests__/chart.test.ts +48 -6
- package/mixins/__tests__/create-edit-view.test.ts +2 -3
- package/mixins/auth-config.js +3 -2
- package/mixins/brand.js +75 -57
- package/mixins/chart.js +27 -13
- package/mixins/create-edit-view/index.js +2 -2
- package/mixins/fetch.client.js +42 -48
- package/mixins/labeled-form-element.ts +21 -1
- package/mixins/page-actions.js +7 -5
- package/mixins/resource-fetch-api-pagination.js +304 -0
- package/mixins/resource-fetch-namespaced.js +1 -1
- package/mixins/resource-fetch.js +46 -5
- package/models/__tests__/cluster.test.ts +44 -0
- package/models/__tests__/fleet.cattle.io.cluster.test.ts +36 -0
- package/models/__tests__/schema.tests.ts +24 -0
- package/models/__tests__/steve-schema.test.ts +73 -0
- package/models/__tests__/workload.test.ts +1 -1
- package/models/catalog.cattle.io.app.js +8 -0
- package/models/catalog.cattle.io.clusterrepo.js +9 -1
- package/models/catalog.cattle.io.uiplugin.js +7 -8
- package/models/cis.cattle.io.clusterscan.js +29 -8
- package/models/cloudcredential.js +9 -1
- package/models/cluster/node.js +4 -0
- package/models/cluster/schema.js +6 -0
- package/models/cluster.js +33 -0
- package/models/driver.js +62 -0
- package/models/fleet.cattle.io.cluster.js +23 -11
- package/models/fleet.cattle.io.gitrepo.js +10 -0
- package/models/helm.cattle.io.projecthelmchart.js +1 -1
- package/models/kontainerdriver.js +68 -0
- package/models/management/schema.js +6 -0
- package/models/management.cattle.io.authconfig.js +3 -2
- package/models/management.cattle.io.cluster.js +5 -4
- package/models/management.cattle.io.globalrole.js +2 -0
- package/models/management.cattle.io.user.js +67 -2
- package/models/monitoring.coreos.com.receiver.js +3 -1
- package/models/monitoring.coreos.com.route.js +1 -1
- package/models/networking.k8s.io.ingress.js +2 -1
- package/models/nodedriver.js +68 -0
- package/models/provisioning.cattle.io.cluster.js +34 -1
- package/models/schema.js +28 -7
- package/models/service.js +2 -0
- package/models/steve-schema.ts +254 -0
- package/models/workload.js +1 -0
- package/package.json +6 -5
- package/pages/about.vue +12 -5
- package/pages/account/index.vue +7 -2
- package/pages/auth/login.vue +106 -102
- package/pages/auth/logout.vue +2 -2
- package/pages/auth/setup.vue +57 -64
- package/pages/auth/verify.vue +17 -17
- package/pages/c/_cluster/apps/charts/chart.vue +54 -9
- package/pages/c/_cluster/apps/charts/index.vue +37 -13
- package/pages/c/_cluster/apps/charts/install.vue +4 -4
- package/pages/c/_cluster/auth/config/_id.vue +0 -6
- package/pages/c/_cluster/auth/config/index.vue +15 -9
- package/pages/c/_cluster/auth/roles/index.vue +8 -10
- package/pages/c/_cluster/auth/user.retention/index.vue +384 -0
- package/pages/c/_cluster/explorer/ConfigBadge.vue +13 -8
- package/pages/c/_cluster/explorer/EventsTable.vue +18 -0
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +181 -0
- package/pages/c/_cluster/explorer/index.vue +231 -72
- package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +69 -0
- package/pages/c/_cluster/explorer/tools/index.vue +12 -176
- package/pages/c/_cluster/fleet/index.vue +88 -93
- package/pages/c/_cluster/longhorn/__tests__/longhorn.index.test.ts +89 -0
- package/pages/c/_cluster/longhorn/index.vue +52 -17
- package/pages/c/_cluster/manager/cloudCredential/index.vue +18 -25
- package/pages/c/_cluster/manager/drivers/kontainerDriver/_id.vue +12 -0
- package/pages/c/_cluster/manager/drivers/kontainerDriver/create.vue +15 -0
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +94 -0
- package/pages/c/_cluster/manager/drivers/nodeDriver/_id.vue +12 -0
- package/pages/c/_cluster/manager/drivers/nodeDriver/create.vue +15 -0
- package/pages/c/_cluster/manager/drivers/nodeDriver/index.vue +63 -0
- package/pages/c/_cluster/manager/jwt.authentication/index.vue +235 -0
- package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +4 -0
- package/pages/c/_cluster/monitoring/index.vue +1 -17
- package/pages/c/_cluster/monitoring/route-receiver/index.vue +2 -2
- package/pages/c/_cluster/neuvector/index.vue +1 -0
- package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -0
- package/pages/c/_cluster/settings/banners.vue +86 -8
- package/pages/c/_cluster/settings/brand.vue +258 -36
- package/pages/c/_cluster/settings/index.vue +4 -4
- package/pages/c/_cluster/settings/links.vue +5 -3
- package/pages/c/_cluster/settings/performance.vue +71 -2
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +5 -2
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +10 -7
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +9 -6
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +11 -5
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +53 -18
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +36 -301
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +14 -6
- package/pages/c/_cluster/uiplugins/__tests__/SetupUIPlugins.test.ts +52 -106
- package/pages/c/_cluster/uiplugins/index.vue +38 -52
- package/pages/diagnostic.vue +1 -0
- package/pages/fail-whale.vue +103 -41
- package/pages/home.vue +81 -24
- package/pages/prefs.vue +8 -3
- package/pages/support/index.vue +12 -2
- package/plugins/clean-html-directive.js +5 -12
- package/plugins/clean-tooltip-directive.js +6 -31
- package/plugins/codemirror.js +0 -9
- package/plugins/dashboard-store/__tests__/mutations.test.ts +296 -313
- package/plugins/dashboard-store/actions.js +140 -32
- package/plugins/dashboard-store/getters.js +86 -39
- package/plugins/dashboard-store/index.js +0 -99
- package/plugins/dashboard-store/mutations.js +150 -48
- package/plugins/dashboard-store/resource-class.js +14 -109
- package/plugins/directives.js +6 -39
- package/plugins/ember-cookie.js +13 -0
- package/plugins/global-formatters.js +26 -5
- package/plugins/i18n.js +90 -56
- package/plugins/int-number.js +6 -20
- package/plugins/plugin.js +3 -3
- package/plugins/positive-int-number.js +6 -17
- package/plugins/steve/__tests__/{getters.spec.ts → getters.test.ts} +124 -31
- package/plugins/steve/__tests__/mutations.test.ts +49 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +109 -0
- package/plugins/steve/__tests__/utils/mutation.test.helpers.ts +105 -0
- package/plugins/steve/accept-or-reject-socket-message.ts +103 -0
- package/plugins/steve/actions.js +0 -1
- package/plugins/steve/getters.js +183 -63
- package/plugins/steve/hybrid-class.js +5 -1
- package/plugins/steve/mutations.js +29 -5
- package/plugins/steve/norman-class.js +123 -2
- package/{utils → plugins/steve}/projectAndNamespaceFiltering.utils.ts +28 -10
- package/plugins/steve/schema.d.ts +22 -0
- package/plugins/steve/steve-pagination-utils.ts +368 -0
- package/plugins/steve/subscribe.js +37 -75
- package/plugins/trim-whitespace.js +6 -34
- package/plugins/vue-js-modal.js +1 -1
- package/public/index.html +1 -0
- package/rancher-components/Accordion/Accordion.vue +3 -2
- package/rancher-components/BadgeState/BadgeState.vue +3 -3
- package/rancher-components/Banner/Banner.test.ts +1 -5
- package/rancher-components/Banner/Banner.vue +2 -2
- package/rancher-components/Card/Card.vue +4 -4
- package/rancher-components/Form/Checkbox/Checkbox.vue +4 -3
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +1 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +66 -30
- package/rancher-components/Form/Radio/RadioButton.test.ts +1 -3
- package/rancher-components/Form/Radio/RadioButton.vue +13 -7
- package/rancher-components/Form/Radio/RadioGroup.vue +4 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
- package/rancher-components/StringList/StringList.vue +8 -8
- package/rancher-components/components/Accordion/Accordion.vue +3 -2
- package/rancher-components/components/BadgeState/BadgeState.vue +3 -3
- package/rancher-components/components/Banner/Banner.test.ts +1 -5
- package/rancher-components/components/Banner/Banner.vue +2 -2
- package/rancher-components/components/Card/Card.vue +4 -4
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +4 -3
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +1 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +66 -30
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +1 -3
- package/rancher-components/components/Form/Radio/RadioButton.vue +13 -7
- package/rancher-components/components/Form/Radio/RadioGroup.vue +4 -3
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +9 -4
- package/rancher-components/components/StringList/StringList.vue +8 -8
- package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +27 -8
- package/scripts/clean +1 -1
- package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +11 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -0
- package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
- package/scripts/extension/helm/package/Dockerfile +1 -1
- package/scripts/extension/helm/scripts/patch +27 -0
- package/scripts/extension/publish +6 -6
- package/scripts/serve-pkgs +0 -2
- package/scripts/test-plugins-build.sh +6 -6
- package/scripts/vue-migrate.js +683 -0
- package/store/__tests__/catalog.test.ts +224 -0
- package/store/auth.js +23 -4
- package/store/aws.js +53 -6
- package/store/catalog.js +21 -5
- package/store/cru-resource.ts +26 -0
- package/store/customisation.js +35 -0
- package/store/features.js +6 -4
- package/store/index.js +132 -39
- package/store/plugins.js +8 -4
- package/store/type-map.js +143 -143
- package/store/type-map.utils.ts +226 -0
- package/tsconfig.json +0 -1
- package/tsconfig.paths.json +4 -1
- package/types/components/labeledSelect.ts +50 -0
- package/types/resources/settings.d.ts +32 -0
- package/types/{userPreferences.d.ts → resources/userPreferences.d.ts} +0 -1
- package/types/shell/index.d.ts +996 -782
- package/types/store/dashboard-store.types.ts +42 -0
- package/types/store/pagination.types.ts +457 -0
- package/types/store/type-map.ts +30 -0
- package/types/store/vuex.d.ts +9 -0
- package/types/vue-shim.d.ts +51 -0
- package/utils/__tests__/cluster.test.ts +20 -18
- package/utils/__tests__/create-yaml.test.ts +359 -2
- package/utils/__tests__/kontainer.test.ts +92 -0
- package/utils/__tests__/pod-security-admission.test.ts +1 -1
- package/utils/alertmanagerconfig.js +19 -0
- package/utils/array.ts +40 -1
- package/utils/async.ts +2 -0
- package/utils/auth.js +152 -4
- package/utils/axios.js +2 -2
- package/utils/banners.js +103 -0
- package/utils/cluster.js +1 -1
- package/utils/config.js +4 -0
- package/utils/create-yaml.js +54 -27
- package/utils/error.js +25 -0
- package/utils/formatter.js +5 -3
- package/utils/git.ts +1 -1
- package/utils/install-redirect.js +1 -1
- package/utils/kontainer.ts +186 -0
- package/utils/monitoring.js +2 -37
- package/utils/pagination-utils.ts +154 -0
- package/utils/pod-security-admission.ts +1 -1
- package/utils/router.js +86 -0
- package/utils/settings.ts +46 -0
- package/utils/socket.js +1 -0
- package/utils/time.js +1 -0
- package/utils/title.ts +3 -0
- package/utils/unit-tests/ChildRenderingRouterLinkStub.ts +36 -0
- package/utils/validators/formRules/__tests__/index.test.ts +21 -0
- package/utils/validators/formRules/index.ts +3 -0
- package/utils/validators/index.js +1 -0
- package/vue.config.js +376 -421
- package/assets/styles/vendor/vue-js-modal.scss +0 -16
- package/chart/monitoring/steps/uninstall-v1.vue +0 -135
- package/components/EventsTable.vue +0 -67
- package/components/TabbedLinks/index.vue +0 -94
- package/components/nuxt/nuxt-link.server.js +0 -16
- package/components/nuxt/nuxt.js +0 -101
- package/config/router.js +0 -425
- package/initialize/App.js +0 -152
- package/initialize/client.js +0 -734
- package/initialize/index.js +0 -287
- package/middleware/i18n.js +0 -10
- package/middleware/unauthenticated.js +0 -22
- package/mixins/v1-workload-metrics.js +0 -43
- package/pages/c/_cluster/apps/index.vue +0 -15
- package/pages/c/_cluster/auth/index.vue +0 -17
- package/pages/c/_cluster/index.vue +0 -15
- package/pages/c/_cluster/legacy/index.vue +0 -22
- package/pages/c/_cluster/manager/index.vue +0 -22
- package/pages/c/_cluster/mcapps/index.vue +0 -21
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +0 -232
- package/plugins/dashboard-store/rehydrate-all.js +0 -44
- package/plugins/index.js +0 -11
- package/plugins/portal-vue.js +0 -4
- package/plugins/portal.js +0 -4
- package/plugins/resize.js +0 -5
- package/plugins/shortkey.js +0 -4
- package/plugins/tooltip.js +0 -4
- package/plugins/v-select.js +0 -4
- package/utils/group.js +0 -70
- package/utils/nuxt.js +0 -638
- package/utils/router.scrollBehavior.js +0 -78
- /package/components/__tests__/{Collapse.spec.ts → Collapse.test.ts} +0 -0
- /package/models/__tests__/{node.ts → node.test.ts} +0 -0
- /package/plugins/steve/__tests__/{header-warnings.spec.ts → header-warnings.test.ts} +0 -0
- /package/plugins/steve/__tests__/{steve-class.spec.ts → steve-class.test.ts} +0 -0
- /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
- /package/rancher-components/components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
- /package/types/{pod-security-admission.ts → resources/pod-security-admission.ts} +0 -0
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
import { ANNOTATIONS_TO_IGNORE_REGEX, LABELS_TO_IGNORE_REGEX } from '@shell/config/labels-annotations';
|
|
2
2
|
import pickBy from 'lodash/pickBy';
|
|
3
3
|
import Vue from 'vue';
|
|
4
|
-
import { matchesSomeRegex } from '@shell/utils/string';
|
|
5
|
-
import Resource from '@shell/plugins/dashboard-store/resource-class';
|
|
6
4
|
import { findBy } from '@shell/utils/array';
|
|
5
|
+
import { matchesSomeRegex, coerceStringTypeToScalarType } from '@shell/utils/string';
|
|
6
|
+
import Resource, { DNS_LIKE_TYPES } from '@shell/plugins/dashboard-store/resource-class';
|
|
7
|
+
import { get } from '@shell/utils/object';
|
|
8
|
+
import {
|
|
9
|
+
displayKeyFor,
|
|
10
|
+
validateBoolean,
|
|
11
|
+
validateChars,
|
|
12
|
+
validateDnsLikeTypes,
|
|
13
|
+
validateLength,
|
|
14
|
+
} from '@shell/utils/validators';
|
|
15
|
+
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
16
|
+
import isString from 'lodash/isString';
|
|
17
|
+
import uniq from 'lodash/uniq';
|
|
18
|
+
|
|
19
|
+
import isEmpty from 'lodash/isEmpty';
|
|
20
|
+
|
|
21
|
+
const STRING_LIKE_TYPES = [
|
|
22
|
+
'string',
|
|
23
|
+
'date',
|
|
24
|
+
'blob',
|
|
25
|
+
'enum',
|
|
26
|
+
'multiline',
|
|
27
|
+
'masked',
|
|
28
|
+
'password',
|
|
29
|
+
'dnsLabel',
|
|
30
|
+
'hostname',
|
|
31
|
+
];
|
|
7
32
|
|
|
8
33
|
export default class NormanModel extends Resource {
|
|
9
34
|
setLabels(val) {
|
|
@@ -75,4 +100,100 @@ export default class NormanModel extends Resource {
|
|
|
75
100
|
|
|
76
101
|
return (entry.status || '').toLowerCase() === `${ withStatus }`.toLowerCase();
|
|
77
102
|
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check this instance is valid against
|
|
106
|
+
* - the schema's resource fields
|
|
107
|
+
* - also calls super.validationErrors
|
|
108
|
+
*/
|
|
109
|
+
validationErrors(data = this, opt = { ignoreFields: undefined }) {
|
|
110
|
+
const errors = [];
|
|
111
|
+
const {
|
|
112
|
+
type: originalType,
|
|
113
|
+
schema
|
|
114
|
+
} = data;
|
|
115
|
+
const type = normalizeType(originalType);
|
|
116
|
+
|
|
117
|
+
if ( !originalType ) {
|
|
118
|
+
// eslint-disable-next-line
|
|
119
|
+
console.warn(this.t('validation.noType'), data);
|
|
120
|
+
|
|
121
|
+
return errors;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if ( !schema ) {
|
|
125
|
+
// eslint-disable-next-line
|
|
126
|
+
// console.warn(this.t('validation.noSchema'), originalType, data);
|
|
127
|
+
|
|
128
|
+
return errors;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const fields = schema.resourceFields || {};
|
|
132
|
+
const keys = Object.keys(fields);
|
|
133
|
+
let field, key, val, displayKey;
|
|
134
|
+
|
|
135
|
+
for ( let i = 0 ; i < keys.length ; i++ ) {
|
|
136
|
+
const fieldErrors = [];
|
|
137
|
+
|
|
138
|
+
key = keys[i];
|
|
139
|
+
field = fields[key];
|
|
140
|
+
val = get(data, key);
|
|
141
|
+
displayKey = displayKeyFor(type, key, this.$rootGetters);
|
|
142
|
+
|
|
143
|
+
const fieldType = field?.type ? normalizeType(field.type) : null;
|
|
144
|
+
const valIsString = isString(val);
|
|
145
|
+
|
|
146
|
+
if ( opt.ignoreFields && opt.ignoreFields.includes(key) ) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if ( val === undefined ) {
|
|
151
|
+
val = null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (valIsString) {
|
|
155
|
+
if (fieldType) {
|
|
156
|
+
Vue.set(data, key, coerceStringTypeToScalarType(val, fieldType));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Empty strings on nullable string fields -> null
|
|
160
|
+
if ( field.nullable && val.length === 0 && STRING_LIKE_TYPES.includes(fieldType)) {
|
|
161
|
+
val = null;
|
|
162
|
+
|
|
163
|
+
Vue.set(data, key, val);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (fieldType === 'boolean') {
|
|
167
|
+
validateBoolean(val, field, displayKey, this.$rootGetters, fieldErrors);
|
|
168
|
+
} else {
|
|
169
|
+
validateLength(val, field, displayKey, this.$rootGetters, fieldErrors);
|
|
170
|
+
validateChars(val, field, displayKey, this.$rootGetters, fieldErrors);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (fieldErrors.length > 0) {
|
|
174
|
+
fieldErrors.push(this.t('validation.required', { key: displayKey }));
|
|
175
|
+
errors.push(...fieldErrors);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// IDs claim to be these but are lies...
|
|
180
|
+
if ( key !== 'id' && !isEmpty(val) && DNS_LIKE_TYPES.includes(fieldType) ) {
|
|
181
|
+
// DNS types should be lowercase
|
|
182
|
+
const tolower = (val || '').toLowerCase();
|
|
183
|
+
|
|
184
|
+
if ( tolower !== val ) {
|
|
185
|
+
val = tolower;
|
|
186
|
+
|
|
187
|
+
Vue.set(data, key, val);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
fieldErrors.push(...validateDnsLikeTypes(val, fieldType, displayKey, this.$rootGetters, fieldErrors));
|
|
191
|
+
}
|
|
192
|
+
errors.push(...fieldErrors);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const rootErrors = super.validationErrors(this, opt);
|
|
196
|
+
|
|
197
|
+
return uniq([...errors, ...rootErrors]);
|
|
198
|
+
}
|
|
78
199
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { NAMESPACE_FILTER_NS_FULL_PREFIX, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
|
|
2
2
|
import { getPerformanceSetting } from '@shell/utils/settings';
|
|
3
|
-
|
|
4
|
-
type Opt = { [key: string]: any, namespaced?: string[]}
|
|
3
|
+
import { ActionFindAllArgs } from '@shell/types/store/dashboard-store.types';
|
|
5
4
|
|
|
6
5
|
class ProjectAndNamespaceFiltering {
|
|
7
6
|
static param = 'projectsornamespaces'
|
|
@@ -9,7 +8,7 @@ class ProjectAndNamespaceFiltering {
|
|
|
9
8
|
/**
|
|
10
9
|
* Does the request `opt` definition require resources are fetched from a specific set namespaces/projects?
|
|
11
10
|
*/
|
|
12
|
-
isApplicable(opt:
|
|
11
|
+
isApplicable(opt: ActionFindAllArgs): boolean {
|
|
13
12
|
return Array.isArray(opt.namespaced);
|
|
14
13
|
}
|
|
15
14
|
|
|
@@ -37,7 +36,7 @@ class ProjectAndNamespaceFiltering {
|
|
|
37
36
|
/**
|
|
38
37
|
* Check if `opt` requires resources from specific ns/projects, if so return the required query param (x=y)
|
|
39
38
|
*/
|
|
40
|
-
checkAndCreateParam(opt:
|
|
39
|
+
checkAndCreateParam(opt: ActionFindAllArgs): string {
|
|
41
40
|
if (!this.isApplicable(opt)) {
|
|
42
41
|
return '';
|
|
43
42
|
}
|
|
@@ -45,17 +44,36 @@ class ProjectAndNamespaceFiltering {
|
|
|
45
44
|
return this.createParam(opt.namespaced);
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
public createParam(namespaceFilter: string[] | undefined): string {
|
|
49
48
|
if (!namespaceFilter || !namespaceFilter.length) {
|
|
50
49
|
return '';
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
.replace(
|
|
56
|
-
|
|
52
|
+
const namespaces = namespaceFilter.reduce((res, n) => {
|
|
53
|
+
const name = n
|
|
54
|
+
.replace(NAMESPACE_FILTER_NS_FULL_PREFIX, '')
|
|
55
|
+
.replace(NAMESPACE_FILTER_P_FULL_PREFIX, '');
|
|
56
|
+
|
|
57
|
+
if (name.startsWith('-')) {
|
|
58
|
+
res.exclude.push(n.substring(1, n.length));
|
|
59
|
+
} else {
|
|
60
|
+
res.include.push(name);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return res;
|
|
64
|
+
}, { include: [] as string[], exclude: [] as string[] });
|
|
65
|
+
|
|
66
|
+
let res = '';
|
|
67
|
+
|
|
68
|
+
if (namespaces.include.length) {
|
|
69
|
+
res = `${ ProjectAndNamespaceFiltering.param }=${ namespaces.include.join(',') }`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (namespaces.exclude.length) {
|
|
73
|
+
res = `${ ProjectAndNamespaceFiltering.param }!=${ namespaces.exclude.join(',') }`;
|
|
74
|
+
}
|
|
57
75
|
|
|
58
|
-
return
|
|
76
|
+
return res;
|
|
59
77
|
}
|
|
60
78
|
}
|
|
61
79
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
export interface SchemaAttributeColumn {
|
|
3
|
+
description: string,
|
|
4
|
+
field: string,
|
|
5
|
+
format: string,
|
|
6
|
+
name: string,
|
|
7
|
+
priority: number,
|
|
8
|
+
type: string,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SchemaAttribute {
|
|
12
|
+
columns: SchemaAttributeColumn[],
|
|
13
|
+
namespaced: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* At some point this will be properly typed, until then...
|
|
18
|
+
*/
|
|
19
|
+
export interface Schema {
|
|
20
|
+
id: string,
|
|
21
|
+
attributes: SchemaAttribute
|
|
22
|
+
}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
|
|
2
|
+
import { PaginationParam, PaginationFilterField, PaginationParamProjectOrNamespace, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
3
|
+
import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
|
|
4
|
+
import Namespace from '@shell/models/namespace';
|
|
5
|
+
import { uniq } from '@shell/utils/array';
|
|
6
|
+
import {
|
|
7
|
+
CONFIG_MAP, MANAGEMENT, NAMESPACE, NODE, POD
|
|
8
|
+
} from '@shell/config/types';
|
|
9
|
+
import { Schema } from 'plugins/steve/schema';
|
|
10
|
+
|
|
11
|
+
class NamespaceProjectFilters {
|
|
12
|
+
/**
|
|
13
|
+
* User needs all resources.... except if there's some settings which should remove resources in specific circumstances
|
|
14
|
+
*/
|
|
15
|
+
protected handlePrefAndSettingFilter(allNamespaces: Namespace[], showDynamicRancherNamespaces: boolean, productHidesSystemNamespaces: boolean): PaginationParamFilter[] {
|
|
16
|
+
// These are AND'd together
|
|
17
|
+
// Not ns 1 AND ns 2
|
|
18
|
+
return allNamespaces.reduce((res, ns) => {
|
|
19
|
+
// Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
|
|
20
|
+
const hideObscure = showDynamicRancherNamespaces ? false : ns.isObscure;
|
|
21
|
+
// Links to ns.isSystem and covers things like ns with system annotation, hardcoded list, etc
|
|
22
|
+
const hideSystem = productHidesSystemNamespaces ? ns.isSystem : false;
|
|
23
|
+
|
|
24
|
+
if (hideObscure || hideSystem) {
|
|
25
|
+
res.push(PaginationParamFilter.createSingleField({
|
|
26
|
+
field: 'metadata.namespace', value: ns.name, equals: false
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return res;
|
|
31
|
+
}, [] as PaginationParamFilter[]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* User needs either all user resources... or all system
|
|
36
|
+
*
|
|
37
|
+
* System resources revolve around the namespace's isSystem property
|
|
38
|
+
*
|
|
39
|
+
* Users resources are those not in system namespaces
|
|
40
|
+
*/
|
|
41
|
+
protected handleSystemOrUserFilter(allNamespaces: Namespace[], isAllSystem: boolean, isAllUser: boolean) {
|
|
42
|
+
const allSystem = allNamespaces.filter((ns) => ns.isSystem);
|
|
43
|
+
|
|
44
|
+
// > Neither of these use projectsOrNamespaces to avoid scenarios where the local cluster provides a namespace which has
|
|
45
|
+
// > a matching project... which could lead to results in the user project resource being included in the system filter
|
|
46
|
+
if (isAllSystem) {
|
|
47
|
+
// return resources in system ns 1 OR in system ns 2 ...
|
|
48
|
+
// &filter=metadata.namespace=system ns 1,metadata.namespace=system ns 2
|
|
49
|
+
return [PaginationParamFilter.createMultipleFields(
|
|
50
|
+
allSystem.map(
|
|
51
|
+
(ns) => new PaginationFilterField({ field: 'metadata.namespace', value: ns.name })
|
|
52
|
+
)
|
|
53
|
+
)];
|
|
54
|
+
} else { // if isAllUser
|
|
55
|
+
// return resources not in system ns 1 AND not in system ns 2 ...
|
|
56
|
+
// &filter=metadata.namespace!=system ns 1&filter=metadata.namespace!=system ns 2
|
|
57
|
+
return allSystem.map((ns) => PaginationParamFilter.createSingleField({
|
|
58
|
+
field: 'metadata.namespace', value: ns.name, equals: false
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* User needs resources in a set of projects or namespaces
|
|
65
|
+
*/
|
|
66
|
+
protected handleSelectionFilter(neu: string[], isLocalCluster: boolean) {
|
|
67
|
+
// User has one or more projects or namespaces. We can pass this straight through to projectsornamespaces
|
|
68
|
+
|
|
69
|
+
// return resources in project 1 OR namespace 2
|
|
70
|
+
// &projectsornamespaces=project 1,namespace 2
|
|
71
|
+
const projectsOrNamespaces = [
|
|
72
|
+
new PaginationParamProjectOrNamespace({ projectOrNamespace: neu })
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
if (isLocalCluster) {
|
|
76
|
+
// > As per `handleSystemOrUserFilter` above, we need to be careful of the local cluster where there's namespaces related to projects with the same id
|
|
77
|
+
// > In this case
|
|
78
|
+
// - We're including resources in the project and it's related namespace (via projectsornamespaces)
|
|
79
|
+
// - We're also then excluding resources in the related namespace (via below `filter`)
|
|
80
|
+
|
|
81
|
+
// Exclude resources NOT in projects namespace 1 AND not in projects namespace 2
|
|
82
|
+
// &filter=metadata.namespace!=pn1&filter=metadata.namespace!=pn2
|
|
83
|
+
return {
|
|
84
|
+
projectsOrNamespaces,
|
|
85
|
+
filters: neu
|
|
86
|
+
.filter((selection) => selection.startsWith(NAMESPACE_FILTER_P_FULL_PREFIX))
|
|
87
|
+
.map((projects) => PaginationParamFilter.createSingleField({
|
|
88
|
+
field: 'metadata.namespace', value: projects.replace(NAMESPACE_FILTER_P_FULL_PREFIX, ''), equals: false
|
|
89
|
+
}))
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { projectsOrNamespaces, filters: [] };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Helper functions for steve pagination
|
|
99
|
+
*/
|
|
100
|
+
class StevePaginationUtils extends NamespaceProjectFilters {
|
|
101
|
+
/**
|
|
102
|
+
* Filtering with the vai cache supports specific fields
|
|
103
|
+
* 1) Those listed here
|
|
104
|
+
* 2) Those references in the schema's attributes.fields list (which is used by generic lists)
|
|
105
|
+
*/
|
|
106
|
+
static VALID_FIELDS: { [type: string]: { field: string, startsWith?: boolean }[]} = {
|
|
107
|
+
'': [// all types
|
|
108
|
+
{ field: 'metadata.name' },
|
|
109
|
+
{ field: 'metadata.namespace' },
|
|
110
|
+
// { field: 'id' }, // Pending API support
|
|
111
|
+
// { field: 'metadata.state.name' }, // Pending API support
|
|
112
|
+
{ field: 'metadata.creationTimestamp' },
|
|
113
|
+
],
|
|
114
|
+
[NODE]: [
|
|
115
|
+
{ field: 'status.nodeInfo.kubeletVersion' },
|
|
116
|
+
{ field: 'status.nodeInfo.operatingSystem' },
|
|
117
|
+
],
|
|
118
|
+
[POD]: [
|
|
119
|
+
{ field: 'spec.containers.image' },
|
|
120
|
+
{ field: 'spec.nodeName' },
|
|
121
|
+
],
|
|
122
|
+
[MANAGEMENT.NODE]: [
|
|
123
|
+
{ field: 'status.nodeName' },
|
|
124
|
+
],
|
|
125
|
+
[CONFIG_MAP]: [
|
|
126
|
+
{ field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
|
|
127
|
+
],
|
|
128
|
+
[NAMESPACE]: [
|
|
129
|
+
{ field: 'metadata.labels[field.cattle.io/projectId]' }
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private convertArrayPath(path: string): string {
|
|
134
|
+
if (path.startsWith('metadata.fields.')) {
|
|
135
|
+
return `metadata.fields[${ path.substring(16) }]`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return path;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public createSortForPagination(sortByPath: string): string {
|
|
142
|
+
return this.convertArrayPath(sortByPath);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Given the selection of projects or namespaces come up with `filter` and `projectsornamespace` query params
|
|
147
|
+
*/
|
|
148
|
+
public createParamsFromNsFilter({
|
|
149
|
+
allNamespaces,
|
|
150
|
+
selection,
|
|
151
|
+
isAllNamespaces,
|
|
152
|
+
isLocalCluster,
|
|
153
|
+
showDynamicRancherNamespaces,
|
|
154
|
+
productHidesSystemNamespaces,
|
|
155
|
+
}: {
|
|
156
|
+
allNamespaces: Namespace[],
|
|
157
|
+
selection: string[],
|
|
158
|
+
/**
|
|
159
|
+
* There is no user provided filter
|
|
160
|
+
*/
|
|
161
|
+
isAllNamespaces: boolean,
|
|
162
|
+
/**
|
|
163
|
+
* Weird things be happening if the target cluster is local / upstream. Uses this to check what cluster we're in
|
|
164
|
+
*/
|
|
165
|
+
isLocalCluster: boolean,
|
|
166
|
+
/**
|
|
167
|
+
* Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
|
|
168
|
+
*/
|
|
169
|
+
showDynamicRancherNamespaces: boolean,
|
|
170
|
+
/**
|
|
171
|
+
* Links to ns.isSystem and covers things like ns with system annotation, hardcoded list, etc
|
|
172
|
+
*/
|
|
173
|
+
productHidesSystemNamespaces: boolean,
|
|
174
|
+
}): {
|
|
175
|
+
projectsOrNamespaces: PaginationParamProjectOrNamespace[],
|
|
176
|
+
filters: PaginationParamFilter[]
|
|
177
|
+
} {
|
|
178
|
+
// Hold up, why are we doing yet another way to convert the user's project / namespace filter to a set of something?
|
|
179
|
+
// - When doing this for local pagination `getActiveNamespaces` provides a full list of applicable namespaces.
|
|
180
|
+
// Lists then filter resource locally using those namespaces
|
|
181
|
+
// - Pagination cannot take this approach of 'gimme all resources in these namespaces' primarily for the 'Only User Namespaces' case
|
|
182
|
+
// - User could have 2k namespaces. This would result in 2k+ namespaces added to the url (namespace=1,namespace=2,namespace=3, etc)
|
|
183
|
+
// - Instead we do
|
|
184
|
+
// - All but not given settings - Gimme resources NOT in system or obscure namespaces
|
|
185
|
+
// - Only System Namespaces - Gimme resources in the system namespaces (which shouldn't be many namespaces)
|
|
186
|
+
// - Only User Namespaces - Gimme resources NOT in system namespaces
|
|
187
|
+
// - User selection - Gimme resources in specific Projects or Namespaces
|
|
188
|
+
if (isAllNamespaces && (showDynamicRancherNamespaces && !productHidesSystemNamespaces)) {
|
|
189
|
+
// No-op. Everything is returned
|
|
190
|
+
return {
|
|
191
|
+
projectsOrNamespaces: [],
|
|
192
|
+
filters: []
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// used to return resources in / not in projects/namespaces (entries are checked in both types)
|
|
197
|
+
// &projectsornamespaces=project 1,namespace 2
|
|
198
|
+
let projectsOrNamespaces: PaginationParamProjectOrNamespace[] = [];
|
|
199
|
+
// used to return resources in / not in namespaces
|
|
200
|
+
// &filter=metadata.namespace=abc
|
|
201
|
+
let filters: PaginationParamFilter[] = [];
|
|
202
|
+
|
|
203
|
+
if (!showDynamicRancherNamespaces || productHidesSystemNamespaces) {
|
|
204
|
+
// We need to hide dynamic namespaces ('c-', 'p-', etc) OR system namespaces
|
|
205
|
+
filters = this.handlePrefAndSettingFilter(allNamespaces, showDynamicRancherNamespaces, productHidesSystemNamespaces);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const isAllSystem = selection[0] === NAMESPACE_FILTER_ALL_SYSTEM;
|
|
209
|
+
const isAllUser = selection[0] === NAMESPACE_FILTER_ALL_USER;
|
|
210
|
+
|
|
211
|
+
if (selection.length === 1 && (isAllSystem || isAllUser)) {
|
|
212
|
+
// Filter by resources either in or not in system namespaces
|
|
213
|
+
filters.push(...this.handleSystemOrUserFilter(allNamespaces, isAllSystem, isAllUser ));
|
|
214
|
+
} else {
|
|
215
|
+
// User has one or more projects or namespaces
|
|
216
|
+
const res = this.handleSelectionFilter(selection, isLocalCluster);
|
|
217
|
+
|
|
218
|
+
projectsOrNamespaces = res.projectsOrNamespaces;
|
|
219
|
+
filters.push(...res.filters);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
projectsOrNamespaces,
|
|
224
|
+
filters
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
public createParamsForPagination(schema: Schema, opt: ActionFindPageArgs): string | undefined {
|
|
229
|
+
if (!opt.pagination) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const params: string[] = [];
|
|
234
|
+
const namespaceParam = this.convertPaginationParams(schema, opt.pagination.projectsOrNamespaces);
|
|
235
|
+
|
|
236
|
+
if (namespaceParam) {
|
|
237
|
+
params.push(namespaceParam);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (opt.pagination.page) {
|
|
241
|
+
params.push(`page=${ opt.pagination.page }`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (opt.pagination.pageSize) {
|
|
245
|
+
params.push(`pagesize=${ opt.pagination.pageSize }`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (opt.pagination.sort?.length) {
|
|
249
|
+
const validateFields = {
|
|
250
|
+
checked: new Array<string>(),
|
|
251
|
+
invalid: new Array<string>(),
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const joined = opt.pagination.sort
|
|
255
|
+
.map((s) => {
|
|
256
|
+
this.validateField(validateFields, schema, s.field);
|
|
257
|
+
|
|
258
|
+
return `${ s.asc ? '' : '-' }${ this.convertArrayPath(s.field) }`;
|
|
259
|
+
})
|
|
260
|
+
.join(',');
|
|
261
|
+
|
|
262
|
+
params.push(`sort=${ joined }`);
|
|
263
|
+
|
|
264
|
+
if (validateFields.invalid.length) {
|
|
265
|
+
console.warn(`Pagination API does not support sorting '${ schema.id }' by the requested fields: ${ uniq(validateFields.invalid).join(', ') }`); // eslint-disable-line no-console
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (opt.pagination.filters?.length) {
|
|
270
|
+
const filters = this.convertPaginationParams(schema, opt.pagination.filters);
|
|
271
|
+
|
|
272
|
+
if (filters) {
|
|
273
|
+
params.push(filters);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Note - There is a `limit` property that is by default 100,000. This can be disabled by using `limit=-1`,
|
|
278
|
+
// but we shouldn't be fetching any pages big enough to exceed the default
|
|
279
|
+
|
|
280
|
+
return params.join('&');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Check if the API supports filtering by this field
|
|
285
|
+
*/
|
|
286
|
+
private validateField(state: { checked: string[], invalid: string[]}, schema: Schema, field?: string) {
|
|
287
|
+
if (!field) {
|
|
288
|
+
return; // no field, so not invalid
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (state.checked.includes(field)) {
|
|
292
|
+
return; // already checked, exit early
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
state.checked.push(field);
|
|
296
|
+
|
|
297
|
+
// First check in our hardcoded list of supported filters
|
|
298
|
+
if ([
|
|
299
|
+
StevePaginationUtils.VALID_FIELDS[''], // Global
|
|
300
|
+
StevePaginationUtils.VALID_FIELDS[schema.id], // Type specific
|
|
301
|
+
].find((fields) => fields?.find((f) => {
|
|
302
|
+
if (f.startsWith) {
|
|
303
|
+
if (field.startsWith(f.field)) {
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
return field === f.field;
|
|
308
|
+
}
|
|
309
|
+
}))) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Then check in schema (the api automatically supports these)
|
|
314
|
+
if (!!schema?.attributes.columns.find(
|
|
315
|
+
// This isn't the most performant, but the string is tiny
|
|
316
|
+
(at) => at.field.replace('$.', '').replace('[', '.').replace(']', '') === field
|
|
317
|
+
)) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
state.invalid.push(field);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Convert our {@link PaginationParam} definition of params to a set of url params
|
|
326
|
+
*/
|
|
327
|
+
private convertPaginationParams(schema: Schema, filters: PaginationParam[] = []): string {
|
|
328
|
+
const validateFields = {
|
|
329
|
+
checked: new Array<string>(),
|
|
330
|
+
invalid: new Array<string>(),
|
|
331
|
+
};
|
|
332
|
+
const filterStrings = filters
|
|
333
|
+
.filter((filter) => !!filter.fields.length)
|
|
334
|
+
.map((filter) => {
|
|
335
|
+
const joined = filter.fields
|
|
336
|
+
.map((field) => {
|
|
337
|
+
if (field.field) {
|
|
338
|
+
// Check if the API supports filtering by this field
|
|
339
|
+
this.validateField(validateFields, schema, field.field);
|
|
340
|
+
|
|
341
|
+
const exactPartial = field.exact ? `'${ field.value }'` : field.value;
|
|
342
|
+
|
|
343
|
+
return `${ this.convertArrayPath(field.field) }${ field.equals ? '=' : '!=' }${ exactPartial }`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return field.value;
|
|
347
|
+
})
|
|
348
|
+
.join(','); // This means OR
|
|
349
|
+
|
|
350
|
+
return `${ filter.param }${ filter.equals ? '=' : '!=' }${ joined }`;
|
|
351
|
+
});
|
|
352
|
+
const unique = filterStrings.reduce((res, s) => {
|
|
353
|
+
res[s] = true;
|
|
354
|
+
|
|
355
|
+
return res;
|
|
356
|
+
}, { } as {[filterString: string] : boolean });
|
|
357
|
+
|
|
358
|
+
const res = Object.keys(unique).join('&'); // This means AND
|
|
359
|
+
|
|
360
|
+
if (validateFields.invalid.length) {
|
|
361
|
+
console.warn(`Pagination API does not support filtering '${ schema.id }' by the requested fields: ${ uniq(validateFields.invalid).join(', ') }`); // eslint-disable-line no-console
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return res;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export default new StevePaginationUtils();
|