@rancher/shell 3.0.7 → 3.0.8-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/brand/suse/banner.svg +1 -0
- package/assets/brand/suse/dark/banner.svg +1 -0
- package/assets/brand/suse/dark/login-landscape.svg +1 -0
- package/assets/brand/suse/dark/rancher-logo.svg +1 -1
- package/assets/brand/suse/favicon.png +0 -0
- package/assets/brand/suse/login-landscape.svg +1 -0
- package/assets/brand/suse/metadata.json +11 -1
- package/assets/brand/suse/rancher-logo.svg +1 -1
- package/assets/fonts/suse/suse-v2-latin-300.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-300.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff2 +0 -0
- package/assets/images/content/README.md +5 -0
- package/assets/images/content/cloud-native.svg +84 -0
- package/assets/images/content/dark/cloud-native.svg +21 -0
- package/assets/images/content/dark/shield.svg +59 -0
- package/assets/images/content/dark/suse.svg +10 -0
- package/assets/images/content/shield.svg +59 -0
- package/assets/images/content/suse.svg +10 -0
- package/assets/images/vendor/githubapp.svg +13 -0
- package/assets/styles/base/_typography.scss +2 -1
- package/assets/styles/fonts/_fontstack.scss +53 -1
- package/assets/styles/global/_cards.scss +0 -3
- package/assets/styles/global/_layout.scss +21 -35
- package/assets/styles/themes/_dark.scss +1 -1
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +16 -8
- package/assets/styles/themes/_suse.scss +116 -24
- package/assets/translations/en-us.yaml +185 -21
- package/assets/translations/zh-hans.yaml +0 -4
- package/components/AutoscalerCard.vue +113 -0
- package/components/AutoscalerTab.vue +94 -0
- package/components/BackLink.vue +8 -0
- package/components/BannerGraphic.vue +36 -21
- package/components/BrandImage.vue +17 -6
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/Cron/CronExpressionEditor.vue +1 -1
- package/components/Cron/CronExpressionEditorModal.vue +1 -1
- package/components/Drawer/Chrome.vue +2 -6
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
- package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
- package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
- package/components/Drawer/types.ts +3 -0
- package/components/DynamicContent/DynamicContentBanner.vue +102 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
- package/components/DynamicContent/DynamicContentIcon.vue +132 -0
- package/components/DynamicContent/DynamicContentPanel.vue +112 -0
- package/components/DynamicContent/content.ts +78 -0
- package/components/EmberPage.vue +1 -1
- package/components/IconOrSvg.vue +2 -2
- package/components/Inactivity.vue +222 -106
- package/components/InstallHelmCharts.vue +2 -2
- package/components/PaginatedResourceTable.vue +2 -6
- package/components/PopoverCard.vue +192 -0
- package/components/Questions/__tests__/index.test.ts +159 -0
- package/components/Resource/Detail/CopyToClipboard.vue +4 -1
- package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
- package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
- package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
- package/components/Resource/Detail/Metadata/composables.ts +9 -9
- package/components/Resource/Detail/Metadata/index.vue +3 -3
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
- package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
- package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -6
- package/components/Resource/Detail/composables.ts +12 -0
- package/components/ResourceDetail/Masthead/latest.vue +29 -0
- package/components/ResourceDetail/index.vue +5 -2
- package/components/ResourceList/Masthead.vue +1 -1
- package/components/SortableTable/index.vue +18 -2
- package/components/Tabbed/__tests__/index.test.ts +86 -0
- package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
- package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
- package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
- package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
- package/components/__tests__/AutoscalerCard.test.ts +154 -0
- package/components/__tests__/AutoscalerTab.test.ts +125 -0
- package/components/__tests__/PopoverCard.test.ts +204 -0
- package/components/auth/SelectPrincipal.vue +24 -6
- package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
- package/components/fleet/FleetConfigMapSelector.vue +117 -0
- package/components/fleet/FleetSecretSelector.vue +127 -0
- package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
- package/components/form/FileImageSelector.vue +13 -4
- package/components/form/FileSelector.vue +11 -2
- package/components/form/ResourceLabeledSelect.vue +1 -0
- package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
- package/components/formatter/Autoscaler.vue +97 -0
- package/components/formatter/InternalExternalIP.vue +198 -24
- package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
- package/components/google/util/__tests__/formatter.test.ts +47 -0
- package/components/google/util/formatter.ts +5 -2
- package/components/nav/Group.vue +12 -3
- package/components/nav/Header.vue +37 -16
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/index.vue +2 -1
- package/components/nav/TopLevelMenu.helper.ts +16 -6
- package/components/nav/TopLevelMenu.vue +4 -2
- package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
- package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
- package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
- package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
- package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
- package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
- package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
- package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
- package/components/nav/WindowManager/constants.ts +23 -0
- package/components/nav/WindowManager/index.vue +61 -575
- package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
- package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
- package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
- package/components/templates/default.vue +4 -40
- package/components/templates/home.vue +31 -5
- package/components/templates/plain.vue +30 -4
- package/components/templates/standalone.vue +1 -1
- package/composables/useI18n.ts +10 -1
- package/composables/useInterval.ts +15 -0
- package/config/__test__/uiplugins.test.ts +309 -0
- package/config/labels-annotations.js +9 -1
- package/config/product/auth.js +1 -0
- package/config/product/explorer.js +3 -1
- package/config/product/manager.js +20 -9
- package/config/query-params.js +1 -0
- package/config/router/routes.js +10 -2
- package/config/settings.ts +10 -2
- package/config/store.js +4 -2
- package/config/table-headers.js +8 -0
- package/config/types.js +11 -0
- package/config/uiplugins.js +46 -2
- package/config/version.js +1 -1
- package/core/__test__/extension-manager-impl.test.js +236 -0
- package/core/extension-manager-impl.js +23 -6
- package/core/plugin-helpers.ts +2 -0
- package/core/types-provisioning.ts +4 -1
- package/detail/pod.vue +1 -0
- package/detail/provisioning.cattle.io.cluster.vue +13 -1
- package/dialog/AddonConfigConfirmationDialog.vue +45 -1
- package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
- package/dialog/RollbackWorkloadDialog.vue +2 -5
- package/directives/ui-context.ts +103 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
- package/edit/auth/AuthProviderWarningBanners.vue +14 -1
- package/edit/auth/__tests__/oidc.test.ts +26 -0
- package/edit/auth/github-app-steps.vue +97 -0
- package/edit/auth/github-steps.vue +75 -0
- package/edit/auth/github.vue +99 -65
- package/edit/auth/oidc.vue +5 -1
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
- package/edit/cloudcredential.vue +1 -1
- package/edit/configmap.vue +1 -0
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +0 -10
- package/edit/fleet.cattle.io.helmop.vue +51 -2
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
- package/edit/logging-flow/index.vue +1 -0
- package/edit/logging.banzaicloud.io.output/index.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +1 -1
- package/edit/management.cattle.io.project.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
- package/edit/monitoring.coreos.com.route.vue +1 -1
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +1 -0
- package/edit/networking.k8s.io.ingress/index.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +27 -22
- package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
- package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
- package/edit/persistentvolume/plugins/azureFile.vue +15 -14
- package/edit/persistentvolume/plugins/cephfs.vue +15 -14
- package/edit/persistentvolume/plugins/cinder.vue +15 -14
- package/edit/persistentvolume/plugins/csi.vue +18 -16
- package/edit/persistentvolume/plugins/fc.vue +13 -14
- package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
- package/edit/persistentvolume/plugins/flocker.vue +1 -3
- package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
- package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
- package/edit/persistentvolume/plugins/hostPath.vue +40 -39
- package/edit/persistentvolume/plugins/iscsi.vue +13 -14
- package/edit/persistentvolume/plugins/local.vue +1 -3
- package/edit/persistentvolume/plugins/longhorn.vue +23 -22
- package/edit/persistentvolume/plugins/nfs.vue +15 -14
- package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
- package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
- package/edit/persistentvolume/plugins/quobyte.vue +15 -14
- package/edit/persistentvolume/plugins/rbd.vue +15 -14
- package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
- package/edit/persistentvolume/plugins/storageos.vue +15 -14
- package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
- package/edit/provisioning.cattle.io.cluster/index.vue +25 -15
- package/edit/provisioning.cattle.io.cluster/rke2.vue +98 -17
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
- package/edit/secret/index.vue +1 -1
- package/edit/service.vue +9 -4
- package/edit/serviceaccount.vue +1 -0
- package/edit/storage.k8s.io.storageclass/index.vue +1 -0
- package/edit/workload/index.vue +2 -1
- package/edit/workload/mixins/workload.js +1 -1
- package/initialize/App.vue +4 -4
- package/initialize/install-directives.js +2 -0
- package/initialize/install-plugins.js +19 -2
- package/list/projectsecret.vue +1 -1
- package/list/provisioning.cattle.io.cluster.vue +15 -2
- package/machine-config/amazonec2.vue +42 -135
- package/machine-config/azure.vue +1 -1
- package/machine-config/components/EC2Networking.vue +490 -0
- package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
- package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
- package/machine-config/digitalocean.vue +11 -0
- package/machine-config/google.vue +1 -1
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/__tests__/chart.test.ts +21 -0
- package/mixins/brand.js +1 -7
- package/mixins/chart.js +8 -2
- package/mixins/create-edit-view/index.js +5 -0
- package/models/__tests__/chart.test.ts +49 -12
- package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/chart.js +28 -14
- package/models/cluster/node.js +13 -6
- package/models/cluster.x-k8s.io.machine.js +10 -20
- package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
- package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/management.cattle.io.cluster.js +21 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +249 -33
- package/package.json +6 -5
- package/pages/auth/login.vue +43 -4
- package/pages/auth/verify.vue +1 -1
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
- package/pages/c/_cluster/apps/charts/chart.vue +35 -17
- package/pages/c/_cluster/apps/charts/index.vue +11 -13
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
- package/pages/c/_cluster/explorer/index.vue +8 -6
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
- package/pages/c/_cluster/settings/brand.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +12 -25
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
- package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
- package/pages/c/_cluster/uiplugins/index.vue +126 -184
- package/pages/home.vue +327 -16
- package/pkg/dynamic-importer.lib.js +4 -0
- package/plugins/axios.js +2 -1
- package/plugins/dashboard-client-init.js +3 -0
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/getters.js +18 -1
- package/plugins/dashboard-store/resource-class.js +21 -6
- package/plugins/dynamic-content.js +13 -0
- package/plugins/i18n.js +8 -0
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
- package/plugins/steve/steve-pagination-utils.ts +41 -22
- package/plugins/steve/subscribe.js +17 -9
- package/plugins/subscribe-events.ts +4 -2
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
- package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
- package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
- package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
- package/rancher-components/Pill/types.ts +0 -1
- package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
- package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
- package/rancher-components/RcIcon/RcIcon.vue +46 -0
- package/rancher-components/RcIcon/index.ts +1 -0
- package/rancher-components/RcIcon/types.ts +160 -0
- package/rancher-components/utils/status.test.ts +67 -0
- package/rancher-components/utils/status.ts +77 -0
- package/scripts/extension/publish +1 -1
- package/scripts/typegen.sh +1 -0
- package/store/action-menu.js +8 -0
- package/store/auth.js +11 -6
- package/store/aws.js +8 -6
- package/store/catalog.js +6 -0
- package/store/features.js +2 -0
- package/store/index.js +45 -20
- package/store/notifications.ts +51 -4
- package/store/plugins.js +7 -3
- package/store/prefs.js +12 -6
- package/store/type-map.js +3 -3
- package/store/ui-context.ts +86 -0
- package/store/wm.ts +244 -0
- package/types/kube/kube-api.ts +2 -1
- package/types/notifications/index.ts +27 -3
- package/types/rancher/index.d.ts +1 -0
- package/types/resources/settings.d.ts +29 -7
- package/types/shell/index.d.ts +138 -4
- package/types/store/__tests__/pagination.types.spec.ts +137 -0
- package/types/store/pagination.types.ts +157 -9
- package/types/store/subscribe-events.types.ts +8 -1
- package/types/store/subscribe.types.ts +1 -0
- package/types/window-manager.ts +24 -0
- package/utils/__tests__/cluster.test.ts +379 -1
- package/utils/__tests__/object.test.ts +19 -0
- package/utils/__tests__/provider.test.ts +98 -0
- package/utils/__tests__/selector-typed.test.ts +263 -0
- package/utils/__tests__/version.test.ts +19 -1
- package/utils/autoscaler-utils.ts +7 -0
- package/utils/back-off.ts +3 -3
- package/utils/brand.ts +29 -0
- package/utils/chart.js +18 -0
- package/utils/cluster.js +157 -3
- package/utils/color.js +1 -1
- package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
- package/utils/dynamic-content/__tests__/config.test.ts +187 -0
- package/utils/dynamic-content/__tests__/index.test.ts +390 -0
- package/utils/dynamic-content/__tests__/info.test.ts +275 -0
- package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
- package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
- package/utils/dynamic-content/__tests__/util.test.ts +235 -0
- package/utils/dynamic-content/announcement.ts +142 -0
- package/utils/dynamic-content/config.ts +55 -0
- package/utils/dynamic-content/example.json +40 -0
- package/utils/dynamic-content/index.ts +277 -0
- package/utils/dynamic-content/info.ts +261 -0
- package/utils/dynamic-content/new-release.ts +126 -0
- package/utils/dynamic-content/notification-handler.ts +48 -0
- package/utils/dynamic-content/support-notice.ts +169 -0
- package/utils/dynamic-content/types.d.ts +153 -0
- package/utils/dynamic-content/util.ts +122 -0
- package/utils/dynamic-importer.js +2 -2
- package/utils/favicon.js +4 -4
- package/utils/inactivity.ts +104 -0
- package/utils/object.js +20 -2
- package/utils/pagination-utils.ts +19 -4
- package/utils/pagination-wrapper.ts +12 -8
- package/utils/provider.ts +14 -0
- package/utils/release-notes.ts +1 -1
- package/utils/scroll.js +7 -0
- package/utils/selector-typed.ts +6 -2
- package/utils/settings.ts +15 -0
- package/utils/validators/machine-pool.ts +13 -3
- package/utils/version.js +15 -0
- package/assets/images/icons/document.svg +0 -3
- package/plugins/nuxt-client-init.js +0 -3
- package/store/wm.js +0 -95
- /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
- /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
- /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
package/config/settings.ts
CHANGED
|
@@ -52,6 +52,7 @@ export const SETTING = {
|
|
|
52
52
|
RKE_METADATA_CONFIG: 'rke-metadata-config',
|
|
53
53
|
EULA_AGREED: 'eula-agreed',
|
|
54
54
|
AUTH_USER_INFO_MAX_AGE_SECONDS: 'auth-user-info-max-age-seconds',
|
|
55
|
+
AUTH_USER_SESSION_IDLE_TTL_MINUTES: 'auth-user-session-idle-ttl-minutes',
|
|
55
56
|
AUTH_USER_SESSION_TTL_MINUTES: 'auth-user-session-ttl-minutes',
|
|
56
57
|
AUTH_USER_INFO_RESYNC_CRON: 'auth-user-info-resync-cron',
|
|
57
58
|
AUTH_LOCAL_VALIDATE_DESC: 'auth-password-requirements-description',
|
|
@@ -109,7 +110,13 @@ export const SETTING = {
|
|
|
109
110
|
SYSTEM_AGENT_UPGRADER_INSTALL_CONCURRENCY: 'system-agent-upgrader-install-concurrency',
|
|
110
111
|
IMPORTED_CLUSTER_VERSION_MANAGEMENT: 'imported-cluster-version-management',
|
|
111
112
|
CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS: 'cluster-agent-default-priority-class',
|
|
112
|
-
CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET: 'cluster-agent-default-pod-disruption-budget'
|
|
113
|
+
CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET: 'cluster-agent-default-pod-disruption-budget',
|
|
114
|
+
KEV2_OPERATORS: 'kev2-operators',
|
|
115
|
+
/**
|
|
116
|
+
* Dynamic Content settings
|
|
117
|
+
*/
|
|
118
|
+
DYNAMIC_CONTENT_ENABLED: 'ui-content-enabled',
|
|
119
|
+
DYNAMIC_CONTENT_ENDPOINT: 'ui-content-endpoint',
|
|
113
120
|
} as const;
|
|
114
121
|
|
|
115
122
|
// These are the settings that are allowed to be edited via the UI
|
|
@@ -140,6 +147,7 @@ export const ALLOWED_SETTINGS: GlobalSetting = {
|
|
|
140
147
|
},
|
|
141
148
|
[SETTING.INGRESS_IP_DOMAIN]: {},
|
|
142
149
|
[SETTING.AUTH_USER_INFO_MAX_AGE_SECONDS]: {},
|
|
150
|
+
[SETTING.AUTH_USER_SESSION_IDLE_TTL_MINUTES]: {},
|
|
143
151
|
[SETTING.AUTH_USER_SESSION_TTL_MINUTES]: {},
|
|
144
152
|
[SETTING.AUTH_TOKEN_MAX_TTL_MINUTES]: {},
|
|
145
153
|
[SETTING.KUBECONFIG_GENERATE_TOKEN]: { kind: 'boolean' },
|
|
@@ -186,7 +194,7 @@ export const PROVISIONING_SETTINGS = [
|
|
|
186
194
|
SETTING.K3S_UPGRADER_UNINSTALL_CONCURRENCY,
|
|
187
195
|
SETTING.IMPORTED_CLUSTER_VERSION_MANAGEMENT,
|
|
188
196
|
SETTING.CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS,
|
|
189
|
-
SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET
|
|
197
|
+
SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET,
|
|
190
198
|
];
|
|
191
199
|
|
|
192
200
|
/**
|
package/config/store.js
CHANGED
|
@@ -35,11 +35,12 @@ let store = {};
|
|
|
35
35
|
resolveStoreModules(require('../store/slideInPanel.ts'), 'slideInPanel.ts');
|
|
36
36
|
resolveStoreModules(require('../store/type-map.js'), 'type-map.js');
|
|
37
37
|
resolveStoreModules(require('../store/uiplugins.ts'), 'uiplugins.ts');
|
|
38
|
-
resolveStoreModules(require('../store/wm.
|
|
38
|
+
resolveStoreModules(require('../store/wm.ts'), 'wm.ts');
|
|
39
39
|
resolveStoreModules(require('../store/customisation.js'), 'customisation.js');
|
|
40
40
|
resolveStoreModules(require('../store/cru-resource.ts'), 'cru-resource.ts');
|
|
41
41
|
resolveStoreModules(require('../store/notifications.ts'), 'notifications.ts');
|
|
42
42
|
resolveStoreModules(require('../store/cookies.ts'), 'cookies.ts');
|
|
43
|
+
resolveStoreModules(require('../store/ui-context.ts'), 'ui-context.ts');
|
|
43
44
|
|
|
44
45
|
// If the environment supports hot reloading...
|
|
45
46
|
|
|
@@ -66,11 +67,12 @@ let store = {};
|
|
|
66
67
|
'../store/slideInPanel.ts',
|
|
67
68
|
'../store/type-map.js',
|
|
68
69
|
'../store/uiplugins.ts',
|
|
69
|
-
'../store/wm.
|
|
70
|
+
'../store/wm.ts',
|
|
70
71
|
'../store/customisation.js',
|
|
71
72
|
'../store/cru-resource.ts',
|
|
72
73
|
'../store/notifications.ts',
|
|
73
74
|
'../store/cookies.ts',
|
|
75
|
+
'../store/ui-context.ts',
|
|
74
76
|
], () => {
|
|
75
77
|
// Update `root.modules` with the latest definitions.
|
|
76
78
|
updateModules();
|
package/config/table-headers.js
CHANGED
|
@@ -1183,3 +1183,11 @@ export const PROJECT = {
|
|
|
1183
1183
|
name: 'project',
|
|
1184
1184
|
labelKey: 'tableHeaders.project',
|
|
1185
1185
|
};
|
|
1186
|
+
|
|
1187
|
+
export const AUTOSCALER_ENABLED = {
|
|
1188
|
+
name: 'autoscaler',
|
|
1189
|
+
labelKey: 'tableHeaders.autoscaler',
|
|
1190
|
+
value: 'isAutoscalerEnabled',
|
|
1191
|
+
sort: ['autoscaler'],
|
|
1192
|
+
formatter: 'Autoscaler',
|
|
1193
|
+
};
|
package/config/types.js
CHANGED
|
@@ -222,6 +222,15 @@ export const MANAGEMENT = {
|
|
|
222
222
|
OIDC_CLIENT: 'management.cattle.io.oidcclient'
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
+
export const BRAND = {
|
|
226
|
+
SUSE: 'suse',
|
|
227
|
+
CSP: 'csp',
|
|
228
|
+
FEDERAL: 'federal',
|
|
229
|
+
RGS: 'rgs',
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export const EXT = { USER_ACTIVITY: 'ext.cattle.io.useractivity' };
|
|
233
|
+
|
|
225
234
|
export const CAPI = {
|
|
226
235
|
CAPI_CLUSTER: 'cluster.x-k8s.io.cluster',
|
|
227
236
|
MACHINE_DEPLOYMENT: 'cluster.x-k8s.io.machinedeployment',
|
|
@@ -362,3 +371,5 @@ export const DEFAULT_GRAFANA_STORAGE_SIZE = '10Gi';
|
|
|
362
371
|
|
|
363
372
|
export const DEPRECATED = 'Deprecated';
|
|
364
373
|
export const EXPERIMENTAL = 'Experimental';
|
|
374
|
+
export const AUTOSCALER_CONFIG_MAP_ID = 'kube-system/cluster-autoscaler-status';
|
|
375
|
+
export const HOSTED_PROVIDER = 'hostedprovider';
|
package/config/uiplugins.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
|
+
import { isRancherPrime } from '@shell/config/version';
|
|
2
3
|
|
|
3
4
|
// Version of the plugin API supported
|
|
4
5
|
// here we inject the current shell version that we read in vue.config
|
|
@@ -43,6 +44,7 @@ export const UI_PLUGIN_CHART_ANNOTATIONS = {
|
|
|
43
44
|
EXTENSIONS_HOST: 'catalog.cattle.io/ui-extensions-host',
|
|
44
45
|
DISPLAY_NAME: 'catalog.cattle.io/display-name',
|
|
45
46
|
HIDDEN_BUILTIN: 'catalog.cattle.io/ui-hidden-builtin',
|
|
47
|
+
PRIME_ONLY: 'catalog.cattle.io/prime-only'
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
// Extension catalog labels
|
|
@@ -58,6 +60,7 @@ export const EXTENSIONS_INCOMPATIBILITY_TYPES = {
|
|
|
58
60
|
EXTENSIONS_API: 'extensionsApiVersion',
|
|
59
61
|
KUBE: 'kubeVersion',
|
|
60
62
|
HOST: 'host',
|
|
63
|
+
PRIME_ONLY: 'primeOnly',
|
|
61
64
|
};
|
|
62
65
|
|
|
63
66
|
export const EXTENSIONS_INCOMPATIBILITY_DATA = {
|
|
@@ -87,6 +90,11 @@ export const EXTENSIONS_INCOMPATIBILITY_DATA = {
|
|
|
87
90
|
tooltipKey: 'plugins.info.requiresHost',
|
|
88
91
|
mainHost: UI_PLUGIN_HOST_APP,
|
|
89
92
|
},
|
|
93
|
+
PRIME_ONLY: {
|
|
94
|
+
type: EXTENSIONS_INCOMPATIBILITY_TYPES.PRIME_ONLY,
|
|
95
|
+
cardMessageKey: 'plugins.incompatiblePrimeOnly',
|
|
96
|
+
tooltipKey: 'plugins.info.requiresRancherPrime',
|
|
97
|
+
},
|
|
90
98
|
};
|
|
91
99
|
|
|
92
100
|
export function isUIPlugin(chart) {
|
|
@@ -124,10 +132,29 @@ export function parseRancherVersion(v) {
|
|
|
124
132
|
* Check if a version is incompatible with the current environment
|
|
125
133
|
*/
|
|
126
134
|
function checkIncompatibility(currentVersion, requiredVersion, incompatibilityData, returnObj, versionObj) {
|
|
127
|
-
|
|
135
|
+
let passed = true;
|
|
136
|
+
|
|
137
|
+
switch (incompatibilityData.type) {
|
|
138
|
+
case EXTENSIONS_INCOMPATIBILITY_TYPES.PRIME_ONLY:
|
|
139
|
+
if (requiredVersion && !currentVersion) {
|
|
140
|
+
passed = false;
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
case EXTENSIONS_INCOMPATIBILITY_TYPES.EXTENSIONS_API_MISSING:
|
|
144
|
+
!requiredVersion ? passed = false : passed = true;
|
|
145
|
+
break;
|
|
146
|
+
default:
|
|
147
|
+
if (requiredVersion && !semver.satisfies(currentVersion, requiredVersion)) {
|
|
148
|
+
passed = false;
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!passed) {
|
|
128
154
|
if (!returnObj) {
|
|
129
155
|
return false;
|
|
130
156
|
}
|
|
157
|
+
|
|
131
158
|
versionObj.isVersionCompatible = false;
|
|
132
159
|
versionObj.versionIncompatibilityData = { ...incompatibilityData, required: requiredVersion };
|
|
133
160
|
|
|
@@ -137,7 +164,7 @@ function checkIncompatibility(currentVersion, requiredVersion, incompatibilityDa
|
|
|
137
164
|
return true;
|
|
138
165
|
}
|
|
139
166
|
|
|
140
|
-
// i18n-uses plugins.error.generic, plugins.error.api, plugins.error.host, plugins.error.kubeVersion, plugins.error.version, plugins.error.developerPkg, plugins.error.apiAnnotationMissing
|
|
167
|
+
// i18n-uses plugins.error.generic, plugins.error.api, plugins.error.host, plugins.error.kubeVersion, plugins.error.version, plugins.error.developerPkg, plugins.error.apiAnnotationMissing, plugins.error.primeOnly
|
|
141
168
|
|
|
142
169
|
/**
|
|
143
170
|
* Whether an extension should be loaded based on the metadata returned by the backend in the UIPlugins resource instance
|
|
@@ -148,6 +175,8 @@ function checkIncompatibility(currentVersion, requiredVersion, incompatibilityDa
|
|
|
148
175
|
* @returns String | Boolean
|
|
149
176
|
*/
|
|
150
177
|
export function shouldNotLoadPlugin(UIPluginResource, { rancherVersion, kubeVersion }, loadedPlugins) {
|
|
178
|
+
const isCurrRancherPrime = isRancherPrime();
|
|
179
|
+
|
|
151
180
|
const {
|
|
152
181
|
name, version, endpoint, compressedEndpoint
|
|
153
182
|
} = UIPluginResource;
|
|
@@ -171,6 +200,13 @@ export function shouldNotLoadPlugin(UIPluginResource, { rancherVersion, kubeVers
|
|
|
171
200
|
return 'plugins.error.api';
|
|
172
201
|
}
|
|
173
202
|
|
|
203
|
+
// Prime only
|
|
204
|
+
const primeOnlyAnnotation = UIPluginResource.metadata?.[UI_PLUGIN_CHART_ANNOTATIONS.PRIME_ONLY] === 'true';
|
|
205
|
+
|
|
206
|
+
if (!isCurrRancherPrime && primeOnlyAnnotation) {
|
|
207
|
+
return 'plugins.error.primeOnly';
|
|
208
|
+
}
|
|
209
|
+
|
|
174
210
|
// Host application
|
|
175
211
|
const requiredHost = UIPluginResource.metadata?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_HOST];
|
|
176
212
|
|
|
@@ -220,10 +256,13 @@ export function shouldNotLoadPlugin(UIPluginResource, { rancherVersion, kubeVers
|
|
|
220
256
|
* @returns Boolean | Object
|
|
221
257
|
*/
|
|
222
258
|
export function isSupportedChartVersion(versionData, returnObj = false) {
|
|
259
|
+
const isCurrRancherPrime = isRancherPrime();
|
|
260
|
+
|
|
223
261
|
const { version, rancherVersion, kubeVersion } = versionData;
|
|
224
262
|
const versionObj = {
|
|
225
263
|
...version, isVersionCompatible: true, versionIncompatibilityData: {}
|
|
226
264
|
};
|
|
265
|
+
|
|
227
266
|
const parsedRancherVersion = rancherVersion ? parseRancherVersion(rancherVersion) : '';
|
|
228
267
|
const parsedUiExtensionsApiVersion = semver.coerce(UI_EXTENSIONS_API_VERSION)?.version;
|
|
229
268
|
|
|
@@ -258,6 +297,11 @@ export function isSupportedChartVersion(versionData, returnObj = false) {
|
|
|
258
297
|
requiredVersion: version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_HOST],
|
|
259
298
|
incompatibilityData: EXTENSIONS_INCOMPATIBILITY_DATA.HOST,
|
|
260
299
|
},
|
|
300
|
+
{
|
|
301
|
+
currentVersion: isCurrRancherPrime,
|
|
302
|
+
requiredVersion: version.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.PRIME_ONLY] === 'true',
|
|
303
|
+
incompatibilityData: EXTENSIONS_INCOMPATIBILITY_DATA.PRIME_ONLY,
|
|
304
|
+
}
|
|
261
305
|
];
|
|
262
306
|
|
|
263
307
|
for (const { currentVersion, requiredVersion, incompatibilityData } of checks) {
|
package/config/version.js
CHANGED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { DEVELOPER_LOAD_NAME_SUFFIX } from '@shell/core/extension-manager-impl';
|
|
2
|
+
|
|
3
|
+
// Mock external dependencies
|
|
4
|
+
jest.mock('@shell/store/type-map', () => ({ productsLoaded: jest.fn().mockReturnValue(true) }));
|
|
5
|
+
|
|
6
|
+
jest.mock('@shell/plugins/dashboard-store/model-loader', () => ({ clearModelCache: jest.fn() }));
|
|
7
|
+
|
|
8
|
+
jest.mock('@shell/config/uiplugins', () => ({ UI_PLUGIN_BASE_URL: '/api/v1/uiplugins' }));
|
|
9
|
+
|
|
10
|
+
jest.mock('@shell/plugins/clean-html', () => ({
|
|
11
|
+
addLinkInterceptor: jest.fn(),
|
|
12
|
+
removeLinkInterceptor: jest.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Mock the Plugin class
|
|
16
|
+
jest.mock('@shell/core/plugin', () => {
|
|
17
|
+
return {
|
|
18
|
+
Plugin: jest.fn().mockImplementation((id) => ({
|
|
19
|
+
id,
|
|
20
|
+
name: id,
|
|
21
|
+
types: {},
|
|
22
|
+
uiConfig: {},
|
|
23
|
+
l10n: {},
|
|
24
|
+
modelExtensions: {},
|
|
25
|
+
stores: [],
|
|
26
|
+
locales: [],
|
|
27
|
+
routes: [],
|
|
28
|
+
validators: {},
|
|
29
|
+
uninstallHooks: [],
|
|
30
|
+
productNames: [],
|
|
31
|
+
})),
|
|
32
|
+
EXT_IDS: {
|
|
33
|
+
MODELS: 'models',
|
|
34
|
+
MODEL_EXTENSION: 'model-extension'
|
|
35
|
+
},
|
|
36
|
+
ExtensionPoint: { EDIT_YAML: 'edit-yaml' }
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Mock PluginRoutes
|
|
41
|
+
jest.mock('@shell/core/plugin-routes', () => {
|
|
42
|
+
return { PluginRoutes: jest.fn().mockImplementation(() => ({ addRoutes: jest.fn() })) };
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('extension Manager', () => {
|
|
46
|
+
let mockStore;
|
|
47
|
+
let mockApp;
|
|
48
|
+
let context;
|
|
49
|
+
|
|
50
|
+
// These variables will be assigned the fresh functions inside beforeEach
|
|
51
|
+
let initExtensionManager;
|
|
52
|
+
let getExtensionManager;
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
// singleton instance for every test run, preventing mock store leaks.
|
|
56
|
+
jest.resetModules();
|
|
57
|
+
|
|
58
|
+
// Re-require the System Under Test (SUT)
|
|
59
|
+
const extensionManagerModule = require('../extension-manager-impl');
|
|
60
|
+
|
|
61
|
+
initExtensionManager = extensionManagerModule.initExtensionManager;
|
|
62
|
+
getExtensionManager = extensionManagerModule.getExtensionManager;
|
|
63
|
+
|
|
64
|
+
jest.clearAllMocks();
|
|
65
|
+
|
|
66
|
+
// Setup Mock Context
|
|
67
|
+
mockStore = {
|
|
68
|
+
getters: { 'i18n/t': jest.fn() },
|
|
69
|
+
dispatch: jest.fn(),
|
|
70
|
+
commit: jest.fn(),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
mockApp = { router: {} };
|
|
74
|
+
|
|
75
|
+
context = {
|
|
76
|
+
app: mockApp,
|
|
77
|
+
store: mockStore,
|
|
78
|
+
$axios: {},
|
|
79
|
+
redirect: jest.fn(),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Clean up DOM from previous tests
|
|
83
|
+
document.head.innerHTML = '';
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('singleton Pattern', () => {
|
|
87
|
+
it('initializes and returns the same instance', () => {
|
|
88
|
+
const instance1 = initExtensionManager(context);
|
|
89
|
+
const instance2 = getExtensionManager();
|
|
90
|
+
const instance3 = initExtensionManager(context);
|
|
91
|
+
|
|
92
|
+
expect(instance1).toBeDefined();
|
|
93
|
+
expect(instance1).toBe(instance2);
|
|
94
|
+
expect(instance1).toBe(instance3);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('registration (Dynamic)', () => {
|
|
99
|
+
it('registers and retrieves a dynamic component', () => {
|
|
100
|
+
const manager = initExtensionManager(context);
|
|
101
|
+
const mockFn = jest.fn();
|
|
102
|
+
|
|
103
|
+
manager.register('component', 'my-component', mockFn);
|
|
104
|
+
|
|
105
|
+
const retrieved = manager.getDynamic('component', 'my-component');
|
|
106
|
+
|
|
107
|
+
expect(retrieved).toBe(mockFn);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('unregisters a dynamic component', () => {
|
|
111
|
+
const manager = initExtensionManager(context);
|
|
112
|
+
const mockFn = jest.fn();
|
|
113
|
+
|
|
114
|
+
manager.register('component', 'my-component', mockFn);
|
|
115
|
+
manager.unregister('component', 'my-component');
|
|
116
|
+
|
|
117
|
+
const retrieved = manager.getDynamic('component', 'my-component');
|
|
118
|
+
|
|
119
|
+
expect(retrieved).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('loadPluginAsync (URL Generation)', () => {
|
|
124
|
+
let manager;
|
|
125
|
+
|
|
126
|
+
beforeEach(() => {
|
|
127
|
+
manager = initExtensionManager(context);
|
|
128
|
+
// Mock the internal loadAsync so we only test URL generation here
|
|
129
|
+
jest.spyOn(manager, 'loadAsync').mockImplementation().mockResolvedValue();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('generates correct URL for standard plugin', async() => {
|
|
133
|
+
const pluginData = { name: 'elemental', version: '1.0.0' };
|
|
134
|
+
const expectedId = 'elemental-1.0.0';
|
|
135
|
+
const expectedUrl = `/api/v1/uiplugins/elemental/1.0.0/plugin/elemental-1.0.0.umd.min.js`;
|
|
136
|
+
|
|
137
|
+
await manager.loadPluginAsync(pluginData);
|
|
138
|
+
|
|
139
|
+
expect(manager.loadAsync).toHaveBeenCalledWith(expectedId, expectedUrl);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('handles "direct" metadata plugins', async() => {
|
|
143
|
+
const pluginData = {
|
|
144
|
+
name: 'direct-plugin',
|
|
145
|
+
version: '1.0.0',
|
|
146
|
+
endpoint: 'http://localhost:8000/plugin.js',
|
|
147
|
+
metadata: { direct: 'true' }
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
await manager.loadPluginAsync(pluginData);
|
|
151
|
+
|
|
152
|
+
expect(manager.loadAsync).toHaveBeenCalledWith('direct-plugin-1.0.0', 'http://localhost:8000/plugin.js');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('removes developer suffix from ID but keeps it for internal logic', async() => {
|
|
156
|
+
const pluginData = {
|
|
157
|
+
name: `my-plugin${ DEVELOPER_LOAD_NAME_SUFFIX }`,
|
|
158
|
+
version: `1.0.0`
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
await manager.loadPluginAsync(pluginData);
|
|
162
|
+
|
|
163
|
+
// Expected ID passed to loadAsync should NOT have the suffix
|
|
164
|
+
const expectedIdWithoutSuffix = 'my-plugin-1.0.0';
|
|
165
|
+
|
|
166
|
+
expect(manager.loadAsync).toHaveBeenCalledWith(
|
|
167
|
+
expectedIdWithoutSuffix,
|
|
168
|
+
expect.any(String)
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('loadAsync (Script Injection)', () => {
|
|
174
|
+
let manager;
|
|
175
|
+
|
|
176
|
+
beforeEach(() => {
|
|
177
|
+
manager = initExtensionManager(context);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('resolves immediately if element already exists', async() => {
|
|
181
|
+
const id = 'existing-plugin';
|
|
182
|
+
const script = document.createElement('script');
|
|
183
|
+
|
|
184
|
+
script.id = id;
|
|
185
|
+
document.body.appendChild(script);
|
|
186
|
+
|
|
187
|
+
await expect(manager.loadAsync(id, 'url.js')).resolves.toBeUndefined();
|
|
188
|
+
|
|
189
|
+
document.body.removeChild(script);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('injects script tag and initializes plugin on load', async() => {
|
|
193
|
+
const pluginId = 'test-plugin';
|
|
194
|
+
const pluginUrl = 'http://test.com/plugin.js';
|
|
195
|
+
|
|
196
|
+
// Mock the window object to simulate the plugin loading into global scope
|
|
197
|
+
const mockPluginInit = jest.fn();
|
|
198
|
+
|
|
199
|
+
window[pluginId] = { default: mockPluginInit };
|
|
200
|
+
|
|
201
|
+
// Start the load
|
|
202
|
+
const loadPromise = manager.loadAsync(pluginId, pluginUrl);
|
|
203
|
+
|
|
204
|
+
// Find the injected script tag in the DOM
|
|
205
|
+
const script = document.head.querySelector(`script[id="${ pluginId }"]`);
|
|
206
|
+
|
|
207
|
+
expect(script).toBeTruthy();
|
|
208
|
+
expect(script.src).toBe(pluginUrl);
|
|
209
|
+
|
|
210
|
+
// Manually trigger the onload event
|
|
211
|
+
script.onload();
|
|
212
|
+
|
|
213
|
+
// Await the promise
|
|
214
|
+
await loadPromise;
|
|
215
|
+
|
|
216
|
+
// Assertions
|
|
217
|
+
expect(mockPluginInit).toHaveBeenCalledWith(expect.objectContaining({ id: pluginId }), expect.objectContaining({ ...context }));
|
|
218
|
+
expect(mockStore.dispatch).toHaveBeenCalledWith('uiplugins/addPlugin', expect.objectContaining({ id: pluginId }));
|
|
219
|
+
|
|
220
|
+
// Cleanup
|
|
221
|
+
delete window[pluginId];
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('rejects if script load fails', async() => {
|
|
225
|
+
const pluginId = 'fail-plugin';
|
|
226
|
+
const loadPromise = manager.loadAsync(pluginId, 'bad-url.js');
|
|
227
|
+
|
|
228
|
+
const script = document.head.querySelector(`script[id="${ pluginId }"]`);
|
|
229
|
+
|
|
230
|
+
// Trigger error
|
|
231
|
+
script.onerror({ target: { src: 'bad-url.js' } });
|
|
232
|
+
|
|
233
|
+
await expect(loadPromise).rejects.toThrow('Failed to load script');
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
@@ -6,6 +6,8 @@ import { UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
|
|
|
6
6
|
import { ExtensionPoint } from './types';
|
|
7
7
|
import { addLinkInterceptor, removeLinkInterceptor } from '@shell/plugins/clean-html';
|
|
8
8
|
|
|
9
|
+
export const DEVELOPER_LOAD_NAME_SUFFIX = '-developer-load';
|
|
10
|
+
|
|
9
11
|
let extensionManagerInstance;
|
|
10
12
|
|
|
11
13
|
const createExtensionManager = (context) => {
|
|
@@ -35,11 +37,11 @@ const createExtensionManager = (context) => {
|
|
|
35
37
|
*/
|
|
36
38
|
function instantiateModelExtension($plugin, clz) {
|
|
37
39
|
const context = {
|
|
38
|
-
dispatch:
|
|
39
|
-
getters:
|
|
40
|
-
t:
|
|
40
|
+
dispatch: store.dispatch,
|
|
41
|
+
getters: store.getters,
|
|
42
|
+
t: store.getters['i18n/t'],
|
|
41
43
|
$axios,
|
|
42
|
-
$plugin,
|
|
44
|
+
$extension: $plugin,
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
return new clz(context);
|
|
@@ -63,9 +65,18 @@ const createExtensionManager = (context) => {
|
|
|
63
65
|
// Load a plugin from a UI package
|
|
64
66
|
loadPluginAsync(plugin) {
|
|
65
67
|
const { name, version } = plugin;
|
|
66
|
-
|
|
68
|
+
let id = `${ name }-${ version }`;
|
|
67
69
|
let url;
|
|
68
70
|
|
|
71
|
+
// for a developer load, we need to remove the suffix applied
|
|
72
|
+
// otherwise the extension won't load correctly
|
|
73
|
+
// but with this at least we won't hit developer loaded cards find charts
|
|
74
|
+
// when they aren't supposed to
|
|
75
|
+
if (id.includes(DEVELOPER_LOAD_NAME_SUFFIX)) {
|
|
76
|
+
id = id.replace(DEVELOPER_LOAD_NAME_SUFFIX, '');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// this is where a developer load hits (direct=true, developer=true)
|
|
69
80
|
if (plugin?.metadata?.direct === 'true') {
|
|
70
81
|
url = plugin.endpoint;
|
|
71
82
|
} else {
|
|
@@ -455,7 +466,13 @@ const createExtensionManager = (context) => {
|
|
|
455
466
|
try {
|
|
456
467
|
const provisioner = context.$extension.getDynamic('provisioner', name);
|
|
457
468
|
|
|
458
|
-
|
|
469
|
+
const defaults = {
|
|
470
|
+
isCreate: false,
|
|
471
|
+
isEdit: false,
|
|
472
|
+
isView: false
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
return new provisioner({ ...defaults, ...context });
|
|
459
476
|
} catch (e) {
|
|
460
477
|
console.error('Error loading provisioner(s) from extensions', e); // eslint-disable-line no-console
|
|
461
478
|
}
|
package/core/plugin-helpers.ts
CHANGED
|
@@ -63,7 +63,7 @@ export interface ClusterProvisionerContext {
|
|
|
63
63
|
/**
|
|
64
64
|
* Definition of the extension
|
|
65
65
|
*/
|
|
66
|
-
$
|
|
66
|
+
$extension: any,
|
|
67
67
|
/**
|
|
68
68
|
* Function to retrieve a localised string
|
|
69
69
|
*/
|
|
@@ -158,6 +158,9 @@ export interface IClusterProvisioner {
|
|
|
158
158
|
*/
|
|
159
159
|
hideCreate?: boolean
|
|
160
160
|
|
|
161
|
+
/** Is extension Prime-only */
|
|
162
|
+
prime?: boolean
|
|
163
|
+
|
|
161
164
|
/**
|
|
162
165
|
* Also show the provider card in the cluster importing flow
|
|
163
166
|
* If not set, the card will only be shown in the cluster creation page
|
package/detail/pod.vue
CHANGED
|
@@ -97,6 +97,7 @@ export default {
|
|
|
97
97
|
|
|
98
98
|
return {
|
|
99
99
|
...container,
|
|
100
|
+
kind: 'Container',
|
|
100
101
|
status: status || {},
|
|
101
102
|
stateDisplay: status ? this.value.containerStateDisplay(status) : undefined,
|
|
102
103
|
stateBackground: status ? this.value.containerStateColor(status).replace('text', 'bg') : undefined,
|
|
@@ -33,6 +33,8 @@ import { isAlternate } from '@shell/utils/platform';
|
|
|
33
33
|
import DetailPage from '@shell/components/Resource/Detail/Page.vue';
|
|
34
34
|
import Masthead from '@shell/components/Resource/Detail/Masthead/index.vue';
|
|
35
35
|
import { useDefaultMastheadProps } from '@shell/components/Resource/Detail/Masthead/composable';
|
|
36
|
+
import AutoscalerTab from '@shell/components/AutoscalerTab.vue';
|
|
37
|
+
import { isAutoscalerFeatureFlagEnabled } from '@shell/utils/autoscaler-utils';
|
|
36
38
|
|
|
37
39
|
let lastId = 1;
|
|
38
40
|
const ansiup = new AnsiUp();
|
|
@@ -62,6 +64,7 @@ export default {
|
|
|
62
64
|
emits: ['input'],
|
|
63
65
|
|
|
64
66
|
components: {
|
|
67
|
+
AutoscalerTab,
|
|
65
68
|
Banner,
|
|
66
69
|
ResourceTable,
|
|
67
70
|
ResourceTabs,
|
|
@@ -575,6 +578,7 @@ export default {
|
|
|
575
578
|
// Hosted kubernetes providers with private endpoints need the registration tab
|
|
576
579
|
// https://github.com/rancher/dashboard/issues/6036
|
|
577
580
|
// https://github.com/rancher/dashboard/issues/4545
|
|
581
|
+
|
|
578
582
|
if ( this.value.isHostedKubernetesProvider && this.value.isPrivateHostedProvider && !this.isClusterReady ) {
|
|
579
583
|
return this.extDetailTabs.registration;
|
|
580
584
|
}
|
|
@@ -620,6 +624,10 @@ export default {
|
|
|
620
624
|
|
|
621
625
|
extDetailTabsConditions() {
|
|
622
626
|
return this.extDetailTabs?.conditions;
|
|
627
|
+
},
|
|
628
|
+
|
|
629
|
+
showAutoScalerTab() {
|
|
630
|
+
return isAutoscalerFeatureFlagEnabled(this.$store) && this.value.hasAccessToAutoscalerConfigMap;
|
|
623
631
|
}
|
|
624
632
|
},
|
|
625
633
|
|
|
@@ -870,7 +878,7 @@ export default {
|
|
|
870
878
|
</div>
|
|
871
879
|
</div>
|
|
872
880
|
<div
|
|
873
|
-
v-if="group.ref"
|
|
881
|
+
v-if="group.ref && !group.ref.isAutoscalerEnabled"
|
|
874
882
|
class="right group-header-buttons mr-20"
|
|
875
883
|
>
|
|
876
884
|
<MachineSummaryGraph
|
|
@@ -1119,6 +1127,10 @@ export default {
|
|
|
1119
1127
|
</template>
|
|
1120
1128
|
</SortableTable>
|
|
1121
1129
|
</Tab>
|
|
1130
|
+
<AutoscalerTab
|
|
1131
|
+
v-if="showAutoScalerTab"
|
|
1132
|
+
:value="value"
|
|
1133
|
+
/>
|
|
1122
1134
|
</ResourceTabs>
|
|
1123
1135
|
</div>
|
|
1124
1136
|
</template>
|