@rancher/shell 0.3.4 → 0.3.6
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/images/providers/outscale.svg +19 -0
- package/assets/styles/app.scss +1 -1
- package/assets/styles/base/_basic.scss +18 -0
- package/assets/styles/base/_mixins.scss +0 -11
- package/assets/styles/base/_variables.scss +2 -4
- package/assets/styles/fonts/_fontstack.scss +11 -11
- package/assets/styles/global/_button.scss +12 -2
- package/assets/styles/vendor/vue-js-modal.scss +3 -3
- package/assets/translations/en-us.yaml +113 -22
- package/assets/translations/zh-hans.yaml +113 -24
- package/babel.config.js +13 -0
- package/chart/gatekeeper.vue +78 -0
- package/chart/istio.vue +135 -112
- package/chart/logging/index.vue +13 -4
- package/chart/monitoring/index.vue +15 -5
- package/chart/monitoring/steps/uninstall-v1.vue +2 -2
- package/chart/rancher-backup/index.vue +10 -3
- package/cloud-credential/aws.vue +1 -1
- package/cloud-credential/digitalocean.vue +1 -1
- package/cloud-credential/gcp.vue +1 -1
- package/cloud-credential/generic.vue +2 -2
- package/cloud-credential/linode.vue +1 -1
- package/cloud-credential/pnap.vue +1 -1
- package/components/ActionMenu.vue +3 -4
- package/components/AssignTo.vue +1 -1
- package/components/AsyncButton.vue +1 -1
- package/components/BannerGraphic.vue +1 -1
- package/components/BrandImage.vue +1 -4
- package/components/ButtonDropdown.vue +2 -3
- package/components/Carousel.vue +85 -37
- package/components/ChartPsp.vue +76 -0
- package/components/CruResource.vue +6 -2
- package/components/DashboardMetrics.vue +12 -10
- package/components/DetailText.vue +1 -1
- package/components/DisableAuthProviderModal.vue +1 -1
- package/components/EmberPage.vue +1 -1
- package/components/EtcdInfoBanner.vue +12 -7
- package/components/ExplorerMembers.vue +101 -6
- package/components/ExplorerProjectsNamespaces.vue +46 -3
- package/components/FileDiff.vue +6 -7
- package/components/GrafanaDashboard.vue +27 -23
- package/components/LazyImage.vue +10 -12
- package/components/LogItem.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/PromptRemove.vue +2 -2
- package/components/PromptRestore.vue +1 -1
- package/components/ResourceDetail/Masthead.vue +16 -0
- package/components/ResourceDetail/index.vue +21 -4
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +4 -1
- package/components/SingleClusterInfo.vue +2 -2
- package/components/SortableTable/THead.vue +1 -1
- package/components/SortableTable/index.vue +28 -13
- package/components/SortableTable/selection.js +58 -50
- package/components/Wizard.vue +4 -2
- package/components/__tests__/AsyncButton.test.ts +3 -1
- package/components/__tests__/ChartPsp.test.ts +75 -0
- package/components/__tests__/CruResource.test.ts +3 -1
- package/components/auth/Principal.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +2 -2
- package/components/fleet/FleetBundles.vue +3 -1
- package/components/fleet/FleetClusters.vue +1 -2
- package/components/fleet/FleetIntro.vue +9 -1
- package/components/fleet/FleetNoWorkspaces.vue +62 -0
- package/components/fleet/FleetSummary.vue +7 -1
- package/components/form/HookOption.vue +14 -10
- package/components/form/LabeledSelect.vue +14 -11
- package/components/form/Labels.vue +32 -27
- package/components/form/MatchExpressions.vue +19 -4
- package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
- package/components/form/NameNsDescription.vue +32 -46
- package/components/form/ProjectMemberEditor.vue +46 -21
- package/components/form/ResourceSelector.vue +1 -1
- package/components/form/SecretSelector.vue +5 -1
- package/components/form/ServiceNameSelect.vue +1 -1
- package/components/form/SimpleSecretSelector.vue +9 -9
- package/components/form/Tolerations.vue +4 -1
- package/components/form/ValueFromResource.vue +14 -9
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/form/__tests__/LabeledSelect.test.ts +138 -0
- package/components/form/__tests__/NameNsDescription.ts +59 -0
- package/components/formatter/InternalExternalIP.vue +6 -0
- package/components/formatter/InvolvedObjectLink.vue +54 -0
- package/components/formatter/Link.vue +20 -4
- package/components/formatter/LinkName.vue +6 -1
- package/components/formatter/ServiceTargets.vue +1 -1
- package/components/formatter/WorkloadHealthScale.vue +8 -2
- package/components/nav/Group.vue +2 -2
- package/components/nav/NamespaceFilter.vue +23 -11
- package/components/nav/TopLevelMenu.vue +2 -4
- package/components/nav/Type.vue +1 -1
- package/components/nav/WorkspaceSwitcher.vue +46 -5
- package/components/nuxt/nuxt-build-indicator.vue +143 -0
- package/components/nuxt/nuxt-child.js +122 -0
- package/components/nuxt/nuxt-error.vue +98 -0
- package/components/nuxt/nuxt-link.client.js +98 -0
- package/components/nuxt/nuxt-link.server.js +16 -0
- package/components/nuxt/nuxt-loading.vue +154 -0
- package/components/nuxt/nuxt.js +101 -0
- package/config/labels-annotations.js +17 -0
- package/config/middleware.js +12 -0
- package/config/product/auth.js +3 -2
- package/config/product/explorer.js +34 -6
- package/config/product/fleet.js +2 -0
- package/config/query-params.js +1 -0
- package/config/router.js +414 -0
- package/config/store.js +181 -0
- package/config/table-headers.js +54 -12
- package/config/types.js +18 -8
- package/config/uiplugins.js +30 -0
- package/content/docs/en-us/whats-new.md +10 -0
- package/content/docs/zh-hans/whats-new.md +11 -1
- package/core/plugin-routes.ts +23 -0
- package/core/plugin.ts +4 -2
- package/core/types.ts +258 -1
- package/creators/app/app.package.json +2 -1
- package/creators/app/files/.eslintrc.js +1 -1
- package/creators/app/files/babel.config.js +1 -18
- package/creators/app/files/tsconfig.json +0 -1
- package/creators/app/files/vue.config.js +6 -0
- package/creators/app/init +5 -5
- package/creators/pkg/files/.github/workflows/build-extension.yml +110 -0
- package/creators/pkg/files/tsconfig.json +0 -1
- package/creators/pkg/init +35 -4
- package/creators/pkg/pkg.package.json +3 -3
- package/creators/update/init +1 -1
- package/detail/constraints.gatekeeper.sh.constraint.vue +34 -17
- package/detail/fleet.cattle.io.clustergroup.vue +7 -1
- package/detail/fleet.cattle.io.gitrepo.vue +19 -11
- package/detail/harvesterhci.io.management.cluster.vue +3 -3
- package/detail/provisioning.cattle.io.cluster.vue +54 -12
- package/detail/workload/index.vue +3 -3
- package/dialog/AddClusterMemberDialog.vue +1 -1
- package/dialog/AddProjectMemberDialog.vue +2 -2
- package/dialog/AddonConfigConfirmationDialog.vue +27 -15
- package/dialog/DiagnosticTimingsDialog.vue +1 -1
- package/dialog/ForceMachineRemoveDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +18 -6
- package/dialog/RotateEncryptionKeyDialog.vue +1 -1
- package/dialog/SaveAsRKETemplateDialog.vue +1 -1
- package/dialog/ScaleMachineDownDialog.vue +1 -1
- package/edit/auth/github.vue +8 -8
- package/edit/auth/googleoauth.vue +5 -5
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +1 -1
- package/edit/auth/saml.vue +1 -1
- package/edit/cis.cattle.io.clusterscan.vue +1 -1
- package/edit/fleet.cattle.io.clustergroup.vue +6 -4
- package/edit/fleet.cattle.io.gitrepo.vue +32 -4
- package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
- package/edit/logging.banzaicloud.io.output/index.vue +18 -5
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +141 -6
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
- package/edit/management.cattle.io.setting.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
- package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
- package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
- package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
- package/edit/namespace.vue +14 -10
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +21 -4
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
- package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
- package/edit/provisioning.cattle.io.cluster/rke2.vue +344 -102
- package/edit/resources.cattle.io.backup.vue +1 -1
- package/edit/service.vue +1 -1
- package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
- package/edit/workload/__tests__/Job.test.ts +3 -1
- package/edit/workload/index.vue +8 -3
- package/edit/workload/mixins/workload.js +22 -7
- package/edit/workload/storage/Mount.vue +3 -3
- package/initialize/App.js +206 -0
- package/initialize/client.js +863 -0
- package/initialize/index.js +364 -0
- package/layouts/default.vue +7 -3
- package/layouts/standalone.vue +13 -0
- package/list/catalog.cattle.io.clusterrepo.vue +1 -0
- package/list/fleet.cattle.io.bundle.vue +6 -3
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
- package/list/fleet.cattle.io.gitrepo.vue +44 -5
- package/list/management.cattle.io.fleetworkspace.vue +45 -0
- package/list/node.vue +69 -16
- package/list/provisioning.cattle.io.cluster.vue +30 -1
- package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
- package/list/workload.vue +6 -4
- package/machine-config/azure.vue +97 -38
- package/middleware/authenticated.js +34 -0
- package/mixins/chart.js +101 -2
- package/mixins/fetch.client.js +95 -0
- package/mixins/fetch.server.js +73 -0
- package/mixins/labeled-form-element.ts +2 -2
- package/mixins/resource-fetch.js +2 -2
- package/models/apps.statefulset.js +28 -0
- package/models/cluster/node.js +23 -2
- package/models/cluster.x-k8s.io.machine.js +4 -2
- package/models/clusterroletemplatebinding.js +7 -0
- package/models/constraints.gatekeeper.sh.constraint.js +46 -0
- package/models/fleet.cattle.io.cluster.js +19 -10
- package/models/fleet.cattle.io.gitrepo.js +7 -2
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.fleetworkspace.js +12 -0
- package/models/management.cattle.io.gitreporestriction.js +5 -0
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
- package/models/pod.js +4 -0
- package/models/provisioning.cattle.io.cluster.js +7 -5
- package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
- package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
- package/package.json +13 -21
- package/pages/auth/setup.vue +2 -2
- package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
- package/pages/c/_cluster/apps/charts/chart.vue +4 -4
- package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
- package/pages/c/_cluster/apps/charts/install.vue +98 -102
- package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
- package/pages/c/_cluster/explorer/index.vue +29 -25
- package/pages/c/_cluster/explorer/tools/index.vue +8 -8
- package/pages/c/_cluster/fleet/index.vue +95 -34
- package/pages/c/_cluster/gatekeeper/index.vue +1 -1
- package/pages/c/_cluster/istio/index.vue +5 -5
- package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +7 -0
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
- package/pages/c/_cluster/uiplugins/index.vue +49 -17
- package/pages/diagnostic.vue +32 -25
- package/pages/home.vue +9 -4
- package/pages/index.vue +10 -1
- package/pages/rio/mesh.vue +1 -2
- package/pkg/tsconfig.json +0 -1
- package/plugins/clean-html-directive.js +34 -0
- package/plugins/dashboard-store/actions.js +32 -9
- package/plugins/dashboard-store/index.js +1 -1
- package/plugins/dashboard-store/mutations.js +5 -2
- package/plugins/dashboard-store/resource-class.js +8 -1
- package/plugins/plugin.js +0 -14
- package/plugins/portal-vue.js +4 -0
- package/plugins/steve/mutations.js +3 -2
- package/plugins/steve/steve-description-class.js +5 -1
- package/plugins/steve/subscribe.js +63 -54
- package/plugins/steve-create-worker.js +14 -0
- package/promptRemove/management.cattle.io.globalrole.vue +2 -2
- package/promptRemove/management.cattle.io.project.vue +2 -2
- package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
- package/promptRemove/pod.vue +1 -1
- package/public/index.html +65 -0
- package/rancher-components/components/Banner/Banner.test.ts +7 -1
- package/rancher-components/components/Banner/Banner.vue +2 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
- package/scripts/build-pkg.sh +1 -0
- package/scripts/clean +6 -0
- package/scripts/extension/bundle +58 -0
- package/scripts/extension/helmpatch +89 -0
- package/scripts/extension/publish +333 -0
- package/scripts/serve-pkgs +6 -2
- package/scripts/test-plugins-build.sh +4 -0
- package/store/__tests__/index.test.ts +110 -0
- package/store/index.js +145 -58
- package/store/type-map.js +6 -2
- package/tsconfig.default.json +36 -0
- package/tsconfig.json +23 -0
- package/types/rancher/index.d.ts +2 -0
- package/types/shell/index.d.ts +466 -320
- package/utils/__tests__/grafana.test.ts +44 -0
- package/utils/__tests__/string.test.ts +12 -0
- package/utils/auth.js +65 -0
- package/utils/axios.js +190 -0
- package/utils/cookie-universal-nuxt.js +10 -0
- package/utils/dom.js +15 -0
- package/utils/grafana.js +35 -16
- package/utils/monitoring.js +2 -1
- package/utils/nuxt.js +659 -0
- package/utils/position.js +5 -8
- package/utils/router.scrollBehavior.js +80 -0
- package/utils/select.js +1 -3
- package/utils/socket.js +1 -0
- package/utils/string.js +13 -0
- package/utils/time.js +9 -0
- package/vue.config.js +690 -0
- package/chart/rancher-alerting-drivers.vue +0 -53
- package/chart/rancher-gatekeeper.vue +0 -37
- package/creators/app/files/nuxt.config.js +0 -6
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
- package/nuxt.config.js +0 -798
- package/plugins/dashboard-store/extensions.js +0 -22
|
@@ -5,6 +5,7 @@ import { mapPref, PLUGIN_DEVELOPER } from '@shell/store/prefs';
|
|
|
5
5
|
import { sortBy } from '@shell/utils/sort';
|
|
6
6
|
import { allHash } from '@shell/utils/promise';
|
|
7
7
|
import { CATALOG, UI_PLUGIN, SERVICE } from '@shell/config/types';
|
|
8
|
+
import { getVersionData } from '@shell/config/version';
|
|
8
9
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
9
10
|
import { NAME as APP_PRODUCT } from '@shell/config/product/apps';
|
|
10
11
|
import ActionMenu from '@shell/components/ActionMenu';
|
|
@@ -23,6 +24,8 @@ import {
|
|
|
23
24
|
uiPluginAnnotation,
|
|
24
25
|
uiPluginHasAnnotation,
|
|
25
26
|
isSupportedChartVersion,
|
|
27
|
+
isChartVersionAvailableForInstall,
|
|
28
|
+
isChartVersionHigher,
|
|
26
29
|
UI_PLUGIN_NAMESPACE,
|
|
27
30
|
UI_PLUGIN_CHART_ANNOTATIONS
|
|
28
31
|
} from '@shell/config/uiplugins';
|
|
@@ -59,6 +62,7 @@ export default {
|
|
|
59
62
|
hasService: false,
|
|
60
63
|
defaultIcon: require('~shell/assets/images/generic-plugin.svg'),
|
|
61
64
|
reloadRequired: false,
|
|
65
|
+
rancherVersion: getVersionData()?.Version
|
|
62
66
|
};
|
|
63
67
|
},
|
|
64
68
|
|
|
@@ -183,27 +187,39 @@ export default {
|
|
|
183
187
|
// Label can be overridden by chart annotation
|
|
184
188
|
const label = uiPluginAnnotation(UI_PLUGIN_CHART_ANNOTATIONS.DISPLAY_NAME) || chart.chartNameDisplay;
|
|
185
189
|
const item = {
|
|
186
|
-
name:
|
|
190
|
+
name: chart.chartNameDisplay,
|
|
187
191
|
label,
|
|
188
|
-
description:
|
|
189
|
-
id:
|
|
190
|
-
versions:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER),
|
|
192
|
+
description: chart.chartDescription,
|
|
193
|
+
id: chart.id,
|
|
194
|
+
versions: [],
|
|
195
|
+
installed: false,
|
|
196
|
+
builtin: false,
|
|
197
|
+
experimental: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.EXPERIMENTAL, 'true'),
|
|
198
|
+
certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER),
|
|
196
199
|
};
|
|
197
200
|
|
|
198
|
-
this.latest = chart.versions[0];
|
|
199
201
|
item.versions = [...chart.versions];
|
|
200
202
|
item.chart = chart;
|
|
201
203
|
|
|
202
|
-
// Filter the versions
|
|
203
|
-
item.
|
|
204
|
+
// Filter the versions available to install (plugins-api version and current dashboard version)
|
|
205
|
+
item.installableVersions = item.versions.filter(version => isSupportedChartVersion(version) && isChartVersionAvailableForInstall(version, this.rancherVersion));
|
|
204
206
|
|
|
205
|
-
if
|
|
206
|
-
|
|
207
|
+
// add prop to version object if version is compatible with the current dashboard version
|
|
208
|
+
item.versions = item.versions.map(version => isChartVersionAvailableForInstall(version, this.rancherVersion, true));
|
|
209
|
+
|
|
210
|
+
const latestCompatible = item.installableVersions?.[0];
|
|
211
|
+
const latestNotCompatible = item.versions.find(version => !version.isCompatibleWithUi);
|
|
212
|
+
|
|
213
|
+
if (latestCompatible) {
|
|
214
|
+
item.displayVersion = latestCompatible.version;
|
|
215
|
+
item.icon = latestCompatible.icon;
|
|
216
|
+
} else {
|
|
217
|
+
item.displayVersion = item.versions?.[0]?.version;
|
|
218
|
+
item.icon = chart.icon || latestCompatible.annotations['catalog.cattle.io/ui-icon'];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (latestNotCompatible && item.installableVersions.length && isChartVersionHigher(latestNotCompatible.version, item.installableVersions?.[0].version)) {
|
|
222
|
+
item.incompatibleDisclaimer = this.t('plugins.incompatibleDisclaimer', { version: latestNotCompatible.version, rancherVersion: latestNotCompatible.requiredUiVersion }, true);
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
if (this.installing[item.name]) {
|
|
@@ -253,8 +269,8 @@ export default {
|
|
|
253
269
|
chart.installing = this.installing[chart.name];
|
|
254
270
|
|
|
255
271
|
// Check for upgrade
|
|
256
|
-
if (chart.
|
|
257
|
-
chart.upgrade = chart.
|
|
272
|
+
if (chart.installableVersions?.length && p.version !== chart.installableVersions?.[0]?.version) {
|
|
273
|
+
chart.upgrade = chart.installableVersions[0].version;
|
|
258
274
|
}
|
|
259
275
|
} else {
|
|
260
276
|
// No chart, so add a card for the plugin based on its Custom resource being present
|
|
@@ -619,6 +635,7 @@ export default {
|
|
|
619
635
|
:data-testid="`extension-card-${plugin.name}`"
|
|
620
636
|
@click="showPluginDetail(plugin)"
|
|
621
637
|
>
|
|
638
|
+
<!-- plugin icon -->
|
|
622
639
|
<div
|
|
623
640
|
class="plugin-icon"
|
|
624
641
|
:class="applyDarkModeBg"
|
|
@@ -636,7 +653,9 @@ export default {
|
|
|
636
653
|
class="icon plugin-icon-img"
|
|
637
654
|
>
|
|
638
655
|
</div>
|
|
656
|
+
<!-- plugin card -->
|
|
639
657
|
<div class="plugin-metadata">
|
|
658
|
+
<!-- plugin basic info -->
|
|
640
659
|
<div class="plugin-name">
|
|
641
660
|
{{ plugin.label }}
|
|
642
661
|
</div>
|
|
@@ -654,8 +673,13 @@ export default {
|
|
|
654
673
|
v-if="plugin.upgrade"
|
|
655
674
|
v-tooltip="t('plugins.upgradeAvailable')"
|
|
656
675
|
> -> {{ plugin.upgrade }}</span>
|
|
676
|
+
<p
|
|
677
|
+
v-if="plugin.incompatibleDisclaimer"
|
|
678
|
+
class="incompatible"
|
|
679
|
+
>{{ plugin.incompatibleDisclaimer }}</p>
|
|
657
680
|
</span>
|
|
658
681
|
</div>
|
|
682
|
+
<!-- plugin badges -->
|
|
659
683
|
<div
|
|
660
684
|
v-if="plugin.builtin"
|
|
661
685
|
class="plugin-badges"
|
|
@@ -682,6 +706,7 @@ export default {
|
|
|
682
706
|
</div>
|
|
683
707
|
</div>
|
|
684
708
|
<div class="plugin-spacer" />
|
|
709
|
+
<!-- plugin badges -->
|
|
685
710
|
<div class="plugin-actions">
|
|
686
711
|
<template v-if="plugin.error">
|
|
687
712
|
<div
|
|
@@ -691,6 +716,7 @@ export default {
|
|
|
691
716
|
<i class="icon icon-warning" />
|
|
692
717
|
</div>
|
|
693
718
|
</template>
|
|
719
|
+
<!-- plugin status -->
|
|
694
720
|
<div
|
|
695
721
|
v-if="plugin.helmError"
|
|
696
722
|
v-tooltip="t('plugins.helmError')"
|
|
@@ -713,6 +739,7 @@ export default {
|
|
|
713
739
|
{{ t('plugins.labels.uninstalling') }}
|
|
714
740
|
</div>
|
|
715
741
|
</div>
|
|
742
|
+
<!-- plugin buttons -->
|
|
716
743
|
<div
|
|
717
744
|
v-else-if="plugin.installed"
|
|
718
745
|
class="plugin-buttons"
|
|
@@ -734,7 +761,7 @@ export default {
|
|
|
734
761
|
{{ t('plugins.update.label') }}
|
|
735
762
|
</button>
|
|
736
763
|
<button
|
|
737
|
-
v-if="!plugin.upgrade && plugin.
|
|
764
|
+
v-if="!plugin.upgrade && plugin.installableVersions && plugin.installableVersions.length > 1"
|
|
738
765
|
class="btn role-secondary"
|
|
739
766
|
:data-testid="`extension-card-rollback-btn-${plugin.name}`"
|
|
740
767
|
@click="showInstallDialog(plugin, 'rollback', $event)"
|
|
@@ -942,6 +969,11 @@ export default {
|
|
|
942
969
|
height: 16px;
|
|
943
970
|
width: 16px;
|
|
944
971
|
}
|
|
972
|
+
|
|
973
|
+
.incompatible {
|
|
974
|
+
margin: 10px 0;
|
|
975
|
+
font-weight: bold;
|
|
976
|
+
}
|
|
945
977
|
}
|
|
946
978
|
|
|
947
979
|
.plugin-installing {
|
package/pages/diagnostic.vue
CHANGED
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
const clusterForCounts = filterHiddenLocalCluster(filterOnlyKubernetesClusters(readyClusters), this.$store);
|
|
19
19
|
const finalCounts = [];
|
|
20
20
|
const promises = [];
|
|
21
|
-
|
|
21
|
+
const topFifteenForResponseTime = [];
|
|
22
22
|
|
|
23
23
|
clusterForCounts.forEach((cluster, i) => {
|
|
24
24
|
// Necessary to retrieve the proper display name of the cluster
|
|
@@ -42,6 +42,7 @@ export default {
|
|
|
42
42
|
|
|
43
43
|
if (counts) {
|
|
44
44
|
const sanitizedCount = [];
|
|
45
|
+
let finalCount = [];
|
|
45
46
|
|
|
46
47
|
Object.keys(counts).forEach((key) => {
|
|
47
48
|
sanitizedCount[key] = counts[key].summary?.count;
|
|
@@ -53,20 +54,22 @@ export default {
|
|
|
53
54
|
|
|
54
55
|
const sortedCount = sortBy(sanitizedCount, 'count:desc');
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
finalCount = finalCount.concat(sortedCount);
|
|
58
|
+
finalCount = sortBy(finalCount, 'count:desc');
|
|
59
|
+
finalCount = finalCount.splice(0, 15);
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
finalCount.forEach((item, i) => {
|
|
62
|
+
finalCount[i].id = finalCounts[index].id;
|
|
63
|
+
finalCount[i].capiId = finalCounts[index].capiId;
|
|
63
64
|
});
|
|
64
65
|
|
|
66
|
+
topFifteenForResponseTime.push(finalCount);
|
|
67
|
+
|
|
65
68
|
finalCounts[index].counts = sortedCount;
|
|
66
69
|
}
|
|
67
70
|
});
|
|
68
71
|
|
|
69
|
-
this.
|
|
72
|
+
this.topFifteenForResponseTime = topFifteenForResponseTime;
|
|
70
73
|
this.finalCounts = finalCounts;
|
|
71
74
|
},
|
|
72
75
|
|
|
@@ -122,12 +125,12 @@ export default {
|
|
|
122
125
|
|
|
123
126
|
return {
|
|
124
127
|
systemInformation,
|
|
125
|
-
|
|
126
|
-
responseTimes:
|
|
127
|
-
finalCounts:
|
|
128
|
-
includeResponseTimes:
|
|
129
|
-
storeMapping:
|
|
130
|
-
latestLogs:
|
|
128
|
+
topFifteenForResponseTime: null,
|
|
129
|
+
responseTimes: null,
|
|
130
|
+
finalCounts: null,
|
|
131
|
+
includeResponseTimes: true,
|
|
132
|
+
storeMapping: this.$store?._modules?.root?.state,
|
|
133
|
+
latestLogs: console.logs // eslint-disable-line no-console
|
|
131
134
|
};
|
|
132
135
|
},
|
|
133
136
|
|
|
@@ -205,17 +208,21 @@ export default {
|
|
|
205
208
|
},
|
|
206
209
|
|
|
207
210
|
async gatherResponseTimes(btnCb) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
211
|
+
const promises = this.topFifteenForResponseTime.flatMap((cluster) => {
|
|
212
|
+
return cluster.map((item) => {
|
|
213
|
+
const t = Date.now();
|
|
214
|
+
|
|
215
|
+
return this.$store.dispatch('management/request', { url: `/k8s/clusters/${ item.capiId }/v1/${ item.resource }` })
|
|
216
|
+
.then(() => ({
|
|
217
|
+
outcome: 'success', item, durationMs: Date.now() - t
|
|
218
|
+
}))
|
|
219
|
+
.catch(() => ({
|
|
220
|
+
outcome: 'error', item, durationMs: Date.now() - t
|
|
221
|
+
}));
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
return await Promise.all(promises).then((responseTimes) => {
|
|
219
226
|
this.responseTimes = responseTimes;
|
|
220
227
|
this.setResourceResponseTiming(responseTimes);
|
|
221
228
|
btnCb(true);
|
package/pages/home.vue
CHANGED
|
@@ -38,8 +38,13 @@ export default {
|
|
|
38
38
|
mixins: [PageHeaderActions],
|
|
39
39
|
|
|
40
40
|
fetch() {
|
|
41
|
-
this.$store.
|
|
42
|
-
|
|
41
|
+
if ( this.$store.getters['management/schemaFor'](CAPI.RANCHER_CLUSTER) ) {
|
|
42
|
+
this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if ( this.$store.getters['management/schemaFor'](MANAGEMENT.CLUSTER) ) {
|
|
46
|
+
this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER });
|
|
47
|
+
}
|
|
43
48
|
|
|
44
49
|
if ( this.$store.getters['management/canList'](CAPI.MACHINE) ) {
|
|
45
50
|
this.$store.dispatch('management/findAll', { type: CAPI.MACHINE });
|
|
@@ -307,7 +312,7 @@ export default {
|
|
|
307
312
|
<a
|
|
308
313
|
class="hand"
|
|
309
314
|
@click.prevent.stop="showWhatsNew"
|
|
310
|
-
><span v-html="t('landing.whatsNewLink')" /></a>
|
|
315
|
+
><span v-clean-html="t('landing.whatsNewLink')" /></a>
|
|
311
316
|
</Banner>
|
|
312
317
|
</div>
|
|
313
318
|
</div>
|
|
@@ -330,7 +335,7 @@ export default {
|
|
|
330
335
|
<a
|
|
331
336
|
class="hand mr-20"
|
|
332
337
|
@click.prevent.stop="showUserPrefs"
|
|
333
|
-
><span v-html="t('landing.landingPrefs.userPrefs')" /></a>
|
|
338
|
+
><span v-clean-html="t('landing.landingPrefs.userPrefs')" /></a>
|
|
334
339
|
</Banner>
|
|
335
340
|
</div>
|
|
336
341
|
</div>
|
package/pages/index.vue
CHANGED
|
@@ -7,7 +7,9 @@ const validRoute = (route, router) => {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
|
-
middleware({
|
|
10
|
+
middleware({
|
|
11
|
+
redirect, store, app, route
|
|
12
|
+
} ) {
|
|
11
13
|
const seenWhatsNew = store.getters['prefs/get'](SEEN_WHATS_NEW);
|
|
12
14
|
const versionInfo = getVersionInfo(store);
|
|
13
15
|
const isSingleProduct = store.getters['isSingleProduct'];
|
|
@@ -19,6 +21,13 @@ export default {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const afterLoginRouteObject = store.getters['prefs/afterLoginRoute'];
|
|
24
|
+
const targetRoute = app.router.resolve(afterLoginRouteObject);
|
|
25
|
+
|
|
26
|
+
// If target route is /, then we will loop with endless redirect - so detect that here and
|
|
27
|
+
// redirect to /home, which is what we would do below, if there was no `afterLoginRouteObject`
|
|
28
|
+
if (targetRoute?.route?.fullPath === '/') {
|
|
29
|
+
return redirect(dashboardHome);
|
|
30
|
+
}
|
|
22
31
|
|
|
23
32
|
// Confirm this is a valid route (it could have come from an uninstalled plugin)
|
|
24
33
|
if (validRoute(afterLoginRouteObject, app.router)) {
|
package/pages/rio/mesh.vue
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import $ from 'jquery';
|
|
3
2
|
import { escapeHtml } from '@shell/utils/string';
|
|
4
3
|
|
|
5
4
|
const RADIUS = 5;
|
|
@@ -399,7 +398,7 @@ export default {
|
|
|
399
398
|
},
|
|
400
399
|
|
|
401
400
|
clicked(event) {
|
|
402
|
-
const path =
|
|
401
|
+
const path = event.target.closest('.edgePath');
|
|
403
402
|
|
|
404
403
|
console.log(path); // eslint-disable-line no-console
|
|
405
404
|
}
|
package/pkg/tsconfig.json
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
import DOMPurify from 'dompurify';
|
|
3
|
+
|
|
4
|
+
const ALLOWED_TAGS = [
|
|
5
|
+
'code',
|
|
6
|
+
'li',
|
|
7
|
+
'a',
|
|
8
|
+
'p',
|
|
9
|
+
'b',
|
|
10
|
+
'br',
|
|
11
|
+
'ul',
|
|
12
|
+
'pre',
|
|
13
|
+
'span',
|
|
14
|
+
'div',
|
|
15
|
+
'i',
|
|
16
|
+
'em',
|
|
17
|
+
'strong',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const purifyHTML = value => DOMPurify.sanitize(value, { ALLOWED_TAGS });
|
|
21
|
+
|
|
22
|
+
export const cleanHtmlDirective = {
|
|
23
|
+
inserted(el, binding) {
|
|
24
|
+
el.innerHTML = purifyHTML(binding.value);
|
|
25
|
+
},
|
|
26
|
+
componentUpdated(el, binding) {
|
|
27
|
+
el.innerHTML = purifyHTML(binding.value);
|
|
28
|
+
},
|
|
29
|
+
unbind(el) {
|
|
30
|
+
el.innerHTML = '';
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
Vue.directive('clean-html', cleanHtmlDirective);
|
|
@@ -53,8 +53,9 @@ export async function loadSchemas(ctx, watch = true) {
|
|
|
53
53
|
|
|
54
54
|
commit('loadAll', {
|
|
55
55
|
ctx,
|
|
56
|
-
type:
|
|
57
|
-
data:
|
|
56
|
+
type: SCHEMA,
|
|
57
|
+
data: res.data,
|
|
58
|
+
revision: res.revision
|
|
58
59
|
});
|
|
59
60
|
|
|
60
61
|
if ( watch !== false ) {
|
|
@@ -148,11 +149,14 @@ export default {
|
|
|
148
149
|
commit('registerType', type);
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
// No need to request the resources if we have them already
|
|
151
153
|
if ( opt.force !== true && (getters['haveAll'](type) || getters['haveAllNamespace'](type, opt.namespaced))) {
|
|
152
154
|
const args = {
|
|
153
155
|
type,
|
|
154
156
|
revision: '',
|
|
155
|
-
|
|
157
|
+
// watchNamespace - used sometimes when we haven't fetched the results of a single namespace
|
|
158
|
+
// namespaced - used when we have fetched the result of a single namespace (see https://github.com/rancher/dashboard/pull/7329/files)
|
|
159
|
+
namespace: opt.watchNamespace || opt.namespaced
|
|
156
160
|
};
|
|
157
161
|
|
|
158
162
|
if (opt.watch !== false ) {
|
|
@@ -304,17 +308,21 @@ export default {
|
|
|
304
308
|
ctx,
|
|
305
309
|
type,
|
|
306
310
|
data: out.data,
|
|
311
|
+
revision: out.revision,
|
|
307
312
|
skipHaveAll,
|
|
308
313
|
namespace: opt.namespaced,
|
|
309
314
|
});
|
|
310
315
|
}
|
|
311
316
|
}
|
|
312
317
|
|
|
318
|
+
// ToDo: SM if we start a "bigger" watch (such as watch without a namespace vs a watch with a namespace), we should stop the stop the "smaller" watch so we don't have duplicate events coming back
|
|
313
319
|
if ( opt.watch !== false ) {
|
|
314
320
|
dispatch('watch', {
|
|
315
321
|
type,
|
|
316
322
|
revision: out.revision,
|
|
317
|
-
namespace: opt.watchNamespace
|
|
323
|
+
namespace: opt.watchNamespace || opt.namespaced, // it could be either apparently
|
|
324
|
+
// ToDo: SM namespaced is sometimes a boolean and sometimes a string, I don't see it as especially broken but we should refactor that in the future
|
|
325
|
+
force: opt.forceWatch === true,
|
|
318
326
|
});
|
|
319
327
|
}
|
|
320
328
|
|
|
@@ -369,15 +377,17 @@ export default {
|
|
|
369
377
|
commit('loadSelector', {
|
|
370
378
|
ctx,
|
|
371
379
|
type,
|
|
372
|
-
entries:
|
|
373
|
-
selector
|
|
380
|
+
entries: res.data,
|
|
381
|
+
selector,
|
|
382
|
+
revision: res.revision,
|
|
374
383
|
});
|
|
375
384
|
|
|
376
385
|
if ( opt.watch !== false ) {
|
|
377
386
|
dispatch('watch', {
|
|
378
387
|
type,
|
|
379
388
|
selector,
|
|
380
|
-
revision: res.revision
|
|
389
|
+
revision: res.revision,
|
|
390
|
+
force: opt.forceWatch === true,
|
|
381
391
|
});
|
|
382
392
|
}
|
|
383
393
|
|
|
@@ -394,6 +404,12 @@ export default {
|
|
|
394
404
|
// url: Use this specific URL instead of looking up the URL for the type/id. This should only be used for bootstrapping schemas on startup.
|
|
395
405
|
// @TODO depaginate: If the response is paginated, retrieve all the pages. (default: true)
|
|
396
406
|
async find(ctx, { type, id, opt }) {
|
|
407
|
+
if (!id) {
|
|
408
|
+
console.error('Attempting to find a resource with no id', type, id); // eslint-disable-line no-console
|
|
409
|
+
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
|
|
397
413
|
const { getters, dispatch } = ctx;
|
|
398
414
|
|
|
399
415
|
opt = opt || {};
|
|
@@ -459,6 +475,11 @@ export default {
|
|
|
459
475
|
commit('registerType', type);
|
|
460
476
|
}
|
|
461
477
|
}
|
|
478
|
+
// Inject special fields for indexing schemas
|
|
479
|
+
if ( type === SCHEMA ) {
|
|
480
|
+
addSchemaIndexFields(data);
|
|
481
|
+
}
|
|
482
|
+
|
|
462
483
|
const keyField = getters.keyFieldForType(type);
|
|
463
484
|
const id = data?.[keyField] || existing?.[keyField];
|
|
464
485
|
|
|
@@ -531,8 +552,10 @@ export default {
|
|
|
531
552
|
|
|
532
553
|
// Forget a type in the store
|
|
533
554
|
// Remove all entries for that type and stop watching it
|
|
534
|
-
forgetType({ commit,
|
|
535
|
-
|
|
555
|
+
forgetType({ commit, dispatch, state }, type) {
|
|
556
|
+
state.started
|
|
557
|
+
.filter(entry => entry.type === type)
|
|
558
|
+
.forEach(entry => dispatch('unwatch', entry));
|
|
536
559
|
|
|
537
560
|
commit('forgetType', type);
|
|
538
561
|
},
|
|
@@ -261,7 +261,8 @@ export function loadAll(state, {
|
|
|
261
261
|
data,
|
|
262
262
|
ctx,
|
|
263
263
|
skipHaveAll,
|
|
264
|
-
namespace
|
|
264
|
+
namespace,
|
|
265
|
+
revision
|
|
265
266
|
}) {
|
|
266
267
|
const { getters } = ctx;
|
|
267
268
|
|
|
@@ -283,6 +284,7 @@ export function loadAll(state, {
|
|
|
283
284
|
|
|
284
285
|
clear(cache.list);
|
|
285
286
|
cache.map.clear();
|
|
287
|
+
cache.revision = revision || 0;
|
|
286
288
|
cache.generation++;
|
|
287
289
|
|
|
288
290
|
addObjects(cache.list, proxies);
|
|
@@ -320,7 +322,7 @@ export default {
|
|
|
320
322
|
},
|
|
321
323
|
|
|
322
324
|
loadSelector(state, {
|
|
323
|
-
type, entries, ctx, selector
|
|
325
|
+
type, entries, ctx, selector, revision
|
|
324
326
|
}) {
|
|
325
327
|
const cache = registerType(state, type);
|
|
326
328
|
|
|
@@ -329,6 +331,7 @@ export default {
|
|
|
329
331
|
}
|
|
330
332
|
|
|
331
333
|
cache.haveSelector[selector] = true;
|
|
334
|
+
cache.revision = revision || 0;
|
|
332
335
|
},
|
|
333
336
|
|
|
334
337
|
loadAll,
|
|
@@ -1110,7 +1110,7 @@ export default class Resource {
|
|
|
1110
1110
|
}
|
|
1111
1111
|
|
|
1112
1112
|
// @TODO remove this once the API maps steve _type <-> k8s type in both directions
|
|
1113
|
-
opt.data = { ...this };
|
|
1113
|
+
opt.data = this.toSave() || { ...this };
|
|
1114
1114
|
|
|
1115
1115
|
if (opt?.data._type) {
|
|
1116
1116
|
opt.data.type = opt.data._type;
|
|
@@ -1884,6 +1884,13 @@ export default class Resource {
|
|
|
1884
1884
|
return out;
|
|
1885
1885
|
}
|
|
1886
1886
|
|
|
1887
|
+
/**
|
|
1888
|
+
* Allow models to override the object that is sent when saving this resource
|
|
1889
|
+
*/
|
|
1890
|
+
toSave() {
|
|
1891
|
+
return undefined;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1887
1894
|
get creationTimestamp() {
|
|
1888
1895
|
return this.metadata?.creationTimestamp;
|
|
1889
1896
|
}
|
package/plugins/plugin.js
CHANGED
|
@@ -2,23 +2,9 @@
|
|
|
2
2
|
import { allHashSettled } from '@shell/utils/promise';
|
|
3
3
|
import { shouldNotLoadPlugin, UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
|
|
4
4
|
|
|
5
|
-
const META_NAME_PREFIX = 'app-autoload-';
|
|
6
|
-
|
|
7
5
|
export default async function(context) {
|
|
8
|
-
// UI Plugins declared in the HTML head
|
|
9
|
-
const meta = context.app?.head?.meta || [];
|
|
10
6
|
const hash = {};
|
|
11
7
|
|
|
12
|
-
meta.forEach((m) => {
|
|
13
|
-
const metaName = m.name || '';
|
|
14
|
-
|
|
15
|
-
if (metaName.indexOf(META_NAME_PREFIX) === 0) {
|
|
16
|
-
const name = metaName.substr(META_NAME_PREFIX.length);
|
|
17
|
-
|
|
18
|
-
hash[name] = context.$plugin.loadAsync(name, m.content);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
8
|
// Provide a mechanism to load the UI without the plugins loaded - in case there is a problem
|
|
23
9
|
let loadPlugins = true;
|
|
24
10
|
|
|
@@ -121,7 +121,8 @@ export default {
|
|
|
121
121
|
data,
|
|
122
122
|
ctx,
|
|
123
123
|
skipHaveAll,
|
|
124
|
-
namespace
|
|
124
|
+
namespace,
|
|
125
|
+
revision
|
|
125
126
|
}) {
|
|
126
127
|
// Performance testing in dev and when env var is set
|
|
127
128
|
if (process.env.dev && !!process.env.perfTest) {
|
|
@@ -129,7 +130,7 @@ export default {
|
|
|
129
130
|
}
|
|
130
131
|
|
|
131
132
|
const proxies = loadAll(state, {
|
|
132
|
-
type, data, ctx, skipHaveAll, namespace
|
|
133
|
+
type, data, ctx, skipHaveAll, namespace, revision
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
// If we loaded a set of pods, then update the podsByNamespace cache
|
|
@@ -20,7 +20,7 @@ export default class SteveDescriptionModel extends SteveModel {
|
|
|
20
20
|
this._description = value;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// Ensure when we clone that we preserve the
|
|
23
|
+
// Ensure when we clone that we preserve the description
|
|
24
24
|
toJSON() {
|
|
25
25
|
const data = super.toJSON();
|
|
26
26
|
|
|
@@ -29,4 +29,8 @@ export default class SteveDescriptionModel extends SteveModel {
|
|
|
29
29
|
|
|
30
30
|
return data;
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
toSave() {
|
|
34
|
+
return this.toJSON();
|
|
35
|
+
}
|
|
32
36
|
}
|