@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/impl/apis.ts +6 -0
- package/apis/index.ts +26 -0
- package/apis/intf/resources-api/cluster-api.ts +18 -0
- package/apis/intf/resources-api/mgmt-api.ts +15 -0
- package/apis/intf/resources-api/resource-base.ts +107 -0
- package/apis/intf/resources-api/resource-constants.ts +147 -0
- package/apis/intf/resources-api/resources-api.ts +143 -0
- package/apis/intf/resources.ts +49 -0
- package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
- package/apis/intf/shell-api/proxy.ts +216 -0
- package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
- package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
- package/apis/intf/shell.ts +12 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
- package/apis/resources/index.ts +22 -0
- package/apis/resources/resources-api-class.ts +187 -0
- package/apis/shell/__tests__/proxy.test.ts +369 -0
- package/apis/shell/index.ts +8 -1
- package/apis/shell/modal.ts +4 -1
- package/apis/shell/notifications.ts +9 -6
- package/apis/shell/proxy.ts +256 -0
- package/apis/shell/slide-in.ts +4 -1
- package/apis/vue-shim.d.ts +2 -1
- package/assets/data/aws-regions.json +4 -0
- package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/fonts/_fontstack.scss +132 -8
- package/assets/styles/global/_layout.scss +4 -0
- package/assets/translations/en-us.yaml +165 -45
- package/assets/translations/zh-hans.yaml +1 -7
- package/chart/monitoring/ClusterSelector.vue +0 -21
- package/chart/monitoring/index.vue +10 -1
- package/chart/monitoring/prometheus/index.vue +6 -3
- package/components/ActionDropdownShell.vue +2 -1
- package/components/CruResource.vue +161 -14
- package/components/CruResourceFooter.vue +9 -5
- package/components/ExplorerMembers.vue +8 -4
- package/components/ExplorerProjectsNamespaces.vue +11 -7
- package/components/GrowlManager.vue +4 -0
- package/components/InstallHelmCharts.vue +2 -2
- package/components/LandingPagePreference.vue +14 -5
- package/components/MgmtNodeList.vue +184 -0
- package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
- package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
- package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
- package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +17 -1
- package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
- package/components/Resource/Detail/Metadata/index.vue +6 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
- package/components/Resource/Detail/SpacedRow.vue +3 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -11
- package/components/ResourceDetail/index.vue +1 -1
- package/components/ResourceList/Masthead.vue +19 -9
- package/components/ResourceList/index.vue +82 -1
- package/components/RichTranslation.vue +5 -2
- package/components/SelectIconGrid.vue +0 -10
- package/components/Setting.vue +1 -0
- package/components/SingleClusterInfo.vue +1 -0
- package/components/SortableTable/__tests__/sorting.test.ts +126 -0
- package/components/SortableTable/index.vue +6 -9
- package/components/SortableTable/selection.js +23 -5
- package/components/SortableTable/sorting.js +6 -3
- package/components/SubtleLink.vue +31 -6
- package/components/Tabbed/Tab.vue +29 -3
- package/components/Tabbed/index.vue +25 -3
- package/components/TableOfContents/TableOfContents.vue +109 -0
- package/components/TableOfContents/composables.ts +258 -0
- package/components/Window/ContainerShell.vue +21 -11
- package/components/Window/__tests__/ContainerShell.test.ts +107 -37
- package/components/Wizard.vue +23 -17
- package/components/fleet/AppCoChartGrid.vue +401 -0
- package/components/fleet/AppCoEmptyState.vue +127 -0
- package/components/fleet/AppCoPageHeader.vue +119 -0
- package/components/fleet/AppCoVersionSelect.vue +70 -0
- package/components/fleet/FleetBundles.vue +100 -12
- package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
- package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
- package/components/fleet/FleetClusterTargets/index.vue +226 -161
- package/components/fleet/FleetIntro.vue +7 -3
- package/components/fleet/FleetNoWorkspaces.vue +7 -3
- package/components/fleet/FleetSecretSelector.vue +5 -3
- package/components/fleet/FleetValuesFrom.vue +8 -2
- package/components/fleet/GitRepoTargetTab.vue +0 -2
- package/components/fleet/HelmOpAdvancedTab.vue +19 -53
- package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
- package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
- package/components/fleet/HelmOpResourcesSection.vue +82 -0
- package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
- package/components/fleet/HelmOpTargetTab.vue +64 -60
- package/components/fleet/HelmOpValuesTab.vue +129 -105
- package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
- package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
- package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +402 -115
- package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
- package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
- package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
- package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
- package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
- package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
- package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
- package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
- package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
- package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
- package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
- package/components/fleet/dashboard/Empty.vue +8 -4
- package/components/fleet/dashboard/ResourceCard.vue +28 -0
- package/components/fleet/dashboard/ResourceDetails.vue +28 -0
- package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
- package/components/form/ArrayList.vue +61 -4
- package/components/form/KeyValue.vue +23 -2
- package/components/form/LabeledSelect.vue +59 -4
- package/components/form/Labels.vue +22 -3
- package/components/form/NameNsDescription.vue +24 -5
- package/components/form/ResourceTabs/index.vue +1 -0
- package/components/form/Security.vue +6 -2
- package/components/form/WorkloadPorts.vue +2 -7
- package/components/form/__tests__/NameNsDescription.test.ts +75 -0
- package/components/form/__tests__/Security.test.ts +76 -0
- package/components/formatter/Autoscaler.vue +4 -4
- package/components/formatter/ClusterKubeVersion.vue +27 -0
- package/components/formatter/ClusterLink.vue +1 -7
- package/components/formatter/ClusterProvider.vue +6 -10
- package/components/formatter/FleetSummaryGraph.vue +0 -3
- package/components/formatter/InternalExternalIP.vue +10 -4
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/PodsUsage.vue +2 -2
- package/components/formatter/ServiceTargets.vue +26 -7
- package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
- package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
- package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
- package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
- package/components/nav/Header.vue +4 -0
- package/components/nav/NamespaceFilter.vue +2 -2
- package/components/nav/TopLevelMenu.helper.ts +15 -3
- package/components/nav/TopLevelMenu.vue +22 -6
- package/components/nav/__tests__/Header.test.ts +15 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +263 -21
- package/components/templates/default.vue +9 -4
- package/components/templates/home.vue +23 -0
- package/components/templates/plain.vue +23 -0
- package/components/templates/standalone.vue +17 -0
- package/composables/useFormValidation.ts +93 -0
- package/composables/useHelmOpResources.test.ts +56 -0
- package/composables/useHelmOpResources.ts +32 -0
- package/composables/useStateColor.test.ts +325 -0
- package/composables/useStateColor.ts +128 -0
- package/composables/useVeeValidateField.test.ts +159 -0
- package/composables/useVeeValidateField.ts +67 -0
- package/config/home-links.js +1 -1
- package/config/labels-annotations.js +1 -0
- package/config/pagination-table-headers.js +18 -1
- package/config/product/explorer.js +17 -4
- package/config/product/manager.js +84 -21
- package/config/router/index.js +16 -0
- package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
- package/config/router/navigation-guards/authentication.js +10 -4
- package/config/router/routes.js +26 -6
- package/config/settings.ts +0 -2
- package/config/table-headers.js +23 -5
- package/config/types.js +11 -1
- package/core/__tests__/plugin-products.test.ts +904 -20
- package/core/plugin-products-base.ts +110 -10
- package/core/plugin-products.ts +4 -0
- package/core/plugin-types.ts +194 -31
- package/core/plugin.ts +18 -7
- package/core/productDebugger.js +9 -4
- package/core/types-provisioning.ts +77 -31
- package/core/types.ts +72 -22
- package/detail/__tests__/pod.test.ts +41 -0
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
- package/detail/__tests__/workload.test.ts +3 -152
- package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
- package/detail/harvesterhci.io.management.cluster.vue +6 -2
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +34 -14
- package/detail/workload/index.vue +12 -55
- package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
- package/edit/auth/__tests__/azuread.test.ts +247 -39
- package/edit/auth/__tests__/github.test.ts +234 -0
- package/edit/auth/__tests__/oidc.test.ts +26 -6
- package/edit/auth/__tests__/saml.test.ts +196 -0
- package/edit/auth/azuread.vue +197 -56
- package/edit/auth/github.vue +72 -13
- package/edit/auth/ldap/__tests__/index.test.ts +206 -0
- package/edit/auth/ldap/config.vue +8 -0
- package/edit/auth/ldap/index.vue +75 -1
- package/edit/auth/oidc.vue +119 -73
- package/edit/auth/saml.vue +76 -12
- package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
- package/edit/fleet.cattle.io.helmop.vue +491 -136
- package/edit/management.cattle.io.user.vue +5 -2
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
- package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
- package/edit/networking.k8s.io.ingress/index.vue +75 -20
- package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/rke2.vue +92 -14
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +22 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
- package/edit/secret/__tests__/ssh.test.ts +5 -6
- package/edit/secret/basic.vue +31 -0
- package/edit/secret/index.vue +68 -17
- package/edit/secret/registry.vue +38 -0
- package/edit/secret/ssh.vue +29 -0
- package/edit/secret/tls.vue +30 -0
- package/edit/service.vue +4 -4
- package/edit/workload/Upgrading.vue +3 -3
- package/edit/workload/__tests__/Upgrading.test.ts +6 -9
- package/edit/workload/mixins/workload.js +2 -1
- package/list/fleet.cattle.io.bundle.vue +7 -104
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
- package/list/group.principal.vue +5 -4
- package/list/harvesterhci.io.management.cluster.vue +8 -9
- package/list/management.cattle.io.user.vue +12 -9
- package/list/provisioning.cattle.io.cluster.vue +268 -180
- package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
- package/mixins/__tests__/auth-config.test.ts +90 -0
- package/mixins/__tests__/chart.test.ts +206 -0
- package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
- package/mixins/auth-config.js +7 -0
- package/mixins/brand.js +2 -1
- package/mixins/chart.js +22 -9
- package/mixins/child-hook.js +12 -6
- package/mixins/create-edit-view/impl.js +5 -3
- package/mixins/resource-fetch-api-pagination.js +62 -6
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
- package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
- package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
- package/models/__tests__/fleet-application.test.ts +175 -0
- package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
- package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
- package/models/__tests__/management.cattle.io.node.ts +28 -5
- package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
- package/models/__tests__/namespace.test.ts +36 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +81 -11
- package/models/__tests__/workload.test.ts +401 -26
- package/models/base-cluster.x-k8s.io.js +26 -0
- package/models/catalog.cattle.io.clusterrepo.js +28 -4
- package/models/cluster.js +1 -1
- package/models/cluster.x-k8s.io.machine.js +4 -22
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
- package/models/cluster.x-k8s.io.machineset.js +2 -20
- package/models/compliance.cattle.io.clusterscan.js +165 -2
- package/models/ext.cattle.io.kubeconfig.ts +4 -7
- package/models/fleet-application.js +7 -1
- package/models/fleet.cattle.io.helmop.js +20 -1
- package/models/management.cattle.io.cluster.js +434 -41
- package/models/management.cattle.io.node.js +50 -7
- package/models/management.cattle.io.nodepool.js +1 -1
- package/models/namespace.js +1 -1
- package/models/networking.k8s.io.ingress.js +12 -4
- package/models/pod.js +33 -1
- package/models/provisioning.cattle.io.cluster.js +51 -334
- package/models/rke.cattle.io.etcdsnapshot.js +1 -2
- package/models/workload.js +108 -13
- package/models/workload.service.js +5 -0
- package/package.json +22 -39
- package/pages/__tests__/readme.test.ts +49 -0
- package/pages/about.vue +5 -6
- package/pages/auth/login.vue +0 -35
- package/pages/auth/setup.vue +13 -3
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
- package/pages/c/_cluster/apps/charts/chart.vue +62 -9
- package/pages/c/_cluster/apps/charts/index.vue +48 -10
- package/pages/c/_cluster/apps/charts/install.vue +122 -113
- package/pages/c/_cluster/auth/roles/index.vue +5 -4
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
- package/pages/c/_cluster/explorer/index.vue +5 -49
- package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
- package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
- package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
- package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
- package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
- package/pages/c/_cluster/fleet/application/create.vue +187 -136
- package/pages/c/_cluster/fleet/application/index.vue +5 -3
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
- package/pages/c/_cluster/fleet/index.vue +2 -2
- package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
- package/pages/c/_cluster/istio/index.vue +21 -6
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +815 -2
- package/pages/c/_cluster/uiplugins/index.vue +218 -197
- package/pages/diagnostic.vue +13 -17
- package/pages/fail-whale.vue +30 -7
- package/pages/home.vue +93 -306
- package/pages/readme.vue +88 -0
- package/plugins/clean-html.d.ts +9 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +181 -0
- package/plugins/dashboard-store/actions.js +40 -18
- package/plugins/dashboard-store/resource-class.js +67 -9
- package/plugins/steve/__tests__/actions.test.ts +212 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
- package/plugins/steve/actions.js +96 -0
- package/plugins/steve/steve-pagination-utils.ts +12 -4
- package/plugins/steve/subscribe.js +35 -5
- package/rancher-components/Accordion/Accordion.vue +53 -9
- package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
- package/rancher-components/Form/Radio/RadioButton.vue +17 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
- package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
- package/rancher-components/RcButton/RcButton.test.ts +140 -1
- package/rancher-components/RcButton/RcButton.vue +126 -17
- package/rancher-components/RcButton/types.ts +3 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
- package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
- package/rancher-components/RcSection/RcSection.vue +28 -3
- package/scripts/extension/helm/package/Dockerfile +1 -1
- package/scripts/test-plugins-build.sh +2 -1
- package/store/__tests__/catalog.test.ts +115 -1
- package/store/__tests__/notifications.test.ts +434 -0
- package/store/__tests__/type-map.test.ts +556 -1
- package/store/action-menu.js +8 -3
- package/store/auth.js +1 -1
- package/store/aws.js +27 -16
- package/store/catalog.js +84 -3
- package/store/digitalocean.js +20 -38
- package/store/index.js +2 -0
- package/store/linode.js +25 -40
- package/store/plugins.js +7 -4
- package/store/pnap.js +1 -0
- package/store/type-map.js +111 -29
- package/tsconfig.paths.json +8 -8
- package/types/components/buttonGroup.ts +5 -0
- package/types/kube/kube-api.ts +14 -1
- package/types/rancher/steve.api.ts +12 -12
- package/types/resources/settings.d.ts +2 -1
- package/types/shell/index.d.ts +206 -72
- package/types/store/dashboard-store.types.ts +108 -11
- package/types/store/pagination.types.ts +6 -3
- package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
- package/utils/__tests__/async.test.ts +87 -0
- package/utils/__tests__/auth.test.ts +273 -0
- package/utils/__tests__/aws.test.ts +140 -0
- package/utils/__tests__/banners.test.ts +176 -0
- package/utils/__tests__/chart.test.ts +64 -1
- package/utils/__tests__/color.test.ts +226 -0
- package/utils/__tests__/computed.test.ts +193 -0
- package/utils/__tests__/cspAdaptor.test.ts +163 -0
- package/utils/__tests__/dom.test.ts +81 -0
- package/utils/__tests__/duration.test.ts +176 -0
- package/utils/__tests__/dynamic-importer.test.ts +102 -0
- package/utils/__tests__/fleet-appco.test.ts +312 -0
- package/utils/__tests__/fleet.test.ts +340 -0
- package/utils/__tests__/ingress.test.ts +553 -0
- package/utils/__tests__/kube.test.ts +68 -0
- package/utils/__tests__/monitoring.test.ts +130 -0
- package/utils/__tests__/namespace-filter.test.ts +109 -0
- package/utils/__tests__/object.test.ts +22 -0
- package/utils/__tests__/pagination-utils.test.ts +361 -0
- package/utils/__tests__/parse-externalid.test.ts +137 -0
- package/utils/__tests__/perf-setting.utils.test.ts +98 -0
- package/utils/__tests__/platform.test.ts +91 -0
- package/utils/__tests__/poller-sequential.test.ts +177 -0
- package/utils/__tests__/poller.test.ts +170 -0
- package/utils/__tests__/position.test.ts +237 -0
- package/utils/__tests__/promise.test.ts +346 -0
- package/utils/__tests__/provider.test.ts +51 -1
- package/utils/__tests__/queue.test.ts +232 -0
- package/utils/__tests__/release-notes.test.ts +221 -0
- package/utils/__tests__/router.test.js +254 -1
- package/utils/__tests__/select.test.ts +208 -0
- package/utils/__tests__/settings.test.ts +140 -0
- package/utils/__tests__/sort-utils.test.ts +301 -0
- package/utils/__tests__/string-utils.test.ts +798 -0
- package/utils/__tests__/string.test.ts +23 -1
- package/utils/__tests__/style.test.ts +154 -0
- package/utils/__tests__/svg-filter.test.ts +184 -0
- package/utils/__tests__/time.test.ts +265 -1
- package/utils/__tests__/title.test.ts +47 -0
- package/utils/__tests__/units.test.ts +417 -0
- package/utils/__tests__/versions.test.ts +128 -0
- package/utils/__tests__/width.test.ts +53 -0
- package/utils/__tests__/window.test.ts +158 -0
- package/utils/__tests__/xccdf.test.ts +511 -0
- package/utils/chart.js +36 -0
- package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
- package/utils/crypto/__tests__/index.test.ts +144 -0
- package/utils/duration.ts +104 -0
- package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
- package/utils/dynamic-content/info.ts +2 -1
- package/utils/error.js +13 -0
- package/utils/fleet-appco.ts +323 -0
- package/utils/fleet.ts +13 -3
- package/utils/gatekeeper/__tests__/util.test.ts +174 -0
- package/utils/gc/__tests__/gc-interval.test.ts +119 -0
- package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
- package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
- package/utils/gc/__tests__/gc.test.ts +487 -0
- package/utils/ingress.ts +9 -1
- package/utils/object.js +22 -2
- package/utils/pagination-utils.ts +2 -1
- package/utils/provider.ts +12 -0
- package/utils/string.js +25 -2
- package/utils/uiplugins.ts +5 -5
- package/utils/validators/__tests__/cluster-name.test.ts +110 -0
- package/utils/validators/__tests__/container-images.test.ts +104 -0
- package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
- package/utils/validators/__tests__/flow-output.test.ts +91 -0
- package/utils/validators/__tests__/index.test.ts +481 -0
- package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
- package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
- package/utils/validators/__tests__/misc-validators.test.ts +246 -0
- package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
- package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
- package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
- package/utils/validators/__tests__/role-template.test.ts +149 -0
- package/utils/validators/__tests__/service.test.ts +283 -0
- package/utils/validators/__tests__/setting.test.js +32 -0
- package/utils/validators/formRules/__tests__/index.test.ts +50 -0
- package/utils/validators/formRules/index.ts +5 -5
- package/utils/validators/machine-pool.ts +1 -1
- package/utils/validators/setting.js +18 -3
- package/utils/xccdf.ts +415 -0
- package/vue.config.js +1 -1
- package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
- package/pages/support/index.vue +0 -264
- package/utils/duration.js +0 -43
|
@@ -17,6 +17,7 @@ describe('clusterRepo', () => {
|
|
|
17
17
|
jest.spyOn(model, 'save').mockImplementation().mockResolvedValue(true);
|
|
18
18
|
jest.spyOn(model, 'waitForState').mockImplementation().mockResolvedValue(true);
|
|
19
19
|
jest.spyOn(model, '$dispatch', 'get').mockReturnValue(jest.fn());
|
|
20
|
+
jest.spyOn(model, 't', 'get').mockReturnValue((key: string) => key);
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
describe('refresh', () => {
|
|
@@ -59,6 +60,62 @@ describe('clusterRepo', () => {
|
|
|
59
60
|
});
|
|
60
61
|
});
|
|
61
62
|
|
|
63
|
+
describe('defaultRefreshIntervalHours', () => {
|
|
64
|
+
it('returns 24 for OCI repos', () => {
|
|
65
|
+
model.spec.url = 'oci://example.com/chart';
|
|
66
|
+
model.spec.insecurePlainHttp = false;
|
|
67
|
+
expect(model.defaultRefreshIntervalHours).toStrictEqual(24);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('returns 1 for git repos', () => {
|
|
71
|
+
model.spec = { gitRepo: 'https://github.com/example/charts' };
|
|
72
|
+
expect(model.defaultRefreshIntervalHours).toStrictEqual(1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('returns 1 for helm repos', () => {
|
|
76
|
+
model.spec = { url: 'https://charts.example.com' };
|
|
77
|
+
expect(model.defaultRefreshIntervalHours).toStrictEqual(1);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('defaultRefreshInterval', () => {
|
|
82
|
+
it('returns seconds for OCI repos (24 hours)', () => {
|
|
83
|
+
model.spec.url = 'oci://example.com/chart';
|
|
84
|
+
model.spec.insecurePlainHttp = false;
|
|
85
|
+
expect(model.defaultRefreshInterval).toStrictEqual(86400);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns seconds for non-OCI repos (1 hour)', () => {
|
|
89
|
+
model.spec = { gitRepo: 'https://github.com/example/charts' };
|
|
90
|
+
expect(model.defaultRefreshInterval).toStrictEqual(3600);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('refreshIntervalDisplay', () => {
|
|
95
|
+
it.each([
|
|
96
|
+
-1,
|
|
97
|
+
-100,
|
|
98
|
+
])('returns "Disabled" when value is %p', (val) => {
|
|
99
|
+
model.spec.refreshInterval = val;
|
|
100
|
+
expect(model.refreshIntervalDisplay).toStrictEqual('generic.disabled');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('returns formatted duration for positive values', () => {
|
|
104
|
+
model.spec.refreshInterval = 3661;
|
|
105
|
+
expect(model.refreshIntervalDisplay).toStrictEqual('1h 1m 1s');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('returns default formatted duration when not set', () => {
|
|
109
|
+
model.spec = { url: 'https://charts.example.com' };
|
|
110
|
+
expect(model.refreshIntervalDisplay).toStrictEqual('1h');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('returns default formatted duration for OCI when not set', () => {
|
|
114
|
+
model.spec = { url: 'oci://example.com/chart', insecurePlainHttp: false };
|
|
115
|
+
expect(model.refreshIntervalDisplay).toStrictEqual('1d');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
62
119
|
describe('refreshBulk', () => {
|
|
63
120
|
it('calls refresh(false) on all items and then dispatches a single catalog/load with all repoKeys', async() => {
|
|
64
121
|
const mockItem1 = {
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import ClusterScan from '@shell/models/compliance.cattle.io.clusterscan';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build a ClusterScan model wired to a mocked store `dispatch`.
|
|
5
|
+
* `$dispatch` resolves to `this.$ctx.dispatch`, so injecting it via the
|
|
6
|
+
* constructor context is enough to exercise `_resolveExportMetadata`.
|
|
7
|
+
*/
|
|
8
|
+
const makeScan = (dispatch: jest.Mock) => new ClusterScan({}, {
|
|
9
|
+
getters: {},
|
|
10
|
+
rootGetters: {},
|
|
11
|
+
dispatch,
|
|
12
|
+
} as any) as any;
|
|
13
|
+
|
|
14
|
+
const benchmarkWithConfigMap = {
|
|
15
|
+
spec: {
|
|
16
|
+
customBenchmarkConfigMapName: 'metadata-cm',
|
|
17
|
+
customBenchmarkConfigMapNamespace: 'compliance',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('class: ClusterScan', () => {
|
|
22
|
+
describe('method: _resolveExportMetadata', () => {
|
|
23
|
+
it('returns empty metadata and decorations when the benchmark is undefined', async() => {
|
|
24
|
+
const dispatch = jest.fn();
|
|
25
|
+
const scan = makeScan(dispatch);
|
|
26
|
+
|
|
27
|
+
const result = await scan._resolveExportMetadata(undefined);
|
|
28
|
+
|
|
29
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
30
|
+
expect(dispatch).not.toHaveBeenCalled();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('returns empty when the ConfigMap name is missing', async() => {
|
|
34
|
+
const dispatch = jest.fn();
|
|
35
|
+
const scan = makeScan(dispatch);
|
|
36
|
+
|
|
37
|
+
const result = await scan._resolveExportMetadata({ spec: { customBenchmarkConfigMapNamespace: 'compliance' } });
|
|
38
|
+
|
|
39
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
40
|
+
expect(dispatch).not.toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns empty when the ConfigMap namespace is missing', async() => {
|
|
44
|
+
const dispatch = jest.fn();
|
|
45
|
+
const scan = makeScan(dispatch);
|
|
46
|
+
|
|
47
|
+
const result = await scan._resolveExportMetadata({ spec: { customBenchmarkConfigMapName: 'metadata-cm' } });
|
|
48
|
+
|
|
49
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
50
|
+
expect(dispatch).not.toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('fetches the ConfigMap by namespace/name from the configmap type', async() => {
|
|
54
|
+
const dispatch = jest.fn().mockResolvedValue({ data: {} });
|
|
55
|
+
const scan = makeScan(dispatch);
|
|
56
|
+
|
|
57
|
+
await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
58
|
+
|
|
59
|
+
expect(dispatch).toHaveBeenCalledWith('find', { type: 'configmap', id: 'compliance/metadata-cm' });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns empty when the ConfigMap has no metadata.yaml data key', async() => {
|
|
63
|
+
const dispatch = jest.fn().mockResolvedValue({ data: { 'other.yaml': 'title: x' } });
|
|
64
|
+
const scan = makeScan(dispatch);
|
|
65
|
+
|
|
66
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
67
|
+
|
|
68
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('returns empty when the ConfigMap itself is not found', async() => {
|
|
72
|
+
const dispatch = jest.fn().mockResolvedValue(undefined);
|
|
73
|
+
const scan = makeScan(dispatch);
|
|
74
|
+
|
|
75
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
76
|
+
|
|
77
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('splits top-level fields into metadata and the checks map into decorations', async() => {
|
|
81
|
+
const yaml = [
|
|
82
|
+
'title: CIS Kubernetes Benchmark',
|
|
83
|
+
'description: A CIS profile',
|
|
84
|
+
'referenceType: cis',
|
|
85
|
+
'checks:',
|
|
86
|
+
' "5.1.1":',
|
|
87
|
+
' ruleId: CIS-5.1.1-rule',
|
|
88
|
+
' severity: high',
|
|
89
|
+
' idents:',
|
|
90
|
+
' - system: https://www.cisecurity.org/controls/',
|
|
91
|
+
' value: CIS-CSC-3',
|
|
92
|
+
' "5.1.2":',
|
|
93
|
+
' ruleId: CIS-5.1.2-rule',
|
|
94
|
+
].join('\n');
|
|
95
|
+
const dispatch = jest.fn().mockResolvedValue({ data: { 'metadata.yaml': yaml } });
|
|
96
|
+
const scan = makeScan(dispatch);
|
|
97
|
+
|
|
98
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
99
|
+
|
|
100
|
+
expect(result.metadata).toStrictEqual({
|
|
101
|
+
title: 'CIS Kubernetes Benchmark',
|
|
102
|
+
description: 'A CIS profile',
|
|
103
|
+
referenceType: 'cis',
|
|
104
|
+
});
|
|
105
|
+
expect(result.decorations).toStrictEqual({
|
|
106
|
+
'5.1.1': {
|
|
107
|
+
ruleId: 'CIS-5.1.1-rule',
|
|
108
|
+
severity: 'high',
|
|
109
|
+
idents: [{ system: 'https://www.cisecurity.org/controls/', value: 'CIS-CSC-3' }],
|
|
110
|
+
},
|
|
111
|
+
'5.1.2': { ruleId: 'CIS-5.1.2-rule' },
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('returns empty decorations when metadata.yaml has no checks map', async() => {
|
|
116
|
+
const yaml = ['title: STIG', 'source: disa'].join('\n');
|
|
117
|
+
const dispatch = jest.fn().mockResolvedValue({ data: { 'metadata.yaml': yaml } });
|
|
118
|
+
const scan = makeScan(dispatch);
|
|
119
|
+
|
|
120
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
121
|
+
|
|
122
|
+
expect(result.metadata).toStrictEqual({ title: 'STIG', source: 'disa' });
|
|
123
|
+
expect(result.decorations).toStrictEqual({});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('returns empty when the ConfigMap lookup rejects', async() => {
|
|
127
|
+
const dispatch = jest.fn().mockRejectedValue(new Error('not found'));
|
|
128
|
+
const scan = makeScan(dispatch);
|
|
129
|
+
|
|
130
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
131
|
+
|
|
132
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('returns empty when metadata.yaml is malformed YAML', async() => {
|
|
136
|
+
const dispatch = jest.fn().mockResolvedValue({ data: { 'metadata.yaml': 'title: "unterminated' } });
|
|
137
|
+
const scan = makeScan(dispatch);
|
|
138
|
+
|
|
139
|
+
const result = await scan._resolveExportMetadata(benchmarkWithConfigMap);
|
|
140
|
+
|
|
141
|
+
expect(result).toStrictEqual({ metadata: {}, decorations: {} });
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Kubeconfig from '@shell/models/ext.cattle.io.kubeconfig';
|
|
2
|
-
import {
|
|
2
|
+
import { MANAGEMENT } from '@shell/config/types';
|
|
3
3
|
|
|
4
4
|
// SteveModel is JS, so we need to type the constructor
|
|
5
5
|
const KubeconfigModel = Kubeconfig as unknown as new (data: object) => Kubeconfig;
|
|
@@ -19,8 +19,9 @@ describe('class Kubeconfig', () => {
|
|
|
19
19
|
// Mock $rootGetters before any getters are accessed
|
|
20
20
|
// Cast to any since $rootGetters is inherited from JS SteveModel
|
|
21
21
|
jest.spyOn(kubeconfig as any, '$rootGetters', 'get').mockReturnValue({
|
|
22
|
-
'i18n/t':
|
|
23
|
-
'management/all':
|
|
22
|
+
'i18n/t': mockT,
|
|
23
|
+
'management/all': () => [],
|
|
24
|
+
'management/byId': () => null,
|
|
24
25
|
...rootGetters
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -70,11 +71,12 @@ describe('class Kubeconfig', () => {
|
|
|
70
71
|
});
|
|
71
72
|
|
|
72
73
|
describe('referencedClusters', () => {
|
|
73
|
-
const mockProvCluster = {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
const mockProvCluster = { detailLocation: { name: 'c-cluster-product-resource-id', params: { cluster: 'my-cluster' } } };
|
|
75
|
+
|
|
76
|
+
const mockMgmtClusterWithProv = {
|
|
77
|
+
id: 'c-m-abc123',
|
|
78
|
+
nameDisplay: 'my-cluster',
|
|
79
|
+
provCluster: mockProvCluster
|
|
78
80
|
};
|
|
79
81
|
|
|
80
82
|
const mockMgmtCluster = {
|
|
@@ -99,12 +101,12 @@ describe('class Kubeconfig', () => {
|
|
|
99
101
|
spec: { clusters: ['c-m-abc123'] }
|
|
100
102
|
},
|
|
101
103
|
{
|
|
102
|
-
'management/
|
|
103
|
-
if (type ===
|
|
104
|
-
return
|
|
104
|
+
'management/byId': (type: string, id: string) => {
|
|
105
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-abc123') {
|
|
106
|
+
return mockMgmtClusterWithProv;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
return
|
|
109
|
+
return null;
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
);
|
|
@@ -124,12 +126,12 @@ describe('class Kubeconfig', () => {
|
|
|
124
126
|
spec: { clusters: ['c-m-def456'] }
|
|
125
127
|
},
|
|
126
128
|
{
|
|
127
|
-
'management/
|
|
128
|
-
if (type === MANAGEMENT.CLUSTER) {
|
|
129
|
-
return
|
|
129
|
+
'management/byId': (type: string, id: string) => {
|
|
130
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-def456') {
|
|
131
|
+
return mockMgmtCluster;
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
return
|
|
134
|
+
return null;
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
);
|
|
@@ -157,11 +159,12 @@ describe('class Kubeconfig', () => {
|
|
|
157
159
|
expect(mockT).toHaveBeenCalledWith('"ext.cattle.io.kubeconfig".deleted', { name: 'c-m-deleted' });
|
|
158
160
|
});
|
|
159
161
|
|
|
160
|
-
it('should prefer provisioning cluster over management cluster', () => {
|
|
161
|
-
const
|
|
162
|
+
it('should prefer provisioning cluster over management cluster for location', () => {
|
|
163
|
+
const mgmtClusterBothLocs = {
|
|
162
164
|
id: 'c-m-abc123',
|
|
163
|
-
nameDisplay: '
|
|
164
|
-
detailLocation: { name: 'mgmt-location' }
|
|
165
|
+
nameDisplay: 'my-cluster',
|
|
166
|
+
detailLocation: { name: 'mgmt-location' },
|
|
167
|
+
provCluster: { detailLocation: { name: 'prov-location' } }
|
|
165
168
|
};
|
|
166
169
|
|
|
167
170
|
const kubeconfig = createKubeconfig(
|
|
@@ -170,15 +173,12 @@ describe('class Kubeconfig', () => {
|
|
|
170
173
|
spec: { clusters: ['c-m-abc123'] }
|
|
171
174
|
},
|
|
172
175
|
{
|
|
173
|
-
'management/
|
|
174
|
-
if (type ===
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
if (type === MANAGEMENT.CLUSTER) {
|
|
178
|
-
return [mgmtClusterSameId];
|
|
176
|
+
'management/byId': (type: string, id: string) => {
|
|
177
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-abc123') {
|
|
178
|
+
return mgmtClusterBothLocs;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
return
|
|
181
|
+
return null;
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
);
|
|
@@ -186,7 +186,7 @@ describe('class Kubeconfig', () => {
|
|
|
186
186
|
expect(kubeconfig.referencedClusters).toStrictEqual([
|
|
187
187
|
{
|
|
188
188
|
label: 'my-cluster',
|
|
189
|
-
location:
|
|
189
|
+
location: { name: 'prov-location' }
|
|
190
190
|
}
|
|
191
191
|
]);
|
|
192
192
|
});
|
|
@@ -195,7 +195,7 @@ describe('class Kubeconfig', () => {
|
|
|
195
195
|
describe('sortedReferencedClusters', () => {
|
|
196
196
|
it('should sort existing clusters before deleted clusters', () => {
|
|
197
197
|
const existingCluster = {
|
|
198
|
-
|
|
198
|
+
id: 'c-m-exists',
|
|
199
199
|
nameDisplay: 'existing-cluster',
|
|
200
200
|
detailLocation: { name: 'location' }
|
|
201
201
|
};
|
|
@@ -206,12 +206,12 @@ describe('class Kubeconfig', () => {
|
|
|
206
206
|
spec: { clusters: ['deleted-1', 'c-m-exists', 'deleted-2'] }
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
|
-
'management/
|
|
210
|
-
if (type ===
|
|
211
|
-
return
|
|
209
|
+
'management/byId': (type: string, id: string) => {
|
|
210
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-exists') {
|
|
211
|
+
return existingCluster;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
return
|
|
214
|
+
return null;
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
);
|
|
@@ -225,17 +225,17 @@ describe('class Kubeconfig', () => {
|
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
it('should sort existing clusters alphabetically', () => {
|
|
228
|
-
const clusters =
|
|
229
|
-
{
|
|
230
|
-
|
|
228
|
+
const clusters: Record<string, any> = {
|
|
229
|
+
'c-m-zebra': {
|
|
230
|
+
id: 'c-m-zebra', nameDisplay: 'zebra', detailLocation: { name: 'z' }
|
|
231
231
|
},
|
|
232
|
-
{
|
|
233
|
-
|
|
232
|
+
'c-m-alpha': {
|
|
233
|
+
id: 'c-m-alpha', nameDisplay: 'alpha', detailLocation: { name: 'a' }
|
|
234
234
|
},
|
|
235
|
-
{
|
|
236
|
-
|
|
235
|
+
'c-m-beta': {
|
|
236
|
+
id: 'c-m-beta', nameDisplay: 'beta', detailLocation: { name: 'b' }
|
|
237
237
|
}
|
|
238
|
-
|
|
238
|
+
};
|
|
239
239
|
|
|
240
240
|
const kubeconfig = createKubeconfig(
|
|
241
241
|
{
|
|
@@ -243,12 +243,12 @@ describe('class Kubeconfig', () => {
|
|
|
243
243
|
spec: { clusters: ['c-m-zebra', 'c-m-alpha', 'c-m-beta'] }
|
|
244
244
|
},
|
|
245
245
|
{
|
|
246
|
-
'management/
|
|
247
|
-
if (type ===
|
|
248
|
-
return clusters;
|
|
246
|
+
'management/byId': (type: string, id: string) => {
|
|
247
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
248
|
+
return clusters[id] || null;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
return
|
|
251
|
+
return null;
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
);
|
|
@@ -259,17 +259,17 @@ describe('class Kubeconfig', () => {
|
|
|
259
259
|
});
|
|
260
260
|
|
|
261
261
|
it('should sort numerically when names contain numbers', () => {
|
|
262
|
-
const clusters =
|
|
263
|
-
{
|
|
264
|
-
|
|
262
|
+
const clusters: Record<string, any> = {
|
|
263
|
+
'c-m-2': {
|
|
264
|
+
id: 'c-m-2', nameDisplay: 'cluster2', detailLocation: { name: 'c2' }
|
|
265
265
|
},
|
|
266
|
-
{
|
|
267
|
-
|
|
266
|
+
'c-m-10': {
|
|
267
|
+
id: 'c-m-10', nameDisplay: 'cluster10', detailLocation: { name: 'c10' }
|
|
268
268
|
},
|
|
269
|
-
{
|
|
270
|
-
|
|
269
|
+
'c-m-1': {
|
|
270
|
+
id: 'c-m-1', nameDisplay: 'cluster1', detailLocation: { name: 'c1' }
|
|
271
271
|
}
|
|
272
|
-
|
|
272
|
+
};
|
|
273
273
|
|
|
274
274
|
const kubeconfig = createKubeconfig(
|
|
275
275
|
{
|
|
@@ -277,12 +277,12 @@ describe('class Kubeconfig', () => {
|
|
|
277
277
|
spec: { clusters: ['c-m-2', 'c-m-10', 'c-m-1'] }
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
|
-
'management/
|
|
281
|
-
if (type ===
|
|
282
|
-
return clusters;
|
|
280
|
+
'management/byId': (type: string, id: string) => {
|
|
281
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
282
|
+
return clusters[id] || null;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
return
|
|
285
|
+
return null;
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
);
|
|
@@ -295,14 +295,14 @@ describe('class Kubeconfig', () => {
|
|
|
295
295
|
|
|
296
296
|
describe('referencedClustersSortable', () => {
|
|
297
297
|
it('should return comma-separated lowercase labels', () => {
|
|
298
|
-
const clusters =
|
|
299
|
-
{
|
|
300
|
-
|
|
298
|
+
const clusters: Record<string, any> = {
|
|
299
|
+
'c-m-1': {
|
|
300
|
+
id: 'c-m-1', nameDisplay: 'Alpha', detailLocation: { name: 'a' }
|
|
301
301
|
},
|
|
302
|
-
{
|
|
303
|
-
|
|
302
|
+
'c-m-2': {
|
|
303
|
+
id: 'c-m-2', nameDisplay: 'Beta', detailLocation: { name: 'b' }
|
|
304
304
|
}
|
|
305
|
-
|
|
305
|
+
};
|
|
306
306
|
|
|
307
307
|
const kubeconfig = createKubeconfig(
|
|
308
308
|
{
|
|
@@ -310,12 +310,12 @@ describe('class Kubeconfig', () => {
|
|
|
310
310
|
spec: { clusters: ['c-m-1', 'c-m-2'] }
|
|
311
311
|
},
|
|
312
312
|
{
|
|
313
|
-
'management/
|
|
314
|
-
if (type ===
|
|
315
|
-
return clusters;
|
|
313
|
+
'management/byId': (type: string, id: string) => {
|
|
314
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
315
|
+
return clusters[id] || null;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
return
|
|
318
|
+
return null;
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
);
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import FleetApplication from '@shell/models/fleet-application.js';
|
|
2
|
+
|
|
3
|
+
describe('class FleetApplication', () => {
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
jest.restoreAllMocks();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
describe('applicationType', () => {
|
|
9
|
+
it('should return the kind property', () => {
|
|
10
|
+
const instance = new FleetApplication({ kind: 'GitRepo' });
|
|
11
|
+
|
|
12
|
+
expect(instance.applicationType).toStrictEqual('GitRepo');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('targetClusters', () => {
|
|
17
|
+
function createFleetApplication(targets: any[] | undefined, clusters: any[], workspaceId = 'fleet-default', groups: any[] = []) {
|
|
18
|
+
const workspace = {
|
|
19
|
+
id: workspaceId,
|
|
20
|
+
clusters,
|
|
21
|
+
clusterGroups: groups,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
jest.spyOn(FleetApplication.prototype, '$getters', 'get').mockReturnValue({ byId: () => workspace });
|
|
25
|
+
|
|
26
|
+
return new FleetApplication({
|
|
27
|
+
metadata: { namespace: workspaceId },
|
|
28
|
+
spec: { targets },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it.each([
|
|
33
|
+
[
|
|
34
|
+
'metadata.name',
|
|
35
|
+
[{ clusterName: 'c-m-abc123' }],
|
|
36
|
+
[{
|
|
37
|
+
id: 'fleet-default/c-m-abc123', metadata: { name: 'c-m-abc123' }, nameDisplay: 'my-cluster'
|
|
38
|
+
}],
|
|
39
|
+
[{
|
|
40
|
+
id: 'fleet-default/c-m-abc123', metadata: { name: 'c-m-abc123' }, nameDisplay: 'my-cluster'
|
|
41
|
+
}],
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
'nameDisplay when metadata.name does not match',
|
|
45
|
+
[{ clusterName: 'my-display-name' }],
|
|
46
|
+
[{
|
|
47
|
+
id: 'fleet-default/c-m-abc123', metadata: { name: 'c-m-abc123' }, nameDisplay: 'my-display-name'
|
|
48
|
+
}],
|
|
49
|
+
[{
|
|
50
|
+
id: 'fleet-default/c-m-abc123', metadata: { name: 'c-m-abc123' }, nameDisplay: 'my-display-name'
|
|
51
|
+
}],
|
|
52
|
+
],
|
|
53
|
+
])('should find cluster by %s', (_label, targets, clusters, expected) => {
|
|
54
|
+
const app = createFleetApplication(targets, clusters);
|
|
55
|
+
|
|
56
|
+
expect(app.targetClusters).toStrictEqual(expected);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should prefer metadata.name match over nameDisplay match', () => {
|
|
60
|
+
const clusters = [
|
|
61
|
+
{
|
|
62
|
+
id: 'fleet-default/exact-match',
|
|
63
|
+
metadata: { name: 'exact-match' },
|
|
64
|
+
nameDisplay: 'display-a',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'fleet-default/c-m-other',
|
|
68
|
+
metadata: { name: 'c-m-other' },
|
|
69
|
+
nameDisplay: 'exact-match',
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const app = createFleetApplication([{ clusterName: 'exact-match' }], clusters);
|
|
74
|
+
|
|
75
|
+
expect(app.targetClusters).toStrictEqual([clusters[0]]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should return empty array when no cluster matches by name or nameDisplay', () => {
|
|
79
|
+
const clusters = [
|
|
80
|
+
{
|
|
81
|
+
id: 'fleet-default/c-m-abc123',
|
|
82
|
+
metadata: { name: 'c-m-abc123' },
|
|
83
|
+
nameDisplay: 'my-cluster',
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const app = createFleetApplication([{ clusterName: 'non-existent' }], clusters);
|
|
88
|
+
|
|
89
|
+
expect(app.targetClusters).toStrictEqual([]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should handle multiple targets with mixed name and nameDisplay matches', () => {
|
|
93
|
+
const clusters = [
|
|
94
|
+
{
|
|
95
|
+
id: 'fleet-default/c-m-abc123',
|
|
96
|
+
metadata: { name: 'c-m-abc123' },
|
|
97
|
+
nameDisplay: 'cluster-alpha',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'fleet-default/c-m-def456',
|
|
101
|
+
metadata: { name: 'c-m-def456' },
|
|
102
|
+
nameDisplay: 'cluster-beta',
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const targets = [
|
|
107
|
+
{ clusterName: 'c-m-abc123' },
|
|
108
|
+
{ clusterName: 'cluster-beta' },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const app = createFleetApplication(targets, clusters);
|
|
112
|
+
|
|
113
|
+
expect(app.targetClusters).toStrictEqual([clusters[0], clusters[1]]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should return empty array when targets is empty', () => {
|
|
117
|
+
const app = createFleetApplication([], []);
|
|
118
|
+
|
|
119
|
+
expect(app.targetClusters).toStrictEqual([]);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should return empty array when targets is undefined', () => {
|
|
123
|
+
const app = createFleetApplication(undefined, []);
|
|
124
|
+
|
|
125
|
+
expect(app.targetClusters).toStrictEqual([]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should return empty array when workspace has no clusters', () => {
|
|
129
|
+
const app = createFleetApplication([{ clusterName: 'any-name' }], []);
|
|
130
|
+
|
|
131
|
+
expect(app.targetClusters).toStrictEqual([]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should handle cluster with undefined nameDisplay gracefully', () => {
|
|
135
|
+
const clusters = [
|
|
136
|
+
{
|
|
137
|
+
id: 'fleet-default/c-m-abc123',
|
|
138
|
+
metadata: { name: 'c-m-abc123' },
|
|
139
|
+
nameDisplay: undefined,
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const app = createFleetApplication([{ clusterName: 'c-m-abc123' }], clusters);
|
|
144
|
+
|
|
145
|
+
expect(app.targetClusters).toStrictEqual([clusters[0]]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should return local cluster targets when workspace is fleet-local', () => {
|
|
149
|
+
const localTargetClusters = [
|
|
150
|
+
{
|
|
151
|
+
id: 'fleet-local/local',
|
|
152
|
+
metadata: { name: 'local' },
|
|
153
|
+
nameDisplay: 'local',
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
const groups = [
|
|
158
|
+
{
|
|
159
|
+
id: 'fleet-local/default',
|
|
160
|
+
targetClusters: localTargetClusters,
|
|
161
|
+
}
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
const app = createFleetApplication([], [], 'fleet-local', groups);
|
|
165
|
+
|
|
166
|
+
expect(app.targetClusters).toStrictEqual(localTargetClusters);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should return empty array when workspace is fleet-local and default group is missing', () => {
|
|
170
|
+
const app = createFleetApplication([], [], 'fleet-local', []);
|
|
171
|
+
|
|
172
|
+
expect(app.targetClusters).toStrictEqual([]);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|