@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
|
@@ -174,7 +174,7 @@ export default {
|
|
|
174
174
|
await wait(5000);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
const user = this.value.save();
|
|
177
|
+
const user = await this.value.save();
|
|
178
178
|
|
|
179
179
|
return user;
|
|
180
180
|
},
|
|
@@ -214,8 +214,10 @@ export default {
|
|
|
214
214
|
return;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
const userId = user?.id || this.value.id;
|
|
218
|
+
|
|
217
219
|
try {
|
|
218
|
-
await this.$refs.grb.save(
|
|
220
|
+
await this.$refs.grb.save(userId);
|
|
219
221
|
} catch (err) {
|
|
220
222
|
if (this.isCreate) {
|
|
221
223
|
try {
|
|
@@ -245,6 +247,7 @@ export default {
|
|
|
245
247
|
:can-yaml="false"
|
|
246
248
|
class="create-edit"
|
|
247
249
|
@finish="save"
|
|
250
|
+
@error="e=>errors = e"
|
|
248
251
|
>
|
|
249
252
|
<div class="credentials">
|
|
250
253
|
<h2> {{ t("user.edit.credentials.label") }}</h2>
|
|
@@ -43,7 +43,9 @@ export default {
|
|
|
43
43
|
const backend = get(this.value.spec, this.value.defaultBackendPath);
|
|
44
44
|
|
|
45
45
|
this.serviceName = get(backend, this.value.serviceNamePath) || '';
|
|
46
|
-
this.servicePort = get(backend, this.value.servicePortPath) ||
|
|
46
|
+
this.servicePort = get(backend, this.value.servicePortPath) ||
|
|
47
|
+
get(backend, this.value.servicePortNamePath) ||
|
|
48
|
+
'';
|
|
47
49
|
},
|
|
48
50
|
computed: {
|
|
49
51
|
isView() {
|
|
@@ -75,10 +77,14 @@ export default {
|
|
|
75
77
|
},
|
|
76
78
|
methods: {
|
|
77
79
|
update() {
|
|
78
|
-
|
|
80
|
+
// Fresh object so the old port path (name vs number) doesn't linger.
|
|
81
|
+
const backend = {};
|
|
82
|
+
const parsed = Number.parseInt(this.servicePort);
|
|
83
|
+
const servicePort = Number.isNaN(parsed) ? this.servicePort : parsed;
|
|
84
|
+
const portPath = typeof servicePort === 'number' ? this.value.servicePortPath : this.value.servicePortNamePath;
|
|
79
85
|
|
|
80
86
|
set(backend, this.value.serviceNamePath, this.serviceName);
|
|
81
|
-
set(backend,
|
|
87
|
+
set(backend, portPath, servicePort);
|
|
82
88
|
set(this.value.spec, this.value.defaultBackendPath, backend);
|
|
83
89
|
|
|
84
90
|
this.$emit('update:value', this.value);
|
|
@@ -119,10 +125,12 @@ export default {
|
|
|
119
125
|
class="col span-3"
|
|
120
126
|
:style="{'margin-right': '0px'}"
|
|
121
127
|
>
|
|
128
|
+
<!-- :required drives the asterisk; portRequired doesn't have .name === 'required' -->
|
|
122
129
|
<LabeledInput
|
|
123
130
|
v-if="portOptions.length === 0 || isView"
|
|
124
|
-
v-model:value
|
|
131
|
+
v-model:value="servicePort"
|
|
125
132
|
:mode="mode"
|
|
133
|
+
:required="true"
|
|
126
134
|
:label="t('ingress.defaultBackend.port.label')"
|
|
127
135
|
:placeholder="t('ingress.defaultBackend.port.placeholder')"
|
|
128
136
|
:rules="rules.port"
|
|
@@ -132,6 +140,7 @@ export default {
|
|
|
132
140
|
v-else
|
|
133
141
|
v-model:value="servicePort"
|
|
134
142
|
:mode="mode"
|
|
143
|
+
:required="true"
|
|
135
144
|
:options="portOptions"
|
|
136
145
|
:label="t('ingress.defaultBackend.port.label')"
|
|
137
146
|
:placeholder="t('ingress.defaultBackend.port.placeholder')"
|
|
@@ -79,20 +79,24 @@ export default {
|
|
|
79
79
|
set(this.value, 'path', this.value.path || '');
|
|
80
80
|
set(this.value, 'pathType', this.value.pathType || this.pathTypes[0]);
|
|
81
81
|
set(this.value.backend, this.ingress.serviceNamePath, get(this.value.backend, this.ingress.serviceNamePath) || '');
|
|
82
|
-
set(this.value.backend, this.ingress.servicePortPath, get(this.value.backend, this.ingress.servicePortPath) || '');
|
|
83
82
|
|
|
84
83
|
this.serviceName = get(this.value.backend, this.ingress.serviceNamePath);
|
|
85
|
-
this.servicePort = get(this.value.backend, this.ingress.servicePortPath)
|
|
84
|
+
this.servicePort = get(this.value.backend, this.ingress.servicePortPath) ||
|
|
85
|
+
get(this.value.backend, this.ingress.servicePortNamePath) ||
|
|
86
|
+
'';
|
|
86
87
|
},
|
|
87
88
|
methods: {
|
|
88
89
|
update() {
|
|
89
|
-
const
|
|
90
|
+
const parsed = Number.parseInt(this.servicePort);
|
|
91
|
+
const servicePort = Number.isNaN(parsed) ? this.servicePort : parsed;
|
|
90
92
|
const serviceName = this.serviceName.label || this.serviceName;
|
|
91
93
|
const out = {
|
|
92
94
|
id: this.value.id, backend: {}, path: this.path, pathType: this.pathType
|
|
93
95
|
};
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
const portPath = typeof servicePort === 'number' ? this.ingress.servicePortPath : this.ingress.servicePortNamePath;
|
|
98
|
+
|
|
99
|
+
set(out.backend, portPath, servicePort);
|
|
96
100
|
set(out.backend, this.ingress.serviceNamePath, serviceName);
|
|
97
101
|
|
|
98
102
|
this.$emit('update:value', out);
|
|
@@ -87,21 +87,21 @@ export default {
|
|
|
87
87
|
path: 'spec.rules.http.paths.path', rules: ['absolutePath'], translationKey: 'ingress.rules.path.label'
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
|
-
path: 'spec.rules.http.paths.backend.service.port
|
|
90
|
+
path: 'spec.rules.http.paths.backend.service.port', rules: ['portRequired', 'portRange'], translationKey: 'ingress.rules.port.label'
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
path: 'spec.rules.http.paths.backend.service.name', rules: ['required'], translationKey: 'ingress.rules.target.label'
|
|
94
94
|
},
|
|
95
95
|
{ path: 'spec', rules: ['backEndOrRules'] },
|
|
96
96
|
{
|
|
97
|
-
path: 'spec.defaultBackend.service.name', rules: ['
|
|
97
|
+
path: 'spec.defaultBackend.service.name', rules: ['defaultBackendNameRequired'], translationKey: 'ingress.defaultBackend.targetService.label'
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
|
-
path: 'spec.defaultBackend.service.port
|
|
100
|
+
path: 'spec.defaultBackend.service.port', rules: ['defaultBackendPortRequired', 'portRange'], translationKey: 'ingress.defaultBackend.port.label'
|
|
101
101
|
},
|
|
102
102
|
{ path: 'spec.tls.hosts', rules: ['required', 'wildcardHostname'] }
|
|
103
103
|
],
|
|
104
|
-
fvReportedValidationPaths: ['spec.rules.http.paths.backend.service.port
|
|
104
|
+
fvReportedValidationPaths: ['spec.rules.http.paths.backend.service.port', 'spec.rules.http.paths.path', 'spec.rules.http.paths.backend.service.name']
|
|
105
105
|
};
|
|
106
106
|
},
|
|
107
107
|
|
|
@@ -125,35 +125,89 @@ export default {
|
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
const portLabel = this.t('ingress.rules.port.label');
|
|
129
|
+
|
|
130
|
+
// Built-in `required` won't work: it passes for empty objects like {} or { name: '' }.
|
|
131
|
+
const portRequired = (port) => {
|
|
132
|
+
if (typeof port === 'string' || typeof port === 'number') {
|
|
133
|
+
if (!port) {
|
|
134
|
+
return this.t('validation.required', { key: portLabel });
|
|
135
|
+
}
|
|
136
|
+
} else if (!port || (!port.number && !port.name)) {
|
|
137
|
+
return this.t('validation.required', { key: portLabel });
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const portRange = (port) => {
|
|
142
|
+
let num;
|
|
143
|
+
|
|
144
|
+
if (typeof port === 'number') {
|
|
145
|
+
num = port;
|
|
146
|
+
} else if (typeof port === 'string') {
|
|
147
|
+
num = Number.parseInt(port);
|
|
148
|
+
} else if (port?.number) {
|
|
149
|
+
num = port.number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (num !== undefined && !Number.isNaN(num) && (num < 1 || num > 65535)) {
|
|
153
|
+
return this.t('validation.number.between', {
|
|
154
|
+
key: portLabel, min: '1', max: '65535'
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const hasDefaultBackendService = () => {
|
|
160
|
+
const backend = get(this.value?.spec, this.value.defaultBackendPath);
|
|
161
|
+
|
|
162
|
+
return !!get(backend, this.value.serviceNamePath);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const nameLabel = this.t('ingress.defaultBackend.targetService.label');
|
|
166
|
+
|
|
167
|
+
// Only enforce required on the default backend when a service is selected.
|
|
168
|
+
// Selecting "None" means the user wants to remove the backend; willSave() handles cleanup.
|
|
169
|
+
const defaultBackendNameRequired = (name) => {
|
|
170
|
+
if (hasDefaultBackendService() && !name) {
|
|
171
|
+
return this.t('validation.required', { key: nameLabel });
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const defaultBackendPortRequired = (port) => {
|
|
176
|
+
if (!hasDefaultBackendService()) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return portRequired(port);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
backEndOrRules,
|
|
185
|
+
portRequired,
|
|
186
|
+
portRange,
|
|
187
|
+
defaultBackendNameRequired,
|
|
188
|
+
defaultBackendPortRequired,
|
|
189
|
+
};
|
|
129
190
|
},
|
|
130
191
|
tabErrors() {
|
|
131
192
|
return {
|
|
132
|
-
rules: this.fvGetPathErrors(['spec.rules.host', 'spec.rules.http.paths.path', 'spec.rules.http.paths.backend.service.port
|
|
133
|
-
defaultBackend: this.fvGetPathErrors(['spec.defaultBackend.service.name', 'spec.defaultBackend.service.port
|
|
193
|
+
rules: this.fvGetPathErrors(['spec.rules.host', 'spec.rules.http.paths.path', 'spec.rules.http.paths.backend.service.port', 'spec.rules.http.paths.backend.service.name'])?.length > 0,
|
|
194
|
+
defaultBackend: this.fvGetPathErrors(['spec.defaultBackend.service.name', 'spec.defaultBackend.service.port'])?.length > 0
|
|
134
195
|
};
|
|
135
196
|
},
|
|
136
197
|
rulesPathRules() {
|
|
137
198
|
return {
|
|
138
199
|
requestHost: this.fvGetAndReportPathRules('spec.rules.host'),
|
|
139
200
|
path: this.fvGetAndReportPathRules('spec.rules.http.paths.path'),
|
|
140
|
-
port: this.fvGetAndReportPathRules('spec.rules.http.paths.backend.service.port
|
|
201
|
+
port: this.fvGetAndReportPathRules('spec.rules.http.paths.backend.service.port'),
|
|
141
202
|
target: this.fvGetAndReportPathRules('spec.rules.http.paths.backend.service.name'),
|
|
142
203
|
|
|
143
204
|
};
|
|
144
205
|
},
|
|
145
206
|
defaultBackendPathRules() {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
name: this.fvGetAndReportPathRules('spec.defaultBackend.service.name'),
|
|
152
|
-
port: this.fvGetAndReportPathRules('spec.defaultBackend.service.port.number'),
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return { name: [], port: [] };
|
|
207
|
+
return {
|
|
208
|
+
name: this.fvGetAndReportPathRules('spec.defaultBackend.service.name'),
|
|
209
|
+
port: this.fvGetAndReportPathRules('spec.defaultBackend.service.port'),
|
|
210
|
+
};
|
|
157
211
|
},
|
|
158
212
|
serviceTargets() {
|
|
159
213
|
return this.ingressHelper.findAndMapServiceTargets(this.services);
|
|
@@ -188,7 +242,8 @@ export default {
|
|
|
188
242
|
willSave() {
|
|
189
243
|
const backend = get(this.value.spec, this.value.defaultBackendPath);
|
|
190
244
|
const serviceName = get(backend, this.value.serviceNamePath);
|
|
191
|
-
const servicePort = get(backend, this.value.servicePortPath)
|
|
245
|
+
const servicePort = get(backend, this.value.servicePortPath) ||
|
|
246
|
+
get(backend, this.value.servicePortNamePath);
|
|
192
247
|
|
|
193
248
|
if (backend && (!serviceName || !servicePort)) {
|
|
194
249
|
const path = this.value.defaultBackendPath;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import MachinePool from '@shell/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue';
|
|
3
|
+
|
|
4
|
+
const TRANSLATION_KEY = '%cluster.machinePool.name.unique%';
|
|
5
|
+
|
|
6
|
+
function createPool(name: string, { remove = false } = {}) {
|
|
7
|
+
return {
|
|
8
|
+
id: `pool-${ name }`,
|
|
9
|
+
remove,
|
|
10
|
+
create: false,
|
|
11
|
+
update: true,
|
|
12
|
+
pool: {
|
|
13
|
+
name,
|
|
14
|
+
etcdRole: false,
|
|
15
|
+
controlPlaneRole: false,
|
|
16
|
+
workerRole: true,
|
|
17
|
+
quantity: 1,
|
|
18
|
+
},
|
|
19
|
+
config: null,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function mountMachinePool(currentPool: ReturnType<typeof createPool>, allPools: ReturnType<typeof createPool>[]) {
|
|
24
|
+
return shallowMount(MachinePool, {
|
|
25
|
+
props: {
|
|
26
|
+
value: currentPool,
|
|
27
|
+
mode: 'create',
|
|
28
|
+
provider: 'custom',
|
|
29
|
+
idx: 0,
|
|
30
|
+
machinePools: allPools,
|
|
31
|
+
poolId: currentPool.id,
|
|
32
|
+
poolCreateMode: true,
|
|
33
|
+
},
|
|
34
|
+
global: {
|
|
35
|
+
mocks: {
|
|
36
|
+
$store: {
|
|
37
|
+
getters: {
|
|
38
|
+
'i18n/t': (key: string) => key,
|
|
39
|
+
'i18n/exists': () => false,
|
|
40
|
+
'type-map/hasCustomMachineConfigComponent': () => false,
|
|
41
|
+
'type-map/importMachineConfig': () => null,
|
|
42
|
+
'features/get': () => false,
|
|
43
|
+
},
|
|
44
|
+
dispatch: jest.fn(),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
stubs: {
|
|
48
|
+
LabeledInput: true,
|
|
49
|
+
Checkbox: true,
|
|
50
|
+
Taints: true,
|
|
51
|
+
KeyValue: true,
|
|
52
|
+
AdvancedSection: true,
|
|
53
|
+
Banner: true,
|
|
54
|
+
UnitInput: true,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe('component: MachinePool', () => {
|
|
61
|
+
describe('uniquePoolName validation', () => {
|
|
62
|
+
it('should return undefined when the name is empty', () => {
|
|
63
|
+
const pool = createPool('');
|
|
64
|
+
const wrapper = mountMachinePool(pool, [pool]);
|
|
65
|
+
|
|
66
|
+
expect(wrapper.vm.fvExtraRules.uniquePoolName('')).toBeUndefined();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should return undefined when the pool name is unique', () => {
|
|
70
|
+
const pool1 = createPool('pool1');
|
|
71
|
+
const pool2 = createPool('pool2');
|
|
72
|
+
const wrapper = mountMachinePool(pool1, [pool1, pool2]);
|
|
73
|
+
|
|
74
|
+
expect(wrapper.vm.fvExtraRules.uniquePoolName('pool1')).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should return an error message when the pool name is duplicated', () => {
|
|
78
|
+
const pool1 = createPool('same-name');
|
|
79
|
+
const pool2 = createPool('same-name');
|
|
80
|
+
const wrapper = mountMachinePool(pool1, [pool1, pool2]);
|
|
81
|
+
|
|
82
|
+
expect(wrapper.vm.fvExtraRules.uniquePoolName('same-name')).toStrictEqual(TRANSLATION_KEY);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should ignore pools marked for removal', () => {
|
|
86
|
+
const pool1 = createPool('same-name');
|
|
87
|
+
const pool2 = createPool('same-name', { remove: true });
|
|
88
|
+
const wrapper = mountMachinePool(pool1, [pool1, pool2]);
|
|
89
|
+
|
|
90
|
+
expect(wrapper.vm.fvExtraRules.uniquePoolName('same-name')).toBeUndefined();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it.each([
|
|
94
|
+
['Pool1', 'pool1'],
|
|
95
|
+
['POOL', 'pool'],
|
|
96
|
+
])('should flag names that differ only by case as duplicates (%s vs %s)', (nameA, nameB) => {
|
|
97
|
+
const pool1 = createPool(nameA);
|
|
98
|
+
const pool2 = createPool(nameB);
|
|
99
|
+
const wrapper = mountMachinePool(pool1, [pool1, pool2]);
|
|
100
|
+
|
|
101
|
+
expect(wrapper.vm.fvExtraRules.uniquePoolName(nameA)).toStrictEqual(TRANSLATION_KEY);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -5,7 +5,7 @@ import { Banner } from '@components/Banner';
|
|
|
5
5
|
import CruResource from '@shell/components/CruResource';
|
|
6
6
|
import SelectIconGrid from '@shell/components/SelectIconGrid';
|
|
7
7
|
import {
|
|
8
|
-
CHART, FROM_CLUSTER, SUB_TYPE, RKE_TYPE, _EDIT, _IMPORT, _CONFIG, _VIEW
|
|
8
|
+
CHART, FROM_CLUSTER, SUB_TYPE, RKE_TYPE, _EDIT, _IMPORT, _CONFIG, _VIEW, _CREATE
|
|
9
9
|
} from '@shell/config/query-params';
|
|
10
10
|
import { mapGetters } from 'vuex';
|
|
11
11
|
import { sortBy } from '@shell/utils/sort';
|
|
@@ -80,16 +80,20 @@ export default {
|
|
|
80
80
|
},
|
|
81
81
|
|
|
82
82
|
async fetch() {
|
|
83
|
-
const hash = {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const hash = {};
|
|
84
|
+
|
|
85
|
+
if (this.mode === _CREATE) {
|
|
86
|
+
// After we create we wait for these to exist, so start watching
|
|
87
|
+
await this.$store.dispatch('management/watch', { type: MANAGEMENT.CLUSTER, registerType: true });
|
|
88
|
+
await this.$store.dispatch('management/watch', { type: CAPI.RANCHER_CLUSTER, registerType: true });
|
|
89
|
+
} else {
|
|
90
|
+
hash.mgmtClusters = this.value.waitForMgmt();
|
|
91
|
+
}
|
|
88
92
|
|
|
89
93
|
// No need to fetch charts when editing an RKE1 cluster
|
|
90
94
|
// The computed property `isRke1` in this file is based on the RKE1/RKE2 toggle, which is not applicable in this case
|
|
91
95
|
// Instead, we should rely on the value from the model: `this.value.isRke1`
|
|
92
|
-
if (!this.value.isRke1 || (this.value.isRke1 && this.mode !==
|
|
96
|
+
if (!this.value.isRke1 || (this.value.isRke1 && this.mode !== _EDIT)) {
|
|
93
97
|
hash['catalog'] = this.$store.dispatch('catalog/load');
|
|
94
98
|
}
|
|
95
99
|
|
|
@@ -94,8 +94,8 @@ const NODE_TOTAL = {
|
|
|
94
94
|
};
|
|
95
95
|
const CLUSTER_AGENT_CUSTOMIZATION = 'clusterAgentDeploymentCustomization';
|
|
96
96
|
const FLEET_AGENT_CUSTOMIZATION = 'fleetAgentDeploymentCustomization';
|
|
97
|
-
|
|
98
97
|
const REGISTRIES_TAB_NAME = 'registry';
|
|
98
|
+
const INIT_HOOKS = '_initHooks';
|
|
99
99
|
|
|
100
100
|
const isAzureK8sUnsupported = (version) => semver.gte(version, '1.30.0');
|
|
101
101
|
|
|
@@ -174,7 +174,7 @@ export default {
|
|
|
174
174
|
Object.entries(this.chartValues).forEach(([name, value]) => {
|
|
175
175
|
const key = this.chartVersionKey(name);
|
|
176
176
|
|
|
177
|
-
this.
|
|
177
|
+
this.userChartValues[key] = value;
|
|
178
178
|
});
|
|
179
179
|
this.setAgentConfiguration();
|
|
180
180
|
},
|
|
@@ -274,6 +274,7 @@ export default {
|
|
|
274
274
|
truncateLimit: this.value.defaultHostnameLengthLimit || 0,
|
|
275
275
|
busy: false,
|
|
276
276
|
machinePoolValidation: {}, // map of validation states for each machine pool
|
|
277
|
+
infrastructureClusterValid: true,
|
|
277
278
|
machinePoolErrors: {},
|
|
278
279
|
addonConfigValidation: {}, // validation state of each addon config (boolean of whether codemirror's yaml lint passed)
|
|
279
280
|
stackPreferenceError: false, // spec.networking.stackPreference is validated in conjunction with hasOnlyIpv6Pools
|
|
@@ -298,7 +299,9 @@ export default {
|
|
|
298
299
|
isEmpty,
|
|
299
300
|
AGENT_CONFIGURATION_TYPES,
|
|
300
301
|
basicsValid: true,
|
|
302
|
+
registryConfigValid: true,
|
|
301
303
|
originalIngressController: this.value.spec.rkeConfig.machineGlobalConfig?.[INGRESS_CONTROLLER] || INGRESS_NONE,
|
|
304
|
+
infrastructureCluster: null,
|
|
302
305
|
};
|
|
303
306
|
},
|
|
304
307
|
|
|
@@ -328,6 +331,14 @@ export default {
|
|
|
328
331
|
return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
|
|
329
332
|
},
|
|
330
333
|
|
|
334
|
+
isUpstreamCAPIProvider() {
|
|
335
|
+
if (this.extensionProvider?.isUpstreamCAPIProvider !== undefined) {
|
|
336
|
+
return !!this.extensionProvider.isUpstreamCAPIProvider;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return false;
|
|
340
|
+
},
|
|
341
|
+
|
|
331
342
|
chartValues() {
|
|
332
343
|
return this.value.spec.rkeConfig.chartValues;
|
|
333
344
|
},
|
|
@@ -547,7 +558,7 @@ export default {
|
|
|
547
558
|
getters: this.$store.getters,
|
|
548
559
|
axios: this.$store.$axios,
|
|
549
560
|
$extension: this.$store.app.$extension,
|
|
550
|
-
|
|
561
|
+
t: (...args) => this.t.apply(this, args),
|
|
551
562
|
isCreate: this.isCreate
|
|
552
563
|
});
|
|
553
564
|
}
|
|
@@ -825,6 +836,10 @@ export default {
|
|
|
825
836
|
return null;
|
|
826
837
|
},
|
|
827
838
|
|
|
839
|
+
extensionInfrastructureSection() {
|
|
840
|
+
return this.extensionProvider?.extensionInfrastructureSection || null;
|
|
841
|
+
},
|
|
842
|
+
|
|
828
843
|
showForm() {
|
|
829
844
|
return !!this.credentialId || !this.needCredential;
|
|
830
845
|
},
|
|
@@ -878,7 +893,9 @@ export default {
|
|
|
878
893
|
|
|
879
894
|
const hasAddonConfigErrors = Object.values(this.addonConfigValidation).filter((v) => v === false).length > 0;
|
|
880
895
|
|
|
881
|
-
|
|
896
|
+
const hasInfrastructureClusterError = this.isUpstreamCAPIProvider ? !this.infrastructureClusterValid : false;
|
|
897
|
+
|
|
898
|
+
return validRequiredPools && base && !hasAddonConfigErrors && !hasInfrastructureClusterError && !this.stackPreferenceError;
|
|
882
899
|
},
|
|
883
900
|
|
|
884
901
|
currentCluster() {
|
|
@@ -906,7 +923,8 @@ export default {
|
|
|
906
923
|
return this.validationPassed &&
|
|
907
924
|
this.fvFormIsValid &&
|
|
908
925
|
this.etcdConfigValid &&
|
|
909
|
-
this.basicsValid
|
|
926
|
+
this.basicsValid &&
|
|
927
|
+
this.registryConfigValid;
|
|
910
928
|
},
|
|
911
929
|
nginxSupported() {
|
|
912
930
|
if (this.serverArgs?.disable?.options.includes(RKE2_INGRESS_NGINX)) {
|
|
@@ -1013,6 +1031,11 @@ export default {
|
|
|
1013
1031
|
},
|
|
1014
1032
|
|
|
1015
1033
|
created() {
|
|
1034
|
+
// Hooks to be run when cluster is getting initialized
|
|
1035
|
+
if (this.extensionProvider?.registerInitHooks) {
|
|
1036
|
+
this.extensionProvider.registerInitHooks(this.registerHook.bind(this, INIT_HOOKS), this.value);
|
|
1037
|
+
}
|
|
1038
|
+
// Other hooks to be run before/after saving the cluster
|
|
1016
1039
|
this.registerBeforeHook(this.showIpv6Warning, 'show-ipv6-warning', 1);
|
|
1017
1040
|
this.registerBeforeHook(this.saveMachinePools, 'save-machine-pools', 2);
|
|
1018
1041
|
this.registerBeforeHook(this.setRegistryConfig, 'set-registry-config');
|
|
@@ -1031,6 +1054,21 @@ export default {
|
|
|
1031
1054
|
methods: {
|
|
1032
1055
|
set,
|
|
1033
1056
|
|
|
1057
|
+
updateExtensionInfrastructureSection(neu) {
|
|
1058
|
+
if (!neu || typeof neu !== 'object') {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
if (!this.infrastructureCluster || typeof this.infrastructureCluster !== 'object') {
|
|
1063
|
+
this.infrastructureCluster = neu;
|
|
1064
|
+
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// Preserve the original resource model instance while applying extension updates.
|
|
1069
|
+
mergeWithReplace(this.infrastructureCluster, neu, { mutateOriginal: true });
|
|
1070
|
+
},
|
|
1071
|
+
|
|
1034
1072
|
async handleVsphereCpiSecret() {
|
|
1035
1073
|
return VsphereUtils.handleVsphereCpiSecret(this);
|
|
1036
1074
|
},
|
|
@@ -1054,8 +1092,8 @@ export default {
|
|
|
1054
1092
|
if (!this.value.spec.machineSelectorConfig.find((x) => !x.machineLabelSelector)) {
|
|
1055
1093
|
this.value.spec.machineSelectorConfig.unshift({ config: {} });
|
|
1056
1094
|
}
|
|
1057
|
-
|
|
1058
|
-
if (this.value.spec.cloudCredentialSecretName) {
|
|
1095
|
+
// TODO handle upstream capi once credentials part is clear
|
|
1096
|
+
if (this.value.spec.cloudCredentialSecretName ) {
|
|
1059
1097
|
await this.$store.dispatch('rancher/findAll', { type: NORMAN.CLOUD_CREDENTIAL });
|
|
1060
1098
|
this.credentialId = `${ this.value.spec.cloudCredentialSecretName }`;
|
|
1061
1099
|
}
|
|
@@ -1104,6 +1142,9 @@ export default {
|
|
|
1104
1142
|
if ( isEmpty(this.value?.spec?.localClusterAuthEndpoint) ) {
|
|
1105
1143
|
set(this.value, 'spec.localClusterAuthEndpoint', { enabled: false });
|
|
1106
1144
|
}
|
|
1145
|
+
|
|
1146
|
+
await this.applyHooks(INIT_HOOKS, this.value);
|
|
1147
|
+
this.localValue = this.value;
|
|
1107
1148
|
},
|
|
1108
1149
|
|
|
1109
1150
|
/**
|
|
@@ -1279,6 +1320,10 @@ export default {
|
|
|
1279
1320
|
|
|
1280
1321
|
if (this.isElementalCluster) {
|
|
1281
1322
|
type = ELEMENTAL_SCHEMA_IDS.MACHINE_INV_SELECTOR_TEMPLATES;
|
|
1323
|
+
} else if (this.isUpstreamCAPIProvider && pool.machineConfigRef?.apiVersion) {
|
|
1324
|
+
const [group] = (pool.machineConfigRef.apiVersion || '').split('/');
|
|
1325
|
+
|
|
1326
|
+
type = `${ group }.${ pool.machineConfigRef.kind.toLowerCase() }`;
|
|
1282
1327
|
} else {
|
|
1283
1328
|
type = `${ CAPI.MACHINE_CONFIG_GROUP }.${ pool.machineConfigRef.kind.toLowerCase() }`;
|
|
1284
1329
|
}
|
|
@@ -1384,10 +1429,20 @@ export default {
|
|
|
1384
1429
|
pool.pool.machineOS = 'linux';
|
|
1385
1430
|
}
|
|
1386
1431
|
|
|
1387
|
-
if (this.isElementalCluster) {
|
|
1432
|
+
if (this.isElementalCluster && this.machineConfigSchema?.attributes) {
|
|
1388
1433
|
pool.pool.machineConfigRef.apiVersion = `${ this.machineConfigSchema.attributes.group }/${ this.machineConfigSchema.attributes.version }`;
|
|
1389
1434
|
}
|
|
1390
1435
|
|
|
1436
|
+
// Upstream CAPI MachineTemplate resources are referenced by full apiVersion so that
|
|
1437
|
+
// initMachinePools can resolve the correct management store type on subsequent loads.
|
|
1438
|
+
if (this.isUpstreamCAPIProvider && this.machineConfigSchema?.attributes) {
|
|
1439
|
+
const { group, version } = this.machineConfigSchema.attributes;
|
|
1440
|
+
|
|
1441
|
+
if (group && version) {
|
|
1442
|
+
pool.pool.machineConfigRef.apiVersion = `${ group }/${ version }`;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1391
1446
|
this.machinePools.push(pool);
|
|
1392
1447
|
|
|
1393
1448
|
this.$nextTick(() => {
|
|
@@ -1536,6 +1591,10 @@ export default {
|
|
|
1536
1591
|
},
|
|
1537
1592
|
|
|
1538
1593
|
async cleanupMachinePools() {
|
|
1594
|
+
// Allow the extension provider to handle its own resource cleanup
|
|
1595
|
+
if (this.extensionProvider?.cleanupMachinePools) {
|
|
1596
|
+
return await this.extensionProvider.cleanupMachinePools(this.machinePools);
|
|
1597
|
+
}
|
|
1539
1598
|
for (const entry of this.machinePools) {
|
|
1540
1599
|
if (entry.remove && entry.config) {
|
|
1541
1600
|
try {
|
|
@@ -2347,7 +2406,8 @@ export default {
|
|
|
2347
2406
|
if (this.errors) {
|
|
2348
2407
|
clear(this.errors);
|
|
2349
2408
|
}
|
|
2350
|
-
|
|
2409
|
+
|
|
2410
|
+
if ( this.value.cloudProvider === 'aws') {
|
|
2351
2411
|
const missingProfileName = this.machinePools.some((mp) => !mp.config.iamInstanceProfile);
|
|
2352
2412
|
|
|
2353
2413
|
if (missingProfileName) {
|
|
@@ -2356,7 +2416,7 @@ export default {
|
|
|
2356
2416
|
}
|
|
2357
2417
|
|
|
2358
2418
|
for (const [index] of this.machinePools.entries()) { // validator machine config
|
|
2359
|
-
if (typeof this.$refs.pool[index]?.test === 'function') {
|
|
2419
|
+
if (typeof this.$refs.pool?.[index]?.test === 'function') {
|
|
2360
2420
|
try {
|
|
2361
2421
|
const res = await this.$refs.pool[index].test();
|
|
2362
2422
|
|
|
@@ -2473,7 +2533,22 @@ export default {
|
|
|
2473
2533
|
>
|
|
2474
2534
|
{{ appsOSWarning }}
|
|
2475
2535
|
</Banner>
|
|
2476
|
-
|
|
2536
|
+
<div class="span-12">
|
|
2537
|
+
<component
|
|
2538
|
+
:is="extensionInfrastructureSection"
|
|
2539
|
+
v-if="extensionInfrastructureSection"
|
|
2540
|
+
:value="infrastructureCluster"
|
|
2541
|
+
:mode="mode"
|
|
2542
|
+
:provider="provider"
|
|
2543
|
+
:credential-id="credentialId"
|
|
2544
|
+
:provisioning-cluster="value"
|
|
2545
|
+
data-testid="extension-top-section"
|
|
2546
|
+
class="span-12"
|
|
2547
|
+
@update:value="updateExtensionInfrastructureSection"
|
|
2548
|
+
@error="e => errors.push(e)"
|
|
2549
|
+
@validationChanged="(val) => infrastructureClusterValid = val"
|
|
2550
|
+
/>
|
|
2551
|
+
</div>
|
|
2477
2552
|
<!-- Pools Extras -->
|
|
2478
2553
|
<template v-if="hasMachinePools">
|
|
2479
2554
|
<div class="clearfix">
|
|
@@ -2507,7 +2582,6 @@ export default {
|
|
|
2507
2582
|
/>
|
|
2508
2583
|
</div>
|
|
2509
2584
|
</div>
|
|
2510
|
-
|
|
2511
2585
|
<!-- Extra Tabs for Machine Pool -->
|
|
2512
2586
|
<Tabbed
|
|
2513
2587
|
ref="pools"
|
|
@@ -2518,14 +2592,14 @@ export default {
|
|
|
2518
2592
|
>
|
|
2519
2593
|
<template
|
|
2520
2594
|
v-for="(obj, idx) in machinePools"
|
|
2521
|
-
:key="
|
|
2595
|
+
:key="obj.id"
|
|
2522
2596
|
>
|
|
2523
2597
|
<Tab
|
|
2524
2598
|
v-if="!obj.remove"
|
|
2525
2599
|
:key="obj.id"
|
|
2526
2600
|
:weight="-1 * idx"
|
|
2527
2601
|
:name="obj.id"
|
|
2528
|
-
:label="obj.pool.name || '
|
|
2602
|
+
:label="obj.pool.name || t('cluster.machinePool.name.notNamed')"
|
|
2529
2603
|
:show-header="false"
|
|
2530
2604
|
:error="!machinePoolValidation[obj.id]"
|
|
2531
2605
|
>
|
|
@@ -2542,6 +2616,8 @@ export default {
|
|
|
2542
2616
|
:busy="busy"
|
|
2543
2617
|
:pool-id="obj.id"
|
|
2544
2618
|
:pool-create-mode="obj.create"
|
|
2619
|
+
:infrastructure-cluster="infrastructureCluster"
|
|
2620
|
+
:hide-advanced="isUpstreamCAPIProvider"
|
|
2545
2621
|
@error="handleMachinePoolError"
|
|
2546
2622
|
@validationChanged="v => machinePoolValidationChanged(obj.id, v)"
|
|
2547
2623
|
/>
|
|
@@ -2688,6 +2764,7 @@ export default {
|
|
|
2688
2764
|
<Tab
|
|
2689
2765
|
:name="REGISTRIES_TAB_NAME"
|
|
2690
2766
|
label-key="cluster.tabs.registry"
|
|
2767
|
+
:error="!registryConfigValid"
|
|
2691
2768
|
>
|
|
2692
2769
|
<Registries
|
|
2693
2770
|
v-if="isActiveTabRegistries"
|
|
@@ -2703,6 +2780,7 @@ export default {
|
|
|
2703
2780
|
@custom-registry-changed="toggleCustomRegistry"
|
|
2704
2781
|
@registry-host-changed="handleRegistryHostChanged"
|
|
2705
2782
|
@registry-secret-changed="handleRegistrySecretChanged"
|
|
2783
|
+
@registry-validation-changed="(val) => registryConfigValid = val"
|
|
2706
2784
|
/>
|
|
2707
2785
|
</Tab>
|
|
2708
2786
|
|