@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
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { isArray } from '@shell/utils/array';
|
|
2
|
+
import { set, get, isEmpty } from '@shell/utils/object';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This function accepts a v3 cluster object and mutates its config field to sync values that were set outside Rancher (eg, when an imported cluster is created in its respective cloud provider).
|
|
6
|
+
* Values configured outside of rancher are not automatically propagated to the config field that the UI edits; they are reflected in the aksStatus/eksStatus/gkeStatus.upstreamSpec field.
|
|
7
|
+
* This function works in tandem with diffUpstreamSpec: the former runs when the edit form is initialized and the latter runs when the cluster is saved.
|
|
8
|
+
* @param configPrefix one of aks, eks, gke
|
|
9
|
+
* @param normanCluster v3 cluster object
|
|
10
|
+
*/
|
|
11
|
+
export function syncUpstreamConfig(configPrefix: string, normanCluster: {[key: string]: any}): void {
|
|
12
|
+
const configKey = `${ configPrefix }Config`;
|
|
13
|
+
const statusKey = `${ configPrefix }Status`;
|
|
14
|
+
|
|
15
|
+
const rancherConfig = normanCluster[configKey] || {};
|
|
16
|
+
const upstreamConfig = normanCluster?.[statusKey]?.upstreamSpec || {};
|
|
17
|
+
|
|
18
|
+
if (!isEmpty(upstreamConfig)) {
|
|
19
|
+
Object.keys(upstreamConfig).forEach((key) => {
|
|
20
|
+
if (isEmpty(rancherConfig[key]) && !isEmpty(upstreamConfig[key])) {
|
|
21
|
+
set(rancherConfig, key, upstreamConfig[key]);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Hosted provider (aks gke eks) edit functionality differs from other k8s resources
|
|
29
|
+
* see ui issue: https://github.com/rancher/rancher/issues/28541
|
|
30
|
+
* backend issue: https://github.com/rancher/rancher/issues/28422
|
|
31
|
+
* The below code is taken from the rancher/ui implementation https://github.com/rancher/ui/blob/master/app/models/cluster.js#L1368
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
function isEmptyObject(object: any) {
|
|
35
|
+
return Object.keys(object).length === 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isObject(val: any) {
|
|
39
|
+
return Object.prototype.toString.call(val) === '[object Object]';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isEmptyStringOrArray(val: any) {
|
|
43
|
+
return val === null || val === undefined || val === '' || (isArray(val) && val.length === 0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* this is NOT a generic object diff.
|
|
48
|
+
* It tries to be as generic as possible but it does make certain assumptions regarding nulls and emtpy arrays/objects
|
|
49
|
+
* if upstream is null and local aks config is empty we do not count this as a change
|
|
50
|
+
* additionally null values on the RHS will be ignored as null cant be sent in this case
|
|
51
|
+
* nodeGroups, nodePools, tags, and labels are not diffed
|
|
52
|
+
* @param upstream aksStatus.upstreamSpec
|
|
53
|
+
* @param local aksConfig
|
|
54
|
+
* @returns aksConfig containing only values which differ from upstream spec, excluding null values
|
|
55
|
+
*/
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
57
|
+
export function diffUpstreamSpec(upstream: any, local: any): any {
|
|
58
|
+
const delta = {};
|
|
59
|
+
const localKeys = Object.keys(local);
|
|
60
|
+
|
|
61
|
+
localKeys.forEach((key) => {
|
|
62
|
+
if (key === 'type') {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const upstreamMatch = get(upstream, key);
|
|
67
|
+
const localMatch = get(local, key);
|
|
68
|
+
|
|
69
|
+
if (key !== 'nodeGroups' && key !== 'nodePools') {
|
|
70
|
+
try {
|
|
71
|
+
if (JSON.stringify(upstreamMatch) === JSON.stringify(localMatch)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (key === 'nodeGroups' || key === 'nodePools' || key === 'tags' || key === 'labels') {
|
|
78
|
+
// Node Groups and Node Pools do not require a sync, we can safely send the entire object
|
|
79
|
+
// Tags and Labels (maps) are also included by default because what is present in the config is exactly what should be used on save and any equal maps would have been caught by the JSON isEqual comparison above
|
|
80
|
+
if (!isEmptyStringOrArray(localMatch)) {
|
|
81
|
+
// node groups need ALL data so short circut and send it all
|
|
82
|
+
set(delta, key, localMatch);
|
|
83
|
+
} else {
|
|
84
|
+
// all node groups were deleted
|
|
85
|
+
set(delta, key, []);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (isEmptyStringOrArray(upstreamMatch) || isEmptyObject(upstreamMatch)) {
|
|
92
|
+
if (isEmptyStringOrArray(localMatch) || isEmptyObject(localMatch)) {
|
|
93
|
+
if (upstreamMatch !== null && (isArray(localMatch) || isObject(localMatch))) {
|
|
94
|
+
// Empty Arrays and Empty Maps must be sent as such unless the upstream value is null, then the empty array or obj is just an init value
|
|
95
|
+
set(delta, key, localMatch);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
// upstream is empty, local is not, just set
|
|
99
|
+
set(delta, key, localMatch);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
if (localMatch !== null) {
|
|
103
|
+
// entry in og obj
|
|
104
|
+
if (isArray(upstreamMatch)) {
|
|
105
|
+
if (isArray(localMatch)) {
|
|
106
|
+
if (!isEmptyStringOrArray(localMatch) && localMatch.every((m: any) => isObject(m))) {
|
|
107
|
+
// You have more diffing to do
|
|
108
|
+
localMatch.forEach((match: any) => {
|
|
109
|
+
// our most likely candiate for a match is node group name, but lets check the others just incase.
|
|
110
|
+
const matchId = get(match, 'name') || get(match, 'id') || false;
|
|
111
|
+
|
|
112
|
+
if (matchId) {
|
|
113
|
+
let lmatchIdx = 0;
|
|
114
|
+
|
|
115
|
+
// we have soime kind of identifier to find a match in the upstream, so we can diff and insert to new array
|
|
116
|
+
const lMatch = upstreamMatch.find((l: any, idx: number) => {
|
|
117
|
+
const lmatchId = get(l, 'name') || get(l, 'id');
|
|
118
|
+
|
|
119
|
+
if (lmatchId === matchId) {
|
|
120
|
+
lmatchIdx = idx;
|
|
121
|
+
|
|
122
|
+
return l;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
if (lMatch) {
|
|
127
|
+
// we have a match in the upstream, meaning we've probably made updates to the object itself
|
|
128
|
+
const diffedMatch = diffUpstreamSpec(lMatch, match);
|
|
129
|
+
|
|
130
|
+
if (!isArray(get(delta, key))) {
|
|
131
|
+
set(delta, key, [diffedMatch]);
|
|
132
|
+
} else {
|
|
133
|
+
const target: any[] = delta[key as keyof typeof delta];
|
|
134
|
+
|
|
135
|
+
// diff and push into new array
|
|
136
|
+
target.splice(lmatchIdx, 0, diffedMatch);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// no match in upstream, new entry
|
|
140
|
+
if (!isArray(get(delta, key))) {
|
|
141
|
+
set(delta, key, [match]);
|
|
142
|
+
} else {
|
|
143
|
+
const target: any = delta[key as keyof typeof delta];
|
|
144
|
+
|
|
145
|
+
target.push(match);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
// no match id, all we can do is dumb add
|
|
150
|
+
if (!isArray(get(delta, key))) {
|
|
151
|
+
set(delta, key, [match]);
|
|
152
|
+
} else {
|
|
153
|
+
const target: any = delta[key as keyof typeof delta];
|
|
154
|
+
|
|
155
|
+
target.push(match);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
} else {
|
|
160
|
+
set(delta, key, localMatch);
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
set(delta, key, localMatch);
|
|
164
|
+
}
|
|
165
|
+
} else if (isObject(upstreamMatch)) {
|
|
166
|
+
if (!isEmptyStringOrArray(localMatch) && !isEmptyObject(localMatch)) {
|
|
167
|
+
if ((Object.keys(upstreamMatch) || []).length > 0) {
|
|
168
|
+
// You have more diffing to do
|
|
169
|
+
set(delta, key, diffUpstreamSpec(upstreamMatch, localMatch));
|
|
170
|
+
} else if (isEmptyObject(upstreamMatch)) {
|
|
171
|
+
// we had a map now we have an empty map
|
|
172
|
+
set(delta, key, {});
|
|
173
|
+
}
|
|
174
|
+
} else if (!isEmptyObject(upstreamMatch) && isEmptyObject(localMatch)) {
|
|
175
|
+
// we had a map now we have an empty map
|
|
176
|
+
set(delta, key, {});
|
|
177
|
+
}
|
|
178
|
+
} else { // upstreamMatch not an array or object
|
|
179
|
+
set(delta, key, localMatch);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return delta;
|
|
186
|
+
}
|
package/utils/monitoring.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Helpers for determining if V2 or v1 Monitoring are installed
|
|
2
2
|
|
|
3
|
-
import { SCHEMA, MONITORING,
|
|
3
|
+
import { SCHEMA, MONITORING, ENDPOINTS } from '@shell/config/types';
|
|
4
4
|
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
5
5
|
import { findBy } from '@shell/utils/array';
|
|
6
6
|
import { isEmpty } from '@shell/utils/object';
|
|
@@ -9,10 +9,7 @@ import { isEmpty } from '@shell/utils/object';
|
|
|
9
9
|
export function monitoringStatus() {
|
|
10
10
|
return {
|
|
11
11
|
monitoringStatus() {
|
|
12
|
-
const status = {
|
|
13
|
-
v1: haveV1Monitoring(this.$store.getters),
|
|
14
|
-
v2: haveV2Monitoring(this.$store.getters),
|
|
15
|
-
};
|
|
12
|
+
const status = { v2: haveV2Monitoring(this.$store.getters) };
|
|
16
13
|
|
|
17
14
|
status.installed = status.v1 || status.v2;
|
|
18
15
|
|
|
@@ -22,10 +19,6 @@ export function monitoringStatus() {
|
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
export function haveV2Monitoring(getters) {
|
|
25
|
-
// Can't have V2 and V1 monitoring installed, so if V1 is installed we know v2 is not
|
|
26
|
-
if (haveV1Monitoring(getters)) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
22
|
const inStore = getters['getStoreNameByProductId'];
|
|
30
23
|
|
|
31
24
|
// Just check for the pod monitors CRD
|
|
@@ -35,36 +28,8 @@ export function haveV2Monitoring(getters) {
|
|
|
35
28
|
return !!exists;
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
// For v1 Monitoring, the cluster object indicates presence via status.monitoringStatus
|
|
39
|
-
export function haveV1Monitoring(getters) {
|
|
40
|
-
const cluster = getters['currentCluster'];
|
|
41
|
-
|
|
42
|
-
return !!cluster?.status?.monitoringStatus;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
31
|
export const CATTLE_MONITORING_NAMESPACE = 'cattle-monitoring-system';
|
|
46
32
|
|
|
47
|
-
export async function haveV1MonitoringWorkloads(store) {
|
|
48
|
-
const workloadsByType = await Promise.all(
|
|
49
|
-
Object.values(WORKLOAD_TYPES).map((type) => store.dispatch('cluster/findAll', { type })
|
|
50
|
-
)
|
|
51
|
-
);
|
|
52
|
-
const workloads = workloadsByType.flat();
|
|
53
|
-
|
|
54
|
-
for (let i = 0; i < workloads.length; i++) {
|
|
55
|
-
const workload = workloads[i];
|
|
56
|
-
|
|
57
|
-
if (!isEmpty(workload?.spec?.template?.spec?.containers) &&
|
|
58
|
-
workload.spec.template.spec.containers.find((c) => c.image?.includes('quay.io/coreos/prometheus-operator') ||
|
|
59
|
-
c.image?.includes('rancher/coreos-prometheus-operator')) &&
|
|
60
|
-
workload?.metadata?.namespace !== CATTLE_MONITORING_NAMESPACE) {
|
|
61
|
-
return Promise.resolve(true);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return Promise.resolve(false);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
33
|
async function hasEndpointSubsets(store, id) {
|
|
69
34
|
if (store.getters['cluster/schemaFor'](ENDPOINTS)) {
|
|
70
35
|
const endpoints = await store.dispatch('cluster/findAll', { type: ENDPOINTS }) || [];
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { PaginationSettings } from '@shell/types/resources/settings';
|
|
2
|
+
import {
|
|
3
|
+
NAMESPACE_FILTER_ALL_USER as ALL_USER,
|
|
4
|
+
NAMESPACE_FILTER_ALL as ALL,
|
|
5
|
+
NAMESPACE_FILTER_ALL_SYSTEM as ALL_SYSTEM,
|
|
6
|
+
NAMESPACE_FILTER_NAMESPACED_YES as NAMESPACED_YES,
|
|
7
|
+
NAMESPACE_FILTER_NAMESPACED_NO as NAMESPACED_NO,
|
|
8
|
+
NAMESPACE_FILTER_KINDS,
|
|
9
|
+
NAMESPACE_FILTER_NS_FULL_PREFIX,
|
|
10
|
+
NAMESPACE_FILTER_P_FULL_PREFIX,
|
|
11
|
+
} from '@shell/utils/namespace-filter';
|
|
12
|
+
import { PaginationArgs, PaginationParam, PaginationSort } from '@shell/types/store/pagination.types';
|
|
13
|
+
import { sameArrayObjects } from '@shell/utils/array';
|
|
14
|
+
import { isEqual } from '@shell/utils/object';
|
|
15
|
+
import { STEVE_CACHE } from '@shell/store/features';
|
|
16
|
+
import { getPerformanceSetting } from '@shell/utils/settings';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper functions for server side pagination
|
|
20
|
+
*/
|
|
21
|
+
class PaginationUtils {
|
|
22
|
+
/**
|
|
23
|
+
* When a ns filter isn't one or more projects/namespaces... what are the valid values?
|
|
24
|
+
*
|
|
25
|
+
* This basically blocks 'Not in a Project'.. which would involve a projectsornamespaces param with every ns not in a project.
|
|
26
|
+
*/
|
|
27
|
+
validNsProjectFilters = [ALL, ALL_SYSTEM, ALL_USER, ALL_SYSTEM, NAMESPACE_FILTER_KINDS.NAMESPACE, NAMESPACE_FILTER_KINDS.PROJECT, NAMESPACED_YES, NAMESPACED_NO];
|
|
28
|
+
|
|
29
|
+
private getSettings({ rootGetters }: any): PaginationSettings {
|
|
30
|
+
const perf = getPerformanceSetting(rootGetters);
|
|
31
|
+
|
|
32
|
+
return perf.serverPagination;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
isSteveCacheEnabled({ rootGetters }: any): boolean {
|
|
36
|
+
// We always get Feature flags as part of start up (see `dispatch('features/loadServer')` in loadManagement)
|
|
37
|
+
return rootGetters['features/get']?.(STEVE_CACHE);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Is pagination enabled at a global level or for a specific resource
|
|
42
|
+
*/
|
|
43
|
+
isEnabled({ rootGetters }: any, enabledFor: {
|
|
44
|
+
store: string,
|
|
45
|
+
resource?: {
|
|
46
|
+
id: string,
|
|
47
|
+
}
|
|
48
|
+
}) {
|
|
49
|
+
// Cache must be enabled to support pagination api
|
|
50
|
+
if (!this.isSteveCacheEnabled({ rootGetters })) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const settings = this.getSettings({ rootGetters });
|
|
55
|
+
|
|
56
|
+
// No setting, not enabled
|
|
57
|
+
if (!settings?.enabled) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Missing required params, not enabled
|
|
62
|
+
if (!enabledFor) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const storeSettings = settings.stores?.[enabledFor.store];
|
|
67
|
+
|
|
68
|
+
// No pagination setting for target store, not enabled
|
|
69
|
+
if (!storeSettings) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Not interested in a resource, so just top level settings are checked
|
|
74
|
+
if (!enabledFor.resource) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Store says all resources are enabled
|
|
79
|
+
if (storeSettings.resources.enableAll) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// given a resource... but no id... invalid
|
|
84
|
+
if (!enabledFor.resource.id) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Store says only some (those that have pagination columns not from schema and no custom list)
|
|
89
|
+
const isGeneric =
|
|
90
|
+
!rootGetters['type-map/configuredHeaders'](enabledFor.resource.id) &&
|
|
91
|
+
!rootGetters['type-map/configuredPaginationHeaders'](enabledFor.resource.id) &&
|
|
92
|
+
!rootGetters['type-map/hasCustomList'](enabledFor.resource.id);
|
|
93
|
+
|
|
94
|
+
if (storeSettings.resources.enableSome.generic && isGeneric) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (storeSettings.resources.enableSome.enabled.includes(enabledFor.resource.id)) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
validateNsProjectFilters(nsProjectFilters: string[]) {
|
|
106
|
+
return nsProjectFilters?.every((f) => this.validateNsProjectFilter(f));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
validateNsProjectFilter(nsProjectFilter: string) {
|
|
110
|
+
if (nsProjectFilter.startsWith(NAMESPACE_FILTER_NS_FULL_PREFIX) || nsProjectFilter.startsWith(NAMESPACE_FILTER_P_FULL_PREFIX)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return this.validNsProjectFilters.includes(nsProjectFilter);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
paginationFilterEqual(a: PaginationParam, b: PaginationParam): boolean {
|
|
118
|
+
if (a.param !== b.param || a.equals !== b.equals) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return sameArrayObjects(a.fields, b.fields, true);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
paginationFiltersEqual(a: PaginationParam[], b: PaginationParam[]): boolean {
|
|
126
|
+
if (!!a && a?.length !== b?.length) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (let i = 0; i < a.length; i++) {
|
|
131
|
+
if (!this.paginationFilterEqual(a[i], b[i])) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
paginationEqual(a?: PaginationArgs, b?: PaginationArgs): boolean {
|
|
140
|
+
const {
|
|
141
|
+
filters: aFilter = [], sort: aSort = [], projectsOrNamespaces: aPN = [], ...aPrimitiveTypes
|
|
142
|
+
} = a || {};
|
|
143
|
+
const {
|
|
144
|
+
filters: bFilter = [], sort: bSort = [], projectsOrNamespaces: bPN = [], ...bPrimitiveTypes
|
|
145
|
+
} = b || {};
|
|
146
|
+
|
|
147
|
+
return isEqual(aPrimitiveTypes, bPrimitiveTypes) &&
|
|
148
|
+
this.paginationFiltersEqual(aFilter, bFilter) &&
|
|
149
|
+
this.paginationFiltersEqual(aPN, bPN) &&
|
|
150
|
+
sameArrayObjects<PaginationSort>(aSort, bSort, true);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default new PaginationUtils();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { reduce, filter, keys } from 'lodash';
|
|
2
2
|
import { PSALabelPrefix, PSALabelsNamespaces } from '@shell/config/pod-security-admission';
|
|
3
3
|
import { camelToTitle } from '@shell/utils/string';
|
|
4
|
-
import { PSA } from '@shell/types/pod-security-admission';
|
|
4
|
+
import { PSA } from '@shell/types/resources/pod-security-admission';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Return PSA labels present in the resource
|
package/utils/router.js
CHANGED
|
@@ -25,3 +25,89 @@ export function queryParamsFor(current, qp, defaults = {}) {
|
|
|
25
25
|
|
|
26
26
|
return query;
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
export function getClusterFromRoute(to) {
|
|
30
|
+
let cluster = to.params?.cluster;
|
|
31
|
+
|
|
32
|
+
if (!cluster) {
|
|
33
|
+
cluster = findMeta(to, 'cluster');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return cluster;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getProductFromRoute(to) {
|
|
40
|
+
let product = to.params?.product;
|
|
41
|
+
|
|
42
|
+
if ( !product ) {
|
|
43
|
+
const match = to.name?.match(/^c-cluster-([^-]+)/);
|
|
44
|
+
|
|
45
|
+
if ( match ) {
|
|
46
|
+
product = match[1];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// If still no product, see if the route indicates the product via route metadata
|
|
51
|
+
if (!product) {
|
|
52
|
+
product = findMeta(to, 'product');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return product;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const getPackageFromRoute = (route) => {
|
|
59
|
+
if (!route?.meta) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// Sometimes meta is an array... sometimes not
|
|
63
|
+
const arraySafe = Array.isArray(route.meta) ? route.meta : [route.meta];
|
|
64
|
+
|
|
65
|
+
return arraySafe.find((m) => !!m.pkg)?.pkg;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const getResourceFromRoute = (to) => {
|
|
69
|
+
let resource = to.params?.resource;
|
|
70
|
+
|
|
71
|
+
if (!resource) {
|
|
72
|
+
resource = findMeta(to, 'resource');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return resource;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Given a route it will look through the matching parent routes to see if any match the fn (predicate) criteria
|
|
80
|
+
*
|
|
81
|
+
* @param {*} to a VueRouter Route object
|
|
82
|
+
* @param {*} fn fn is a predicate which is passed a matched route. It will return true to indicate there was a matching route and false otherwise
|
|
83
|
+
* @returns true if a matching route was found, false otherwise
|
|
84
|
+
*/
|
|
85
|
+
export const routeMatched = (to, fn) => {
|
|
86
|
+
const matched = to?.matched || [];
|
|
87
|
+
|
|
88
|
+
return !!matched.find(fn);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Checks to see if the route requires authentication by taking a look at the route and it's parents 'meta' to see if it
|
|
93
|
+
* contains { requiresAuthentication: true }
|
|
94
|
+
* @param {*} to a VueRouter Route object
|
|
95
|
+
* @returns true if the route requires authentication, false otherwise
|
|
96
|
+
*/
|
|
97
|
+
export const routeRequiresAuthentication = (to) => {
|
|
98
|
+
return routeMatched(to, (matched) => matched.meta?.requiresAuthentication);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
function findMeta(route, key) {
|
|
102
|
+
if (route?.meta) {
|
|
103
|
+
const meta = Array.isArray(route.meta) ? route.meta : [route.meta];
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < meta.length; i++) {
|
|
106
|
+
if (meta[i][key]) {
|
|
107
|
+
return meta[i][key];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
package/utils/settings.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { MANAGEMENT } from '@shell/config/types';
|
|
2
2
|
import { Store } from 'vuex';
|
|
3
3
|
import { DEFAULT_PERF_SETTING, PerfSettings, SETTING } from '@shell/config/settings';
|
|
4
|
+
import { pluralize } from '@shell/utils/string';
|
|
5
|
+
import { _MULTI } from '@shell/plugins/dashboard-store/actions';
|
|
4
6
|
|
|
5
7
|
export const fetchOrCreateSetting = async(store: Store<any>, id: string, val: string, save = true): Promise<any> => {
|
|
6
8
|
let setting;
|
|
@@ -34,6 +36,50 @@ export const fetchSetting = async(store: Store<any>, id: string): Promise<any> =
|
|
|
34
36
|
return setting;
|
|
35
37
|
};
|
|
36
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Carefully fetch mgmt settings
|
|
41
|
+
*
|
|
42
|
+
* Ensures that
|
|
43
|
+
* - Concurrent calls to this function will only result in a single http request
|
|
44
|
+
* - Subsequent calls, when either logged in or logged out, will only result in a single http request
|
|
45
|
+
* - Logged out call will fetch partial settings, after logging in another call will fetch all settings
|
|
46
|
+
*
|
|
47
|
+
* Will be used in many places, particularly multiple times when loading the dashboard
|
|
48
|
+
*
|
|
49
|
+
* Note - We need to specify the url for cases where it can't be determined (i.e. we haven't fetched schemas)
|
|
50
|
+
*/
|
|
51
|
+
export const fetchInitialSettings = async(store: Store<any>): Promise<any> => {
|
|
52
|
+
const generation = store.getters['management/generation'](MANAGEMENT.SETTING);
|
|
53
|
+
// We use this as it copies the previous mechanism this was based on (in findAll)
|
|
54
|
+
// There is the getter `auth/loggedInAs` (which is set given `fromHeader`), but that's initialised after the first call to here (see `authenticated`)
|
|
55
|
+
const header = store.getters['auth/fromHeader'];
|
|
56
|
+
const authed = `${ header }` === 'true' || `${ header }` === 'none';
|
|
57
|
+
|
|
58
|
+
if (authed) {
|
|
59
|
+
// We're authed, we will always get the full list
|
|
60
|
+
return await store.dispatch('management/findAll', {
|
|
61
|
+
type: MANAGEMENT.SETTING,
|
|
62
|
+
opt: { url: `/v1/${ pluralize(MANAGEMENT.SETTING) }` }
|
|
63
|
+
} );
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!generation) {
|
|
67
|
+
// We're not authed, and haven't previously fetched settings (no generation)
|
|
68
|
+
// Fetch settings, put them in the store, but don't say we've got all yet (so subsequent calls will run)
|
|
69
|
+
return await store.dispatch('management/findAll', {
|
|
70
|
+
type: MANAGEMENT.SETTING,
|
|
71
|
+
opt: {
|
|
72
|
+
url: `/v1/${ pluralize(MANAGEMENT.SETTING) }`,
|
|
73
|
+
load: _MULTI,
|
|
74
|
+
redirectUnauthorized: false
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// We're not authed, but have a previous value, no need to make a http request to fetch again
|
|
80
|
+
return store.getters['management/all'](MANAGEMENT.SETTING);
|
|
81
|
+
};
|
|
82
|
+
|
|
37
83
|
export const setSetting = async(store: Store<any>, id: string, val: string): Promise<any> => {
|
|
38
84
|
const setting = await fetchOrCreateSetting(store, id, val, false);
|
|
39
85
|
|
package/utils/socket.js
CHANGED
|
@@ -27,6 +27,7 @@ export const EVENT_DISCONNECT_ERROR = 'disconnect_error';
|
|
|
27
27
|
|
|
28
28
|
export const NO_WATCH = 'NO_WATCH';
|
|
29
29
|
export const NO_SCHEMA = 'NO_SCHEMA';
|
|
30
|
+
export const NO_PERMS = 'NO_PERMS';
|
|
30
31
|
export const REVISION_TOO_OLD = 'TOO_OLD';
|
|
31
32
|
|
|
32
33
|
export default class Socket extends EventTarget {
|
package/utils/time.js
CHANGED
package/utils/title.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RouterLinkStub } from '@vue/test-utils';
|
|
2
|
+
import { NavigationFailure, Route } from 'vue-router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* See {@link RouterLinkSlotArgument} in vue-router
|
|
6
|
+
*/
|
|
7
|
+
export interface RouterLinkSlotArgumentOptional {
|
|
8
|
+
href?: string;
|
|
9
|
+
route?: Route;
|
|
10
|
+
navigate?: (e?: MouseEvent) => Promise<undefined | NavigationFailure>;
|
|
11
|
+
isActive?: boolean;
|
|
12
|
+
isExactActive?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This is a workaround because VueUtils RouterLinkStub doesn't currently support the slot api.
|
|
17
|
+
*
|
|
18
|
+
* See @link https://github.com/vuejs/vue-test-utils/issues/1803#issuecomment-940884170
|
|
19
|
+
*
|
|
20
|
+
* @param slotProps Provide arguments that you want passed to the child rendered by router-link
|
|
21
|
+
* @returns A stub
|
|
22
|
+
*/
|
|
23
|
+
export function createChildRenderingRouterLinkStub(slotProps?: RouterLinkSlotArgumentOptional): typeof RouterLinkStub | any {
|
|
24
|
+
return {
|
|
25
|
+
...RouterLinkStub,
|
|
26
|
+
render() {
|
|
27
|
+
return this.$scopedSlots.default({
|
|
28
|
+
href: slotProps?.href || '',
|
|
29
|
+
route: slotProps?.route || ({} as any),
|
|
30
|
+
navigate: slotProps?.navigate || (() => {}),
|
|
31
|
+
isActive: slotProps?.isActive || false,
|
|
32
|
+
isExactActive: slotProps?.isExactActive || false,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -103,6 +103,27 @@ describe('formRules', () => {
|
|
|
103
103
|
);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
+
describe('alphanumeric', () => {
|
|
107
|
+
const message = JSON.stringify({ message: 'validation.alphanumeric', key: 'testDisplayKey' });
|
|
108
|
+
const testCases = [
|
|
109
|
+
['', undefined],
|
|
110
|
+
['aaaAAAA111', undefined],
|
|
111
|
+
['aaaAAAA111//', message],
|
|
112
|
+
['/', message],
|
|
113
|
+
['+1', message],
|
|
114
|
+
[undefined, undefined]
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
it.each(testCases)(
|
|
118
|
+
'should return undefined or correct message based on the provided url',
|
|
119
|
+
(val, expected) => {
|
|
120
|
+
const formRuleResult = formRules.alphanumeric(val);
|
|
121
|
+
|
|
122
|
+
expect(formRuleResult).toStrictEqual(expected);
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
106
127
|
it('"interval" : returns undefined when valid hour interval value is supplied', () => {
|
|
107
128
|
const testValue = '5h';
|
|
108
129
|
const formRuleResult = formRules.interval(testValue);
|
|
@@ -145,6 +145,8 @@ export default function(t: Translation, { key = 'Value' }: ValidationOptions): {
|
|
|
145
145
|
|
|
146
146
|
const url: Validator = (val: string) => val && !isUrl(val) ? t('validation.setting.serverUrl.url') : undefined;
|
|
147
147
|
|
|
148
|
+
const alphanumeric: Validator = (val: string) => val && !/^[a-zA-Z0-9]+$/.test(val) ? t('validation.alphanumeric', { key }) : undefined;
|
|
149
|
+
|
|
148
150
|
const interval: Validator = (val: string) => !/^\d+[hms]$/.test(val) ? t('validation.monitoring.route.interval', { key }) : undefined;
|
|
149
151
|
|
|
150
152
|
const containerImage: Validator = (val: any) => !val?.image ? t('workload.validation.containerImage', { name: val.name }) : undefined;
|
|
@@ -458,6 +460,7 @@ export default function(t: Translation, { key = 'Value' }: ValidationOptions): {
|
|
|
458
460
|
|
|
459
461
|
return {
|
|
460
462
|
absolutePath,
|
|
463
|
+
alphanumeric,
|
|
461
464
|
backupTarget,
|
|
462
465
|
betweenLengths,
|
|
463
466
|
betweenValues,
|
|
@@ -47,6 +47,7 @@ export function validateLength(val, field, displayKey, getters, errors = []) {
|
|
|
47
47
|
return errors;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// i18n-uses validation.*.exactly, validation.*.between, validation.*.min, validation.*.max
|
|
50
51
|
const lengthKey = (type.indexOf('array[') === 0 ? 'arrayLength' : 'stringLength');
|
|
51
52
|
|
|
52
53
|
// String and array length:
|